Archive for the ‘en-US’ Category
[ScalaDays 2019] Preserving Privacy with Scala
At ScalaDays Lausanne 2019, Manohar Jonnalagedda and Jakob Odersky, researchers turned industry innovators, unveiled a Scala-powered approach to secure multi-party computation (MPC) at EPFL’s 10th anniversary conference. Their talk, moments before lunch, captivated attendees with a protocol to average salaries without revealing individual data, sparking curiosity about privacy-preserving applications. Manohar and Jakob, from Inpher, detailed a compiler transforming high-level code into secure, distributed computations, addressing real-world challenges like GDPR-compliant banking and satellite collision detection, earning applause and probing questions on security and scalability.
A Privacy-Preserving Protocol
Manohar opened with a relatable scenario: wanting to compare salaries with Jakob without disclosing personal figures. Their solution, a privacy-preserving protocol, lets three parties—Manohar, Jakob, and their CTO Dmitar—compute an average securely. Each generates three random numbers summing to zero, sharing them such that each party holds a unique view of partial sums. In Scala, this is modeled with a SecretValue type for private integers and a SharedNumber list, accessible only by the corresponding party. Each sums their shares, publishes the result, and the final sum reveals the average without exposing individual salaries. This protocol, using random shares, ensures no single party can deduce another’s data unless all communications are intercepted, balancing simplicity and security.
Secure Multi-Party Computation
Jakob explained MPC as a cryptographic subfield enabling joint function computation without revealing private inputs. The salary example used addition, but MPC supports multiplication via Beaver triplets, precomputed by a trusted dealer for efficiency. With addition and multiplication, MPC handles polynomials, enabling linear and logistic regression or exponential approximations via Taylor polynomials. Manohar highlighted Scala’s role in modeling these operations, with functions for element-wise addition and revealing sums. The protocol achieves information-theoretic security for integers, where masked values are indistinguishable, but floating-point numbers require computational security due to distribution challenges. This flexibility makes MPC suitable for complex computations, from machine learning to statistical analysis, all while preserving privacy.
Real-World Applications
MPC shines in domains where data sensitivity or legal constraints, like GDPR, restrict sharing. Manohar cited ING, a bank building credit-scoring models across European countries without moving user data across borders, complying with GDPR. Another compelling case involved satellite operators—American, Russian, or Chinese—secretly computing collision risks to avoid incidents like the 2009 Iridium-Cosmos crash, which threatened the International Space Station. Jakob emphasized that Inpher’s XOR platform, legally vetted by Baker McKenzie, ensures GDPR compliance by keeping data at its source. These use cases, from finance to defense, underscore MPC’s value in enabling secure collaboration, with Scala providing a robust, type-safe foundation for protocol implementation.
Building a Compiler for MPC
To scale MPC beyond simple embeddings, Manohar and Jakob’s team developed a compiler at Inpher, targeting a high-level language resembling Python or Scala for data scientists. This compiler transforms linear algebra-style code into low-level primitives for distributed execution across parties’ virtual machines, verified to prevent data leaks. It performs static analysis to optimize memory and communication, inferring masking parameters to minimize computational overhead. For example, multiplying masked floating-point numbers risks format explosion, so the compiler uses fixed-point representations and statistical bounds to maintain efficiency. The output, resembling assembly for MPC engines, manages memory allocation and propagates data dimensions. While currently MPC-focused, the compiler’s design could integrate other privacy techniques, offering a versatile platform for secure computation.
Links:
Hashtags: #ScalaDays2019 #Scala #Privacy #MPC
[DevoxxPL2019] Kubernetes Essentials: Deploying and Managing Containerized Workloads
Lecturer
Pascal Naber, an Azure-focused architect and Microsoft MVP, leverages his expertise in cloud technologies to guide enterprises through containerization journeys. Previously with Xpirit, he now operates via Tech Driven, delivering consultations on scalable infrastructures and orchestration platforms.
Abstract
This discourse probes the foundational elements of Kubernetes as a premier tool for orchestrating Docker containers in operational settings. It dissects critical abstractions such as pods, services, deployments, secrets, namespaces, and ingress controllers, while scrutinizing approaches for seamless scaling, uninterrupted updates, and resource optimization. Utilizing demonstrative scenarios, it appraises the orchestration’s capacity to ensure resilience and availability, contemplating its ramifications for cloud-integrated architectures and future infrastructure paradigms.
Foundations of Container Orchestration: Addressing Deployment Challenges
The proliferation of container technologies, spearheaded by Docker, has fundamentally altered how applications are packaged and executed, promising uniformity across diverse environments. Pascal commences by delineating the limitations of rudimentary container deployments, where a basic frontend-backend duo on a solitary server suffices initially but falters under growth pressures. When traffic surges, a single point of failure emerges; server downtime halts operations entirely, and manual scaling—adding instances and configuring load balancers—proves cumbersome and error-prone.
Kubernetes emerges as a sophisticated remedy, automating the intricacies of container management to foster reliability and elasticity. Originating from Google’s internal systems and open-sourced in 2014, it has ascended as the de facto standard, supported by major cloud providers through managed offerings like Azure Kubernetes Service (AKS). This abstraction layer permits declarative specifications of desired states, with the orchestrator reconciling discrepancies autonomously.
In essence, Kubernetes clusters comprise master nodes overseeing the control plane—responsible for scheduling, scaling, and health monitoring—and worker nodes executing the actual workloads. Masters maintain the etcd store for cluster state, while workers host pods, the minimal schedulable units encapsulating one or more containers. This architecture ensures fault tolerance; should a worker fail, Kubernetes reschedules pods elsewhere, preserving service continuity.
Analytically, this model transcends mere automation, embedding principles of resilience engineering. By distributing pods across nodes, it mitigates risks from hardware failures or resource contention. However, initial setups demand comprehension of networking overlays, like Calico or Flannel, to facilitate inter-pod communication. The broader context involves shifting from monolithic VMs to granular containers, reducing overhead and accelerating iterations in DevOps pipelines.
The ramifications extend to operational paradigms: teams transition from imperative commands to YAML manifests, promoting version-controlled infrastructure as code. Yet, this necessitates vigilance against misconfigurations, such as inadequate resource requests, which could lead to eviction cascades under pressure.
Key Abstractions and Configuration: Crafting Robust Applications
At Kubernetes’ core are abstractions that decouple application logic from underlying infrastructure, enabling portable, self-healing systems. Pascal elucidates pods as co-located containers sharing storage and network namespaces, ideal for tightly coupled components like a web server and logging sidecar. Pods are ephemeral; deployments manage their lifecycle, specifying replicas for redundancy.
Deployments facilitate rolling updates, progressively replacing pods while monitoring readiness via probes—liveness for restarts on failure, readiness for traffic eligibility. For illustration, a deployment YAML might define:
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
replicas: 2
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: backend-image:v1
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /health
port: 8080
readinessProbe:
httpGet:
path: /ready
port: 8080
This ensures only healthy pods receive traffic, averting partial failures.
Services provide stable IPs and DNS for pods, abstracting volatility. ClusterIP suits internal access, NodePort exposes via host ports, and LoadBalancer integrates cloud balancers for external reach. Secrets inject sensitive data, like API keys, as environment variables or volumes, bolstering security.
Namespaces partition clusters logically, aiding multi-tenancy by isolating resources. Ingress controllers, such as NGINX, consolidate routing, directing traffic based on paths or hosts, often with TLS termination.
Methodologically, tools like Helm chart applications, packaging manifests for reusable deployments. Pascal’s approach: start with local Minikube for prototyping, then migrate to managed services for production.
Analytically, these constructs promote modularity, but interdependencies—e.g., service discovery—require careful design to avoid latency. Implications: accelerated delivery cycles, though debugging distributed traces demands tools like Jaeger.
Scaling Mechanisms and Ecosystem Synergies: Achieving Elasticity
Kubernetes excels in dynamic scaling, adjusting replicas via Horizontal Pod Autoscaler based on CPU/memory metrics. Cluster autoscalers provision nodes on demand, integrating with cloud APIs for elasticity.
Pascal explores serverless extensions like Azure Container Instances, executing containers sans VM management, though capped at resources. Virtual nodes hybridize, offloading bursts to serverless while retaining cluster control.
The ecosystem amplifies: Cert-Manager automates certificates, securing ingress. Service meshes like Istio add traffic management and observability.
Methodologically, monitoring with Prometheus and Grafana informs scaling policies, preventing over-provisioning. Demonstrations via Azure CLI underscore rapid cluster creation, emphasizing managed masters for reduced toil.
Analytically, this decouples scaling from application code, but demands metric tuning to avoid thrashing. In hybrid setups, portability shines, though vendor extensions risk lock-in.
Consequences: cost savings through utilization, but skill gaps in YAML and kubectl can hinder adoption. Kubernetes thus redefines operations, prioritizing automation over manual intervention.
Strategic Implications and Emerging Horizons: Toward Infrastructure Abstraction
Kubernetes’ declarative ethos aligns with infrastructure as code, enabling GitOps workflows where changes trigger reconciliations. Pascal foresees a paradigm where platforms recede, with focus on business logic.
Emerging: service meshes enhance security via mTLS, while operators automate custom resources. Serverless Kubernetes abstracts nodes entirely, as in Azure’s virtual nodes.
In strategic terms, it supports microservices but cautions against granularity without necessity, as overhead accumulates. Implications: organizational shifts toward platform teams, though complexity necessitates training.
Ultimately, Kubernetes empowers resilient architectures, evolving from container runner to ecosystem enabler, poised for serverless convergence.
Links:
[DotCSS2018] DotCSS 2018: Hugues Tennier – Essential Practices for Inclusive Web Experiences
Hugues Tennier, a dedicated advocate for equitable digital interfaces, delivered a succinct yet potent guide at DotCSS 2018 on elevating site usability through foundational accessibility tenets. With a focus on subtle yet seismic adjustments, he empowers creators to craft environments where diverse users thrive, from those with visual impairments to casual browsers under duress. Tennier’s framework underscores that inclusivity is not an addendum but the bedrock of resonant design.
Enhancing Visibility and Scalability
Tennier commences with color contrast, a linchpin for low-vision individuals or those navigating bright externalities. He recommends ratios surpassing WCAG benchmarks, verifiable via Chrome DevTools’ color picker—where hues above a stark threshold signal inaccessibility. This vigilance ensures content pierces veils of glare or haze, democratizing comprehension.
Pivotally, he champions resizable text, countering the fallacy of pixel-bound rigidity. Relative units like em or rem scale harmoniously with user preferences, accommodating 200% zooms sans distortion. A “Buy Now” button exemplifies: pixelated padding contracts uncomfortably at magnification, whereas rem fonts paired with em margins expand proportionally, preserving tap targets and legibility. Heights, too, warrant caution; fixed values invite overflow, but fluid metrics foster seamless growth.
These maneuvers, Tennier asserts, transcend compliance—they cultivate empathy, envisioning interfaces that adapt to life’s variances rather than impose uniformity.
Structuring Semantics and Interaction Clarity
Semantic HTML forms the next pillar, streamlining navigation for screen reader devotees via logical heading hierarchies. Sequential H1 through H6 milestones guide users briskly, averting disorientation amid skipped strata.
Visible focus indicators reclaim agency for keyboard navigators, whose tab traversals demand luminous cues. Dismissing default outlines is permissible, Tennier concedes, provided substitutes—vibrant borders or glows—affirm position without aesthetic compromise.
Finally, discerning links from buttons averts interpretive pitfalls: anchors herald navigational leaps, intoned as such by assistive tech, while buttons signal actions like submissions, primed for Enter or Space invocations. Divs, bereft of innate semantics, falter in announcements, underscoring the peril of repurposing for interactivity.
Tennier encapsulates these as duty-bound refinements—contrast, scalability, semantics, focus, and apt elements—that transmute exclusionary hurdles into welcoming pathways. In weaving accessibility into the warp and weft of creation, we honor the web’s inclusive ethos.
Links:
[DevoxxPL2019] Refining Functional-Style Java Programming: Insights and Recommendations
Lecturer
Brian Vermeer works as a Staff Developer Advocate at Snyk, emphasizing security in software development, and is recognized as a Java Champion. He co-leads the Utrecht Java User Group, promoting community-driven learning on Java technologies, and draws from extensive consulting experience to address practical coding challenges.
Abstract
This investigation addresses prevalent missteps in adopting functional-style programming in Java, advocating for refined techniques to bolster code clarity, robustness, and performance. It covers lambda simplicity, stream usage, immutability, optional handling, and exception strategies, analyzing approaches and their effects on development practices.
Simplifying Lambda Expressions: Fostering Code Clarity
The advent of functional elements in Java 8 marked a paradigm shift, yet Brian observes that developers, accustomed to imperative patterns, often overload lambdas with intricate logic, akin to overenthusiastic application of novel tools. This results in diminished legibility, countering the intent of concise, expressive code.
For a basic uppercase conversion on a list of strings, a straightforward lambda suffices, but embedding controls like conditionals or error handling expands it unnecessarily. Brian recommends extraction to dedicated methods, leveraging references for brevity.
By naming methods descriptively, the code gains self-documentation, easing comprehension. Contextually, this stems from transitional habits where new features are forced into unsuitable contexts. Analytically, concise lambdas uphold functional ideals, minimizing side effects and enhancing modularity. The outcomes promote sustainable codebases, where teams can iterate swiftly without deciphering dense blocks, ultimately streamlining collaboration in enterprise settings.
Effective Stream Utilization and Embracing Immutability: Safeguarding Integrity
Streams represent lazy computational pipelines, not persistent structures, and Brian stresses caution in their return or reuse to avoid unpredictable behavior. Returning streams risks unknown consumption states, potentially causing exceptions on reuse.
Preferring collections as defaults ensures stability, reserving streams for vast data where laziness conserves resources. Immutability complements this, clashing with functional tenets of state avoidance. Mutable objects yield inconsistent results, defying expectations of repeatability.
Brian suggests immutable defaults, profiling for optimizations only when necessary. Methodologically, this involves designing pure functions, free from alterations. Analytically, it aligns with declarative paradigms, where outputs depend solely on inputs. Consequences include fortified concurrency, as immutable data obviates synchronization, facilitating parallel processing in modern applications.
Mastering Optionals and Exception Wrapping: Directing Program Flow
Optionals avert null-related issues, but Brian highlights pitfalls in alternatives like orElse, which executes unconditionally, risking unintended effects. Suppliers via orElseGet defer computation, ensuring execution only when needed.
This precision controls pathways, preventing redundancies such as duplicate database entries. For exceptions in lambdas, wrapping checked ones to runtime variants is common but halts streams prematurely. Brian proposes custom wrappers or Either types to encapsulate outcomes, allowing full evaluation.
Using libraries like Vavr’s Try captures success or failure, empowering recovery. Methodologically, treat exceptions as data for managed responses. Analytically, this integrates error handling into functional flows, preserving composability. Outcomes enhance resilience, enabling sophisticated error strategies like retries, vital for reliable services in distributed architectures.
Security and Optimization in Functional Java: Wider Considerations
Though security isn’t the focus, Brian’s guidelines intersect by favoring immutability, which limits manipulation risks. Performance benefits from judicious laziness, avoiding intermediate assignments that tempt misuse.
In team dynamics, these practices underscore professionalism, trusting expertise over hasty implementations. Analytically, they elevate code quality, balancing innovation with accountability. The broader effects cultivate mature ecosystems, where functional Java supports scalable, secure solutions in evolving technological landscapes.
Links:
[KotlinConf2019] Building Progressive Web Apps in Kotlin: A New Frontier with Erik Hellman
The landscape of web development has traditionally been dominated by JavaScript and its ecosystem of tools and frameworks. However, with Kotlin’s growing versatility, particularly its Kotlin/JS capabilities, new avenues are opening up for developers who prefer Kotlin’s syntax and features. Erik Hellman, an experienced software consultant with a deep background in various programming languages, explored this exciting intersection at KotlinConf 2019. His session, “Building Progressive Web Apps in Kotlin,” introduced how Kotlin, combined with its JavaScript support, could be used to create modern web applications, also known as Progressive Web Apps (PWAs).
Erik Hellman’s talk aimed to show developers how they could leverage their Kotlin knowledge to build PWAs, potentially using popular JavaScript frameworks like React, Vue.js, or LitElement through Kotlin wrappers or directly with Kotlin/JS. This approach offers an alternative for those who find Kotlin more aligned with their development style than TypeScript or plain JavaScript, or for teams looking to unify their technology stack around Kotlin.
Kotlin/JS: Bridging Kotlin to the Web
At the heart of building web applications with Kotlin is Kotlin/JS, which allows Kotlin code to be compiled (or “transpiled”) into JavaScript. Erik Hellman explained the fundamentals of Kotlin/JS, including how it maps Kotlin concepts to their JavaScript equivalents and enables interoperability with existing JavaScript libraries and browser APIs. This capability is crucial, as it allows Kotlin developers to tap into the vast JavaScript ecosystem while writing code in a language they are comfortable and productive with.
The session would have covered how to set up a Kotlin/JS project, manage dependencies, and structure code for web development. Erik might have also discussed the benefits of using Kotlin for web development, such as its strong type system, null safety, and conciseness, which can lead to more robust and maintainable web applications compared to traditional JavaScript development. The focus was on providing a pathway for Kotlin enthusiasts to extend their skills into the PWA domain.
Progressive Web Apps: Enhancing the Web Experience
Progressive Web Apps (PWAs) represent an evolution of web applications, aiming to provide a user experience similar to native mobile apps. Key features of PWAs include offline capabilities (through service workers), installability on user devices, push notifications, and fast performance. Erik Hellman’s talk would have explored how these PWA characteristics can be implemented using Kotlin/JS.
A significant part of building PWAs involves working with service workers for caching and offline support, and web app manifests for installability. Erik demonstrated how to write service worker logic in Kotlin and manage the manifest file within a Kotlin/JS project. He might have also touched upon techniques for optimizing performance and ensuring a smooth user experience, which are critical aspects of successful PWAs. The overall goal was to equip Kotlin developers with the knowledge to build modern, engaging web experiences that leverage the latest web platform features.
Current State and Future Promise
During his 2019 presentation, Erik Hellman acknowledged that while Kotlin/JS was powerful, the tooling and ecosystem were still maturing, particularly around areas like code splitting for service workers. He noted that finding help and up-to-date information sometimes required tapping into the Kotlin community, such as the official Slack channel.
Despite these challenges, he conveyed a sense of optimism, stating that Kotlin/JS looked “really really promising” as an alternative for web development, especially for projects where Kotlin was already in use for other components (like backend or mobile). He suggested that for many use cases, Kotlin/JS was already a viable option. His talk concluded by pointing towards the continued development and improvement of Kotlin/JS, anticipating it would become an even more compelling choice for building PWAs in the future, offering a robust and enjoyable development experience for Kotlin aficionados venturing into the web.
Links:
[DevoxxPL2019] Centralized Logging Patterns: Approaches for Scalable Systems
Lecturer
Philipp Krenn is a developer advocate at Elastic, specializing in infrastructure and database technologies, with a background in web engineering. He leads efforts in the EMEA region to showcase solutions involving search, logging, and analytics, contributing to open-source communities through presentations and demonstrations.
Abstract
This examination reviews strategies for aggregating logs in distributed environments, assessing patterns like parsing, direct transmission, structured formatting, container-based collection, and orchestration in Kubernetes. It evaluates implementation techniques, contextual challenges, and outcomes for system reliability and observability using the Elastic Stack as a case study.
Parsing as an Initial Strategy: Deriving Insights from Unstructured Logs
As systems expand beyond a few instances, manual log inspection via commands like tail becomes impractical, prompting the need for centralized aggregation. Philipp commences with parsing, where applications output logs to files, and agents extract structured data for further processing.
Utilizing a Java application with Logback and SLF4J, logs incorporate contextual details through Mapped Diagnostic Context, such as random session identifiers and loop counters to simulate user interactions. These enable tracing specific activities, like identifying slowdowns for particular users. The parsing workflow involves Filebeat monitoring the file, forwarding to Logstash for dissection using Grok expressions to isolate timestamps, severity levels, and content, followed by enrichment with elements like geographic data from IP addresses.
For example, a Logstash configuration might apply a filter to break down a log line, adding fields for efficient querying. This decouples the application from the logging infrastructure, permitting backend adjustments without code changes. However, evolving log formats can break parsers, requiring vigilant maintenance of patterns.
Contextually, this suits environments with diverse log sources, including legacy applications producing plain text. Analytically, it transforms raw data into actionable intelligence; in Kibana, visualizations filter by severity or session, revealing patterns like error clusters. The ramifications include improved troubleshooting speed, but potential bottlenecks in parsing heavy loads underscore the need for optimized regex to maintain throughput in high-volume scenarios.
Direct Sending and Structured Formatting: Streamlining Data Flow
Moving beyond file-based logging, direct sending employs appenders to dispatch events straight to central systems, bypassing disk writes. Philipp configures a Logstash appender in the application’s logging setup, directing JSON-encoded messages to a designated port, thus eliminating the need for intermediate files.
This approach minimizes storage demands and accelerates delivery, as events transmit in near real-time. Structured formatting advances this by generating JSON logs natively, embedding contextual fields without post-processing. The encoder ensures compatibility, allowing seamless ingestion into Elasticsearch.
Methodologically, minimal application tweaks suffice—log as usual, but output structured payloads. This enhances searchability; fields become directly queryable, facilitating aggregations like error counts per session. In practice, it reduces coupling further, with configurations injectable via variables for flexibility.
Analytically, structuring aligns with observability principles, integrating logs with metrics for holistic views. Implications favor modern architectures, where network efficiency trumps local storage, though increased payload size could strain bandwidth. Compared to parsing, it offers reliability, as format consistency avoids extraction failures, promoting proactive monitoring in dynamic setups.
Container-Based Collection: Adapting to Transient Environments
In containerized deployments, traditional mounting for log files proves cumbersome, involving bind mounts that statically link volumes. Philipp advocates writing to standard output, leveraging Docker’s JSON driver to persist logs on the host.
Filebeat, deployed as a sidecar, accesses these via mounted directories, enriching with metadata like image hashes and project names. Hints embed processing rules in container labels, such as multiline patterns, inverting configuration to the source.
For illustration, enabling Docker inputs in Filebeat collects from all containers, but metadata filters isolate specifics, like by image name. This methodology handles ephemerality; logs capture regardless of container lifespan. Analytically, it supports debugging in microservices, where filtering by labels pinpoints issues without sifting through aggregates.
Ramifications include resilience against restarts—persistent registries prevent duplicates. However, startup artifacts like ASCII art require exclusion patterns to clean data. Overall, this pattern bolsters scalability, ensuring logs remain viable in fleeting environments, thus enhancing operational visibility.
Orchestration in Kubernetes: Managing Dynamic Allocations
Extending containerization, orchestration in Kubernetes demands node-level agents. Philipp deploys Filebeat as a DaemonSet, ensuring one instance per node to gather pod logs. Configurations query the Kubernetes API for metadata, adding namespaces and nodes to events.
This enriches queries, allowing namespace-based segmentation for isolated analysis. Methodologically, it accommodates dynamism—pods spin up/down, but logs flow continuously. Analytically, it enables granular insights, like correlating errors with deployments.
Implications emphasize governance; indices can partition by namespace for data isolation. Challenges like self-logging loops are mitigated by redirecting agent logs to files. This pattern culminates in comprehensive observability, transforming logs into strategic assets for performance tuning and anomaly detection in orchestrated landscapes.
Overall Outcomes for Infrastructure Design: Weighing Advantages and Challenges
Each strategy presents trade-offs shaping infrastructure. Parsing provides versatility but risks fragility; sending and structuring boost efficiency with minor ties; containerization and orchestration excel in volatility, demanding operational savvy.
Philipp advises incremental adoption: begin parsing for rapid setup, progress to structuring for maturity. Outcomes include heightened reliability—centralized views accelerate resolutions—and security, via auditable trails. Analytically, these foster data-centric cultures, where logs inform decisions, optimizing resource allocation in complex ecosystems.
Links:
[SpringIO2019] Event Driven Microservices with Axon and Spring Boot: Excitingly Boring
Simplifying Complex Architectures with Axon and Spring Boot
In his Spring I/O 2019 presentation, Allard Buijze, founder and CTO of AxonIQ, demonstrates how to build and scale event-driven microservices with Axon Framework and Spring Boot, making the process “excitingly boring” due to its simplicity. Buijze addresses the common misconception that microservices, especially event-driven variants, require complex and hard-to-grasp technologies, often diverting focus from core business logic to integration challenges.
The talk highlights the synergy between Spring Boot’s powerful autoconfiguration capabilities and Axon Framework’s support for Command Query Responsibility Segregation (CQRS) and Event Sourcing (ES). Through live coding, Buijze illustrates how this combination trivializes the development of scalable event-driven applications. Axon Framework, an open-source Java framework created by Buijze, is designed to help developers build scalable and maintainable applications using a message-driven approach, simplifying the complexities inherent in distributed systems.
Key takeaways from this session include:
- Trivializing Event-Driven Microservices: Leveraging Spring Boot and Axon to simplify the architecture and development of microservices.
- CQRS and Event Sourcing in Practice: Understanding how Axon Framework provides the necessary building blocks for these patterns.
- Message-Driven Architecture: Components communicate via commands, events, and queries, promoting loose coupling and flexibility.
- Scalability and Maintainability: Designing systems that are easy to extend and manage over time.
- Focus on Business Logic: Shifting developer attention from infrastructure concerns to core business requirements.
Allard Buijze has extensive experience in designing and developing enterprise applications with a strong focus on scalability and performance. He is a recognized expert in Domain-Driven Design (DDD) and CQRS, and regularly shares his insights at conferences and workshops.
Links
[KotlinConf2019] Sharing Is Caring: Kotlin Multiplatform for Android Developers with Britt Barak
The vision of writing code once and running it across multiple platforms is a long-held dream in software development. Britt Barak, an experienced Android and Kotlin developer, and Google Developer Expert, brought this vision closer to reality for Android developers at KotlinConf 2019. Her talk, “Sharing Is Caring – Kotlin Multiplatform for Android Developers,” explored the exciting, albeit then-experimental, capabilities of Kotlin Multiplatform (KMP) and how it could revolutionize the way Android developers collaborate with teams working on iOS, backend, or JavaScript projects.
Britt Barak emphasized the common scenario where Android developers work alongside backend services or with iOS and JavaScript teams developing similar functionalities. The ability to share Kotlin code across these platforms promised significant savings in implementation time, testing effort, and overall development efficiency. Her session focused on creating a full-stack Kotlin project, demonstrating how to share code between an Android app and a backend Kotlin component, ultimately leading to more efficient and robust applications.
The Promise of Kotlin Multiplatform
Kotlin Multiplatform (KMP) allows developers to write common logic in Kotlin and compile it for various targets, including JVM (for Android and backend), JavaScript (for web frontends), and Native (for iOS and other native applications). Britt Barak highlighted the power of this approach: sharing business logic, data models, and even presentation logic (in some architectures) can drastically reduce redundancy and inconsistencies between different platform implementations.
The core idea is to isolate platform-agnostic code in a “common” module. This module can then be consumed by platform-specific modules (e.g., Android, iOS, JVM backend) which implement the platform-dependent parts, such as UI or interactions with platform-specific APIs. This separation allows teams to leverage Kotlin’s strengths across their entire stack while still catering to the unique requirements of each platform. Britt’s presentation aimed to show Android developers how they could take the lead in initiating such code-sharing efforts, benefiting not only their own workflow but also that of their teammates on other platforms.
Practical Implementation and Considerations
Britt Barak’s session was hands-on, guiding attendees through the process of setting up and building a Kotlin Multiplatform project. She covered key KMP concepts such as:
* Common Modules: Where shared Kotlin code resides, free of platform-specific dependencies.
* Platform-Specific Modules: Modules targeting specific platforms (Android, JVM, JS, Native) that can depend on common modules and implement platform-specific functionalities using expect/actual declarations.
* expect and actual Keywords: A powerful mechanism in KMP that allows common code to declare an expected functionality (expect), which platform-specific modules then provide concrete implementations for (actual). This is crucial for accessing platform-specific APIs (like device sensors, file systems, or UI elements) from shared code.
She demonstrated how to structure a project to share code effectively between an Android application and a backend Kotlin component, showcasing the potential for building more cohesive and maintainable full-stack applications. This practical approach would have involved setting up the build system (Gradle), defining dependencies, and writing shared business logic that could be consumed by both the Android client and the server. The goal was to illustrate how to build “more efficient and robust applications” through strategic code sharing.
Navigating the Experimental Landscape and Community Support
At the time of KotlinConf 2019, Kotlin Multiplatform was still an experimental feature. Britt Barak acknowledged this, preparing attendees for a landscape where documentation might sometimes be a bit dated, and tooling was rapidly evolving. However, she also pointed to the strong and growing community support as a significant asset. The official Kotlin Slack and various online forums were highlighted as valuable resources for troubleshooting and learning from others’ experiences.
She shared the sentiment that KMP was gaining popularity in a positive way, with many developers interested and actively contributing to its growth. This collaborative environment was seen as a good sign for the future development and stabilization of KMP. Britt encouraged developers to embrace this journey, start experimenting with multiplatform projects, and contribute to the community by sharing their own code and experiences. Her message was clear: despite its experimental nature, Kotlin Multiplatform offered a powerful and awesome way to achieve cross-platform code sharing, and it was a “really good time to jump on on the ride”.
Links:
[DotCSS2018] DotCSS 2018: Mandy Michael – Variable Fonts Ushering in Typographic Horizons
Mandy Michael, an innovative front-end developer renowned for her CSS artistry, illuminated the transformative promise of variable fonts at DotCSS 2018. As a self-proclaimed tinkerer rather than a traditional designer, she demonstrates how these fonts transcend mere efficiency, unlocking realms of adaptive, interactive typography that harmonizes with the web’s fluidity. Michael’s discourse blends practical gains with visionary applications, positioning variable fonts as harbingers of a more nuanced digital vernacular.
Streamlining Performance While Amplifying Flexibility
Michael demystifies variable fonts as singular files encapsulating myriad styles, where traditional suites demand separate downloads for each weight or variant. Forged by designers via interpolable axes—spanning weight, width, or slant—these fonts grant granular access to intermediary values, from 100 to 900 in 1-unit increments. This continuum facilitates seamless animations, unmarred by the jarring leaps of static counterparts.
Browser compatibility, she assures, is robust across majors, with macOS High Sierra as the sole caveat for Firefox users. Performance perks shine in comparisons: Adobe’s Source Sans variable edition clocks in at 394 KB for exhaustive coverage, dwarfing the 924 KB aggregate of its static kin—even pruned selections. A lone network call supplants cascades of requests, synergizing with HTTP/2 for swifter loads. Yet, beyond bandwidth thrift, variable fonts liberate creativity; their slimmer profiles embolden bolder experimentation without fiscal remorse.
Michael illustrates with bespoke text effects—slimy oozes via Chi by Fontself or vanishing shadows in Dec—where axes morph glyphs in real-time, rendering editable, screen-reader-friendly prose that supplants cumbersome images or canvases.
Adaptive Typography for Inclusive, Dynamic Experiences
The true alchemy of variable fonts, per Michael, resides in environmental responsiveness. Axes like optical size or grade adjust legibility across devices—from wristworn smartwatches to expansive projectors—ensuring hierarchy endures. Scroll-triggered swells in Chi or proximity-based sizing via Sensor API exemplify this; fonts now converse with context, elevating readability in dim alcoves or glaring outdoors.
Emerging CSS media queries, such as prefers-color-scheme: dark, further this dialogue. Michael’s demo toggles oozing text in shadowed modes, blending transitions for intuitive shifts. Audio-responsive variants, attuned to vocal inflections, hint at conversational interfaces for voice assistants, visually encoding tone sans verbosity.
Accessibility amplifies: interpolated contrasts mitigate low-vision strains, while dynamic weights enhance scannability. Michael envisions fonts as APIs, manipulable by JavaScript for user-centric tweaks—be it luminance detection or gestural inputs. Though nascent, these facets dissolve erstwhile constraints, where performance once curbed flair. Now, content’s essence—its rhythm, intent—guides form, fusing print’s poise with web’s interactivity. As Michael avows, this epoch invites developers to sculpt purposeful, performant narratives, unhindered by yesteryear’s shackles.
Links:
[DevoxxPL2019] Functional Programming in Kotlin: Core Concepts and Applications
Lecturer
Venkat Subramaniam is an acclaimed software developer, author, and educator who founded Agile Developer, Inc., specializing in training and consulting on agile practices and programming languages. He holds a position as an instructional professor at the University of Houston, where he imparts knowledge on software engineering principles, and has authored several books on programming topics, including works on Kotlin and functional paradigms.
Abstract
This exploration delves into the principles of functional programming within the Kotlin language, contrasting it with imperative approaches and emphasizing declarative techniques, higher-order functions, lambda expressions, and lazy evaluation strategies. Through detailed examples, it examines how these elements streamline code, mitigate complexity, and support concurrent operations, while discussing methodological choices and their broader effects on software architecture.
Distinguishing Imperative and Declarative Paradigms: Establishing the Base
In software development, the choice of programming style profoundly influences the clarity and maintainability of code. Venkat initiates his discussion by highlighting the imperative style, where developers must specify not only the desired outcome but also the exact sequence of steps to achieve it. This method resembles providing exhaustive instructions, placing the onus on the programmer to manage every aspect of the process, which can introduce unnecessary intricacies that obscure the primary objective.
To illustrate, consider a scenario involving a collection of integers from one to ten, where the task is to calculate the sum of the doubles of all even numbers. In an imperative framework, one would typically declare a mutable variable to accumulate the result, then employ a loop to traverse the collection, apply a condition to identify even numbers, perform the doubling operation, and update the accumulator accordingly. Such an approach requires explicit handling of iteration and state changes, which can lead to errors if not managed meticulously. For instance, overlooking the initialization of the accumulator or mishandling the loop boundaries could yield incorrect results, thereby increasing the cognitive burden on the developer.
Conversely, the declarative style allows programmers to articulate solely what is needed, delegating the implementation details to underlying abstractions. This shift enables a focus on intent rather than mechanics, much like issuing a high-level command without detailing the execution path. Functional programming builds upon this by incorporating higher-order functions, which are capable of accepting other functions as arguments, generating new functions, or yielding functions as results. These constructs facilitate functional composition, where smaller, reusable units of behavior are combined to form more sophisticated operations without altering shared state.
Venkat underscores that while Kotlin permits imperative coding for familiarity, its support for declarative constructs encourages a move toward reduced complexity. By abstracting away low-level controls, developers can produce code that is more intuitive and less prone to defects. This transition has significant ramifications for large-scale systems, where maintaining code over time becomes paramount; declarative code tends to be more adaptable, facilitating easier modifications and extensions without widespread ripple effects.
Harnessing Lambda Expressions and Higher-Order Functions: Fundamental Tools
At the heart of Kotlin’s functional capabilities lie lambda expressions, which Venkat portrays as nameless functions designed to encapsulate behavior concisely and purely, meaning they avoid modifying external state or producing side effects. These expressions consist of a parameter list separated by an arrow from the body, enclosed in curly braces, with the return type inferred from the context to minimize verbosity.
The structure promotes brevity, ideally limiting the body to a single line to preserve readability. For example, incrementing each element in a list can be achieved with a lambda passed to the map function, transforming the collection in a one-to-one manner without explicit loops. However, when transformations yield multiple outputs per input—such as generating predecessors and successors for each number—standard mapping results in nested collections. To address this, flattening merges these into a single list, but performing mapping followed by flattening separately can be inefficient.
Venkat explains that flatMap elegantly combines these operations, applying the transformation and then consolidating the results. This is particularly useful for one-to-many mappings, ensuring the output remains a flat structure. Methodologically, selecting map for direct correspondences and flatMap for expansive transformations optimizes the pipeline, aligning with functional composition principles where functions chain to build complex logic from simple components.
Furthermore, higher-order functions extend this by treating functions as data, enabling dynamic behavior parameterization. The broader context is Kotlin’s hybrid nature, integrating object-oriented features with functional ones, allowing seamless interoperability. Analytically, this purity aids in reasoning about code; since functions depend only on inputs, outputs are predictable, simplifying testing and debugging. The consequences extend to concurrency, where absence of mutable state eliminates contention, making parallelization straightforward and safer in multi-threaded environments.
Implementing Lazy Evaluation: Optimizing Resource Utilization
A critical facet Venkat addresses is evaluation strategy, distinguishing eager from lazy approaches. Eager evaluation processes operations immediately, which can be wasteful for large datasets or when only partial results are needed. For instance, finding the double of the first even number greater than three in a list involves filtering for values exceeding three, then for evenness, doubling, and selecting the first—eagerly traversing the entire collection multiple times.
By converting the list to a sequence in Kotlin, operations become lazy, computing only as required. This defers execution until the terminal operation, such as retrieving the first element, halting further processing once the result is found. Venkat demonstrates this with print statements in filter and map functions, revealing that lazy sequences minimize calls, touching only necessary elements.
Methodologically, employing sequences for potentially infinite or voluminous data prevents unnecessary computations, akin to Java’s streams. However, developers must consciously opt for sequences, as list operations default to eagerness. The context here is performance-sensitive applications, where eager defaults could lead to inefficiencies. Implications include resource conservation in big data scenarios, enabling handling of streams that exceed memory capacity. Analytically, laziness embodies functional essence, allowing declarative chains without premature optimization concerns, thus promoting scalable designs in resource-constrained settings.
Broader Ramifications for Software Engineering: From Concurrency to Maintainability
Although functional programming bolsters concurrency by eschewing mutable state—thus avoiding locks and race conditions—Venkat posits that its chief merit lies in declarative reduction of accidental complexity, where code mirrors intent more closely. Imperative verbosity often embeds implementation details that hinder comprehension, whereas functional pipelines express logic fluidly.
In Kotlin, this manifests through native support for these idioms, blending with object-oriented paradigms for versatile architectures. Yet, judicious application is key; misusing eagerness or bloating lambdas undermines benefits. The consequences foster resilient systems, adaptable to change with minimal disruption. For practitioners, this encourages a mindset shift toward composition and purity, yielding codebases that are easier to evolve and collaborate on.
Ultimately, Kotlin’s functional features empower developers to craft elegant solutions, balancing expressiveness with efficiency, and paving the way for innovative software practices.