Recent Posts
Archives

Archive for the ‘en-US’ Category

PostHeaderIcon [KotlinConf2019] Kotlin Multiplatform Programming: Present and Future with Dmitry Savvinov and Liliia Abdulina

Kotlin Multiplatform Programming (MPP) has been a significant focus for JetBrains, aiming to extend Kotlin’s reach beyond traditional JVM and Android development. At KotlinConf 2019, Dmitry Savvinov and Liliia Abdulina, both from the Kotlin team at JetBrains, delivered an insightful overview of MPP’s capabilities in version 1.3.X and offered a glimpse into its future direction. Dmitry Savvinov, a key contributor to Kotlin Contracts and heavily involved in MPP, brought his compiler expertise to the discussion. The official Kotlin language website, the central hub for MPP information, is kotlinlang.org.

Their talk was structured to cover the fundamentals of multiplatform projects, illustrate these basics with examples, provide guidelines for designing first multiplatform projects, and showcase a production-like application to demonstrate design principles in action. This comprehensive approach aimed to equip developers with the knowledge needed to start leveraging MPP effectively.

Core Concepts of Kotlin Multiplatform

Dmitry Savvinov and Liliia Abdulina began by explaining the core building blocks of Kotlin Multiplatform projects. These foundational concepts are crucial for understanding how code can be shared and specialized across different platforms:
* Source Sets: The fundamental unit of code organization in MPP. A project is typically structured with a commonMain source set containing platform-agnostic Kotlin code. Platform-specific source sets (e.g., jvmMain, jsMain, iosMain) contain code tailored for each target and can depend on commonMain.
* Targets: These define the platforms the project will compile for, such as JVM, Android, JavaScript, iOS (Native), Linux, Windows, and macOS. Each target has its own compilations.
* Compilations: A compilation process for a specific target that produces the appropriate artifacts (e.g., JVM bytecode, JavaScript files, native executables).
* expect and actual Declarations: This powerful mechanism allows common code in commonMain to declare an expect class, function, or property. Platform-specific source sets must then provide an actual implementation for that declaration, bridging the gap between shared logic and platform-specific APIs. For example, a common module might expect a function to generate a UUID, and the JVM and Native modules would provide actual implementations using their respective platform libraries.

These concepts enable developers to write shared business logic, data models, and algorithms once in commonMain and then reuse them across multiple platforms, significantly reducing code duplication and improving consistency.

Designing and Implementing Multiplatform Projects

Beyond the basic syntax, Dmitry and Liliia provided guidance on how to approach the design of a multiplatform project. This involved discussing strategies for identifying what code can and should be shared, how to structure modules for optimal maintainability, and best practices for using expect/actual effectively.

They used toy examples to illustrate these basics in a clear and understandable manner, helping attendees grasp how these pieces fit together in a real project. The presentation then progressed to showcase a “more or less production-like application”. This larger example would have served to demonstrate how the design principles discussed could be applied to build a substantial, real-world multiplatform application, highlighting how to manage dependencies, handle platform-specific interactions, and structure a scalable MPP architecture. The focus was on providing practical insights that developers could apply to their own projects, whether starting from scratch or integrating MPP into existing applications.

The Trajectory of Kotlin Multiplatform: Beyond 1.3.X

While detailing the state of MPP in Kotlin 1.3.X, Dmitry Savvinov and Liliia Abdulina also looked towards its future development. At KotlinConf 2019, MPP was still evolving, with ongoing improvements to tooling, library support, and the overall developer experience. Their talk touched upon the roadmap for MPP, including planned enhancements to areas like Kotlin/Native (for performance and interoperability), library ecosystem growth, and further refinements to the build system and IDE support within IntelliJ IDEA and Android Studio.

The vision presented was one of Kotlin as a truly universal language, enabling developers to target a wide array of platforms with a unified codebase and skillset. The commitment from JetBrains to invest heavily in MPP was clear, with the aim of making it a robust and production-ready solution for cross-platform development. The session would have encouraged developers to explore MPP, provide feedback, and contribute to its growing ecosystem, reinforcing the community-driven aspect of Kotlin’s development.

Links:

PostHeaderIcon [SpringIO2019] Zero Downtime Migrations with Spring Boot by Alex Soto

Deploying software updates without disrupting users is a cornerstone of modern DevOps practices. At Spring I/O 2019 in Barcelona, Alex Soto, a prominent figure at Red Hat, delivered a comprehensive session on achieving zero downtime migrations in Spring Boot applications, particularly within microservices architectures. With a focus on advanced deployment techniques and state management, Alex provided actionable insights for developers navigating the complexities of production environments. This post delves into his strategies, enriched with practical demonstrations and real-world applications.

The Evolution from Monoliths to Microservices

The shift from monolithic to microservices architectures has transformed deployment practices. Alex began by contrasting the simplicity of monolithic deployments—where a single application could be updated during off-hours with minimal disruption—with the complexity of microservices. In a microservices ecosystem, services are interconnected in a graph-like structure, often with independent databases and multiple entry points. This distributed nature amplifies the impact of downtime, as a single service failure can cascade across the system.

To address this, Alex emphasized the distinction between deployment (placing a service in production) and release (routing traffic to it). This separation is critical for zero downtime, allowing teams to test new versions without affecting users. By leveraging service meshes like Istio, developers can manage traffic routing dynamically, ensuring seamless transitions between service versions.

Blue-Green and Canary Deployments

Alex explored two foundational techniques for zero downtime: blue-green and canary deployments. In blue-green deployments, a new version (green) is deployed alongside the existing one (blue), with traffic switched to the green version once validated. This approach minimizes disruption but risks affecting all users if the green version fails. Canary deployments mitigate this by gradually routing a small percentage of traffic to the new version, allowing teams to monitor performance before a full rollout.

Both techniques rely on robust monitoring, such as Prometheus, to detect issues early. Alex demonstrated a blue-green deployment using a movie store application, where a shopping cart’s state was preserved across versions using an in-memory data grid like Redis. This ensured users experienced no loss of data, even during version switches, highlighting the power of stateless and ephemeral state management in microservices.

Managing Persistent State

Persistent state, such as database schemas, poses a significant challenge in zero downtime migrations. Alex illustrated this with a scenario involving renaming a database column from “name” to “full_name.” A naive approach risks breaking compatibility, as some users may access the old schema while others hit the new one. To address this, he proposed a three-step migration process:

  1. Dual-Write Phase: The application writes to both the old and new columns, ensuring data consistency across versions.
  2. Data Migration: Historical data is copied from the old column to the new one, often using tools like Spring Batch to avoid locking the database.
  3. Final Transition: The application reads and writes exclusively to the new column, with the old column retained for rollback compatibility.

This methodical approach, demonstrated with a Kubernetes-based cluster, ensures backward compatibility and uninterrupted service. Alex’s demo showed how Istio’s traffic management capabilities, such as routing rules and mirroring, facilitate these migrations by directing traffic to specific versions without user impact.

Leveraging Istio for Traffic Management

Istio, a service mesh, plays a pivotal role in Alex’s strategy. By abstracting cross-cutting concerns like service discovery, circuit breaking, and security, Istio simplifies zero downtime deployments. Alex showcased how Istio’s sidecar containers handle traffic routing, enabling techniques like traffic mirroring for dark launches. In a dark launch, requests are sent to both old and new service versions, but only the old version’s response is returned to users, allowing teams to test new versions in production without risk.

Istio also supports chaos engineering, simulating delays or timeouts to test resilience. Alex cautioned, however, that such practices require careful communication to avoid unexpected disruptions, as illustrated by anecdotes of misaligned testing efforts. By integrating Istio with Spring Boot, developers can achieve robust, scalable deployments with minimal overhead.

Handling Stateful Services

Stateful services, particularly those with databases, require special attention. Alex addressed the challenge of maintaining ephemeral state, like shopping carts, using in-memory data grids. For persistent state, he recommended strategies like synthetic transactions or throwaway database clusters to handle mirrored traffic during testing. These approaches prevent unintended database writes, ensuring data integrity during migrations.

In his demo, Alex applied these principles to a movie store application, showing how a shopping cart persisted across blue-green deployments. By using Redis to replicate state across a cluster, he ensured users retained their cart contents, even as services switched versions. This practical example underscored the importance of aligning infrastructure with business needs.

Lessons for Modern DevOps

Alex’s presentation offers a roadmap for achieving zero downtime in microservices. By combining advanced deployment techniques, service meshes, and careful state management, developers can deliver reliable, user-focused applications. His emphasis on tools like Istio and Redis, coupled with a disciplined migration process, provides a blueprint for tackling real-world challenges. For teams like those at Red Hat, these strategies enable faster, safer releases, aligning technical excellence with business continuity.

Links:

PostHeaderIcon [DevoxxPL2019] Practical Event Sourcing: Avoiding Common Errors in Implementation

Lecturer

David Schmitz functions as a key architect at Senacor Technologies, with deep roots in rebuilding financial platforms using event-driven designs. His work spans multiple large-scale projects in banking and insurance, emphasizing sustainable architectures.

Abstract

This review critiques simplistic event sourcing adoptions, advocating refined tactics derived from extensive enterprise deployments. It defines events as unalterable facts in streams, integrates CQRS for separated concerns, and tackles hurdles in transactions, compensations, and privacy compliance. Via financial illustrations, it inspects techniques for consistency, deletion via tombstones, and polyglot persistence, reflecting on outcomes for durability and adaptability in regulated domains.

Understanding Event-Driven Foundations: Events as Core Artifacts

Event sourcing posits systems as event appendages, reconstructing states from chronological logs. David analogizes to routine transactions, like cafe orders, where each step—ordering, paying—yields events forming the narrative.

In enterprises, particularly finance, this supplants CRUD with append-only logs, yielding audit trails. Streams, via Kafka, order events, partitions grouping related ones (e.g., per account) for sequential processing.

Context: monolithic databases yield to distributed microservices, but naive per-service databases fragment truth. Event sourcing unifies via shared streams, though over-partitioning bloats management.

Analytically, events as facts enable replays for debugging or migrations, but demand schema versioning. Implications: bolsters traceability, yet escalates storage, mitigated by compaction removing intermediates.

CQRS Integration: Decoupling Commands and Queries

CQRS bifurcates modifications (commands appending events) from retrievals (queries on projections). David exemplifies transfers: commands emit events to sender/receiver streams; processors project balances.

Methodologically, Kafka Streams aggregate, ensuring eventual consistency sans distributed transactions. For guarantees, single-writer patterns serialize per-entity events.

Challenges: optimistic concurrency via versions prevents overwrites; failures invoke compensations—explicit reversals preserving history.

In insurance, initial oversights led to redesigns; polyglot views (e.g., Elasticsearch for searches) enhance flexibility.

Analytically, this scales sides independently, but lags demand monitoring. Consequences: agile evolutions, though compensations complicate logic, necessitating clear business rules.

Compliance Handling: Deletion and Rectification in Immutable Logs

GDPR mandates erasure/rectification, clashing with immutability. David proposes tombstones—events signaling deletions, prompting anonymization downstream.

For users, tombstones propagate, purging identifiers while retaining structures for audits. Rectifications append compensations, adjusting views idempotently.

Methodologically, upcasters during replays adapt old events to new schemas, ensuring compatibility.

Analytically, this reconciles permanence with privacy, but requires cross-domain coordination. Implications: legal alignment, though tombstones inflate streams, offset by compaction.

Maintainability and Tradeoffs: Insights from Deployments

Event sourcing decouples, but excessive streams hinder navigation. David advises aligning with bounded contexts, mixing with relational stores for queries.

From banking, optimistic conflicts resolved via retries; security via encryption guards sensitive events.

Methodologically, tools like KSQL query streams declaratively. Implications: audit-ready systems, but complexity in debugging distributed flows.

In reflection, event sourcing thrives with deliberate design, yielding robust, evolvable platforms in stringent sectors.

Links:

PostHeaderIcon [DevoxxPL2019] Constructing Custom Reactive Publishers: Insights into Project Reactor Internals

Lecturer

Oleh Dokuka contributes to Project Reactor as a committer, authoring books on reactive programming with Spring and serving as a software engineer at Superhuman. Based in Kyiv, he actively participates in conferences and communities focused on asynchronous systems.

Abstract

This inquiry delves into the intricacies of building a reactive publisher compliant with Reactive Streams specifications, drawing from Project Reactor’s design. It covers the rationale behind the spec, naive implementations, concurrency patterns like work-in-progress, and verification via TCK. Through iterative coding, it analyzes challenges in non-blocking data flows, backpressure, and thread safety, pondering effects on debugging, customization, and library extension.

Demystifying Reactive Streams: Specification and Purpose

Reactive Streams standardize asynchronous, non-blocking data processing with backpressure, addressing overflow in producer-consumer scenarios. Oleh commences by recalling the spec’s origins, crafted to unify libraries like RxJava and Akka Streams, ensuring interoperability.

Core interfaces—Publisher, Subscriber, Subscription, Processor—define interactions: publishers emit items, subscribers consume, subscriptions mediate requests and cancellations. The spec mandates rules for thread safety and signal ordering, preventing races.

Contextually, adoption surged with Java 9’s Flow API, embedding reactivity natively. Analytically, backpressure—subscribers requesting items—prevents buffering overloads, crucial in unbounded sources like networks.

Implications: enables composable, resilient pipelines, but demands adherence to 50+ rules, tested via TCK. For developers, understanding facilitates debugging; for extenders, it unlocks optimizations.

Naive Publisher Construction: Initial Steps and Pitfalls

Commencing with a basic array publisher, Oleh demonstrates emitting elements on subscription. Yet, naivety ignores concurrency: parallel subscriptions risk duplicates or misses.

Methodologically, extend TCK’s PublisherVerification for rule checks. Initial failures highlight needs for atomic operations and request tracking.

A subscription class manages emissions:

class ArraySubscription<T> implements Subscription {
    private final Subscriber<? super T> subscriber;
    private final T[] array;
    private int index = 0;
    private boolean canceled = false;

    public ArraySubscription(Subscriber<? super T> subscriber, T[] array) {
        this.subscriber = subscriber;
        this.array = array;
    }

    @Override
    public void request(long n) {
        if (n <= 0 && !canceled) {
            subscriber.onError(new IllegalArgumentException("Non-positive request"));
            canceled = true;
            return;
        }
        for (long i = 0; i < n && !canceled; i++) {
            if (index < array.length) {
                subscriber.onNext(array[index++]);
            } else {
                subscriber.onComplete();
                canceled = true;
                break;
            }
        }
    }

    @Override
    public void cancel() {
        canceled = true;
    }
}

This handles basics but falters under concurrency, necessitating refinements.

Incorporating Concurrency Safeguards: Work-in-Progress and Atomicity

To thread-safely accumulate requests, introduce work-in-progress (WIP)—an atomic counter tracking processing state. Oleh explains: increment WIP to claim emission exclusivity; if non-zero, another thread processes, so defer.

Requests add to a requested counter atomically. On WIP decrement to zero, check if more requests pend, resuming if so.

This pattern, akin to semaphores, ensures single-threaded emission despite multi-threaded requests, averting races.

Analytically, it balances responsiveness and safety, though overflows (Long.MAX_VALUE) signal unbounded requests, potentially overwhelming subscribers.

Implications: facilitates non-blocking I/O, vital for high-throughput, but debugging requires tracing atomics.

Verification and Iterative Refinement: Ensuring Spec Compliance

Leverage TCK for exhaustive testing: extend PublisherVerification, supplying working and failing publishers. Tests validate signals, backpressure, and edge cases like negative requests.

Oleh iterates: failures prompt guards, like canceling on invalid requests. Post-fixes, all pass, confirming robustness.

Methodologically, TCK simulates parallelism, exposing flaws early. For custom operators, similar suites verify.

Consequences: empowers library creation or tweaks, as in optimizing for known guarantees, enhancing performance in specific flows.

Extending to Operators and Libraries: Building Beyond Basics

With a compliant publisher, assemble operators chaining transformations. Oleh hints at flux wrappers, where sources like arrays feed pipelines.

Analytically, operators preserve backpressure, propagating requests upstream. This composability yields expressive, efficient streams.

Implications: demystifies internals, aiding contributions to Reactor or custom variants for niches like low-latency trading.

In conclusion, mastering publishers unlocks reactive potential, transforming complex async into manageable flows.

Links:

PostHeaderIcon [SpringIO2019] Managing Business Processes in Microservice Architecture with Spring Ecosystem by Bartłomiej Słota

In the dynamic landscape of software development, reconciling the structured demands of Business Process Management (BPM) with the flexibility of microservices presents both challenges and opportunities. At Spring I/O 2019 in Barcelona, Bartłomiej Słota, a seasoned consultant from Poland, delivered an insightful presentation on integrating BPM with microservices using the Spring ecosystem. Drawing from his experience at Batcave IT Minds and his work with Vattenfall, a Swedish energy company, Bartłomiej offered a compelling narrative on achieving autonomy and efficiency in business processes. This post explores his approach, emphasizing practical solutions for modern software architectures.

The Business Process Management Challenge

Business Process Management systems are pivotal for organizations aiming to streamline operations and enhance competitiveness. With a market valued at $8 billion and projected to reach $18.5 billion by 2025, companies invest heavily in BPM to optimize workflows and reduce costs. However, traditional BPM solutions often rely on monolithic architectures, which clash with the agile, decentralized nature of microservices. Bartłomiej introduced a fictional developer, Bruce, who faces the frustration of rigid systems, manual interventions, and low productivity. Bruce’s struggle mirrors real-world challenges where teams grapple with aligning business needs with technical agility.

The core issue lies in the inherent tension between the centralized control of BPM systems and the autonomy required for microservices. Traditional BPM architectures lack scalability, technology flexibility, and deployment independence, leading to inefficiencies. Bartłomiej proposed a solution: leveraging microservices to create autonomous, scalable, and resilient business processes, supported by tools like Apache Kafka and Spring Cloud Stream.

Achieving Autonomy Through Microservices

Microservices thrive on autonomy, which Bartłomiej described as a multidimensional vector encompassing scalability, deployment, data management, resilience, technology choice, and team dynamics. Scalability, for instance, extends beyond technical resources to organizational efficiency. Drawing from Robert C. Martin’s Clean Architecture, Bartłomiej highlighted how unchecked complexity can inflate development costs, with more engineers producing fewer lines of business logic per release. Microservices address this by allowing independent scaling of components, reducing organizational bottlenecks.

Deployment autonomy is equally critical. By decoupling services, teams can deploy updates independently, avoiding the all-or-nothing approach of monolithic systems. Bartłomiej emphasized high cohesion, ensuring each microservice focuses on specific business functionalities. This approach also extends to data management, where each service maintains its own database, enhancing autonomy and reducing dependencies. For Bruce, this meant breaking free from the constraints of a shared, generic database schema, enabling faster and safer changes.

Event Storming for Business Alignment

To bridge the gap between business and technical teams, Bartłomiej advocated for event storming, a collaborative workshop method that fosters a shared understanding of business processes. Unlike traditional BPMN diagrams, which may alienate non-technical stakeholders, event storming uses sticky notes to map processes in a way that’s accessible to all. Through a case study of an address change process, Bartłomiej demonstrated how event storming identifies key events—like authorization or AML checks—revealing inefficiencies and silos. This process helped Bruce’s team define clear bounded contexts, ensuring microservices remain cohesive and autonomous.

Event storming also mitigates the risks of Conway’s Law, where system design mirrors organizational communication patterns. By engaging stakeholders from various departments, teams can uncover where value is created or lost, aligning technical solutions with business goals. For Vattenfall, this approach facilitated the migration of their mobility platform to a Kubernetes-based microservice environment, enhancing scalability and user experience.

Orchestration and Spring Ecosystem Tools

Bartłomiej contrasted two communication patterns for microservices: choreography and orchestration. Choreography, where services emit and consume events independently, can lead to tight coupling when new processes are introduced. Instead, he recommended orchestration, where a dedicated process orchestrator manages workflows by sending commands and processing events. In the address change example, an orchestrator coordinates interactions between services like authorization, customer contact, and AML checks, ensuring flexibility and resilience.

Spring Cloud Stream and Apache Kafka play pivotal roles in this architecture. Spring Cloud Stream abstracts messaging complexities, enabling seamless communication via Kafka topics. Kafka’s consumer groups and topic partitioning enhance scalability, while Kafka Streams supports real-time data processing for tasks and reports. Bartłomiej showcased how Vattenfall uses Kafka Streams to build read models, offering business insights that surpass traditional BPM solutions. Additionally, tools like Spring Cloud Sleuth and Spring Cloud Contract ensure observability and reliable testing, critical for maintaining autonomous services.

Empowering Teams and Technology Choices

The success of microservices hinges on people. Bartłomiej stressed that organizational culture must empower teams to own processes end-to-end, fostering leadership and accountability. By assigning a single team to each business process, as identified through event storming, companies can minimize conflicts and enhance autonomy. This approach also allows teams to select technologies suited to their specific challenges, from Spring Data REST for lightweight APIs to Akka for complex workflows.

For Bruce, adopting these principles transformed his project. By embracing microservices, event storming, and Spring ecosystem tools, he addressed pain points, improved productivity, and aligned technical efforts with business value. Bartłomiej’s presentation underscores that integrating BPM with microservices is not just a technical endeavor but a cultural shift, enabling organizations to deliver competitive, scalable solutions.

Links:

PostHeaderIcon [ScalaDays 2019] Techniques for Teaching Scala

Noel Welsh, co-founder of Underscore VC and a respected voice in the Scala community, known for his educational contributions including the books “Creative Scala” and “Essential Scala,” shared his valuable insights on “Techniques for Teaching Scala” at ScalaDays Lausanne 2019. His presentation moved beyond the technical intricacies of the language to explore the pedagogical approaches that make learning Scala more effective, engaging, and accessible to newcomers.

Addressing Scala’s Complexity

Welsh likely began by acknowledging the perceived complexity of Scala. While powerful, its rich feature set, including its blend of object-oriented and functional paradigms, can present a steep learning curve. His talk would have focused on how educators and mentors can break down these complexities into digestible components, fostering a positive learning experience that encourages long-term adoption and mastery of the language.

Structured and Incremental Learning

One of the core themes Welsh might have explored is the importance of a structured and incremental approach to teaching. Instead of overwhelming beginners with advanced concepts like implicits, monads, or higher-kinded types from day one, he probably advocated for starting with Scala’s more familiar object-oriented features, gradually introducing functional concepts as the learner builds confidence and a foundational understanding. He might have shared specific curriculum structures or learning pathways that have proven successful in his experience, perhaps drawing from his work at Underscore Training or the philosophy behind “Creative Scala,” which uses creative coding exercises to make learning fun and tangible.

Practical Application and Real-World Examples

Another key technique Welsh likely emphasized is the power of practical application and real-world examples. Abstract theoretical explanations, he might have argued, are less effective than hands-on coding exercises that allow learners to see Scala in action and understand how its features solve concrete problems. This could involve guiding students through building small, meaningful projects or using Scala for data manipulation, web development, or other relatable tasks. The use of tools like Scala Worksheets or Ammonite scripts for immediate feedback and experimentation could also have been highlighted as beneficial for learning.

Psychological Aspects of Learning

Welsh may have also delved into the psychological aspects of learning a new programming language. Addressing common frustrations, building a supportive learning environment, and celebrating small victories can significantly impact a student’s motivation and persistence. He might have discussed the role of clear, concise explanations, well-chosen analogies, and the importance of providing constructive feedback. Techniques for teaching specific Scala concepts that often trip up beginners, such as pattern matching, futures, or the collections library, could have been illustrated with practical teaching tips.

Investing in Scala Education

Ultimately, Noel Welsh’s presentation would have been a call to the Scala community to invest not just in developing the language and its tools, but also in refining the art and science of teaching it. By adopting more effective pedagogical techniques, the community can lower the barrier to entry, nurture new talent, and ensure that Scala’s power is accessible to a broader audience of developers, fostering a more vibrant and sustainable ecosystem.

Hashtags: #ScalaDays2019 #Scala #Education #Teaching #Pedagogy #NoelWelsh #CreativeScala

PostHeaderIcon [KotlinConf2019] Ktor for Mobile Developers: Conquering the Server with Dan Kim

For many mobile developers, the thought of venturing into server-side development can be daunting, often perceived as a realm of unfamiliar languages, complex frameworks, and different programming paradigms. Dan Kim, an experienced developer, aimed to demystify this process at KotlinConf 2019 with his talk, “Ktor for Mobile Developers: Fear the server no more!”. He showcased Ktor, a Kotlin-based framework for building asynchronous servers and clients, as an accessible and powerful tool for mobile developers looking to create backend components for their applications. The official website for Ktor is ktor.io.

Dan Kim’s session was designed to demonstrate how existing Kotlin knowledge could be leveraged to easily build server-side applications with Ktor. He promised a practical, real-world example, walking attendees through everything needed to get a server up and running: authentication, data retrieval, data posting, and deployment, ultimately aiming to give mobile developers the confidence to build their own backend services.

Introducing Ktor: Simplicity and Power in Kotlin

Ktor is a framework built by JetBrains, designed from the ground up with Kotlin and coroutines in mind, making it inherently asynchronous and well-suited for building scalable network applications. Dan Kim introduced Ktor’s core concepts, such as its flexible pipeline architecture, routing capabilities, and features for handling HTTP requests and responses. A key appeal of Ktor for mobile developers is that it allows them to stay within the Kotlin ecosystem, using a language and paradigms they are already familiar with from Android development.

The presentation would have highlighted Ktor’s ease of use and minimal boilerplate. Unlike some larger, more opinionated server-side frameworks, Ktor offers a more unopinionated and lightweight approach, allowing developers to choose and configure only the features they need. This can include functionalities like authentication, content negotiation (e.g., for JSON or XML), templating engines, and session management, all installable as “features” or plugins within a Ktor application.

Building a Real-World Server-Side Component

The core of Dan Kim’s talk was a hands-on demonstration of building a server-side component. He aimed to build a RESTful API and a web application, complete with authentication, and deploy it to Google Cloud, all within an impressively small amount of code (around 350 lines, as he mentioned). This practical example would have covered essential aspects of backend development:
* Routing: Defining endpoints to handle different HTTP methods (GET, POST, etc.) and URL paths.
* Request Handling: Processing incoming requests, extracting parameters, and validating data.
* Authentication: Implementing mechanisms to secure endpoints and manage user identity, possibly integrating with external services.
* Data Interaction: Showing how to get data from and post data to other services or a database (though the specifics of database interaction might vary).
* Deployment: Walking through the process of deploying the Ktor application to a cloud platform like Google Cloud, making the backend accessible to mobile clients.

By tackling these common server-side tasks using Ktor and Kotlin, Dan aimed to alleviate the fears mobile developers might have about backend development and demonstrate that they already possess many of the necessary skills.

Empowering Mobile Developers to Go Full-Stack

The overarching message of Dan Kim’s presentation was one of empowerment. He sought to show that with Ktor, mobile developers no longer need to “fear the server”. The framework provides a gentle learning curve and a productive environment for building robust and efficient backend services. This capability is increasingly valuable as mobile applications become more sophisticated and often require custom backend logic to support their features.

Dan Kim’s practical demonstration, from basic Ktor setup to cloud deployment, was intended to give attendees a clear understanding of how to connect their own server-side components to virtually any API. By simplifying the backend development process, Ktor enables mobile developers to potentially take on more full-stack responsibilities, leading to greater control over their application’s entire architecture and a faster development cycle for new features. He hoped his session would provide the confidence needed for mobile developers to start building their own server-side solutions with Kotlin and Ktor.

Links:

PostHeaderIcon [DevoxxPL2019] Design Principles in Contemporary JavaScript Frameworks: A Comparative Analysis

Lecturer

Tomasz Ducin operates as an autonomous software specialist through Developer Jutra, delivering expertise in JavaScript ecosystems, architectural consultations, and educational programs on frameworks like Angular and React.

Abstract

This exploration dissects the underlying architectural choices in prominent JavaScript libraries, transcending mere syntax to probe rendering efficiencies, state coordination, and flow controls. It contrasts early tools like jQuery with advanced ones including Angular, React, Vue, and state handlers like Redux, assessing declarative versus imperative methods, virtual DOM diffing, and reactive streams. Via illustrative codes and tradeoff evaluations, it illuminates techniques for boosting efficiency, sustainability, and component reuse, while reflecting on consequences for development teams and project longevity.

Shifting from Manual DOM Handling to Structured Binding: Early Innovations

Web development’s trajectory has moved from direct element manipulation to abstract declarations, reshaping interaction with user interfaces. Tomasz initiates with jQuery, launched in 2006, which streamlined browser APIs for JavaScript and CSS, easing cross-browser inconsistencies prevalent then.

In jQuery-driven apps, state scatters across components, lacking centralized ownership. This scatters responsibility, complicating synchronization; updates demand explicit calls, risking oversights. Dynamic UIs exacerbate issues: rendering new elements requires attaching listeners, potentially duplicating without detachment, fostering leaks.

Couplings tighten as events link disparate parts directly, sans intermediaries. Debugging proves challenging, necessitating stepwise traces through entangled flows. Contextualized in pre-modern browsers, jQuery prioritized expediency over structure, but as APIs matured, its necessity waned.

AngularJS (2009) introduced injections for modularity and bidirectional bindings via dirty-checking—a cyclical poll detecting alterations. This automates refreshes but burdens performance in expansive scopes, as digests iterate watchers repeatedly.

For exchange calculations, bindings tie views to models, but deep nesting amplifies checks. Optimizations like one-way bindings curb this, yet loops cap at 10 to avert infinities.

Analytically, this declarative leap—stating desired outcomes over steps—curtails boilerplate, though polling inefficiency spurred refinements. Ramifications: boosted productivity, but in sizable projects, it mandates watchful optimizations to sustain responsiveness.

Efficient Rendering Via Virtual Representations and Proxies: Modern Optimizations

Advanced libraries refine change detection, favoring notifications over scans for precision. Angular (2016) employs zone.js to intercept asyncs, initiating targeted detections. Components, modular via decorators, separate concerns; OnPush strategies limit checks to input shifts or marks, optimizing trees.

React (2013) pioneers virtual DOMs—abstract trees diffed against actuals for minimal patches. Functional rendering via JSX yields pure outputs from props/state:

const Exchange = ({ amount, rate }) => <div>{amount / rate}</div>;

Hooks like useState localize state, triggering subtree refreshes on mutations. Vue (2014) merges templating with reactivity, proxying objects for granular tracking, compiling to efficient updates.

Svelte diverges, compiling to imperative code at build, eliminating runtime overheads for lean bundles.

Methodologically, virtual diffs compute changes optimally, but large trees inflate costs. Proxies enable fine reactivity, as in Vue’s getters/setters intercepting mutations.

Consequences: superior performance in interactive apps, though initial learning for hooks or proxies. In collaborative settings, this encourages composable units, diminishing global state entanglements.

Centralized State and Unidirectional Flows: Ensuring Predictability

Dispersed state invites inconsistencies; Redux (2015) consolidates into stores, with actions invoking pure reducers for immutable updates. Flows unidirectional: dispatches alter stores, subscribers refresh views.

In banking apps, actions log transfers, reducers compute balances. NgRx adapts for Angular with observables, effects isolating impurities.

Vuex mirrors, centralizing mutations. Analytically, immutability aids traceability, time-travel debugging replaying actions. Yet, verbosity in actions/reducers can bloat code; thunks/sagas manage asynchrony.

Pub/sub alternatives suit simpler needs, emitting events for loose couplings.

Ramifications: excels in auditable systems, but overkill for basics. Micro-frontends integrate disparate states via events or shared stores, avoiding monolithic rewrites.

Modular Decomposition with Micro-Frontends: Facilitating Independent Evolution

Diversified codebases challenge uniformity; micro-frontends permit autonomous teams deploying fragments. Tomasz outlines iframing for isolation or bundling with hosts bootstrapping subs on navigation.

Hosts aggregate events, ensuring cohesion. Methodologically, this decouples lifecycles, enabling framework-agnostic compositions—React beside Angular.

Analytically, it mirrors microservices, but browser constraints like shared DOM demand coordination. Implications: accelerates velocity in large orgs, though integration testing complicates.

In sum, these principles guide selections: functional for concise performance, object-oriented for familiarity, centralized for predictability, modular for scalability.

Links:

PostHeaderIcon [SpringIO2019] Spring I/O 2019 Keynote: Spring Framework 5.2, Reactive Programming, Kotlin, and Coroutines

The Spring I/O 2019 Keynote, featuring Juergen Hoeller, Ben Hale, Violeta Georgieva, and Sébastien Deleuze, offered a comprehensive overview of the latest developments and future directions within the Spring ecosystem. The keynote covered significant themes, including the advancements in Spring Framework 5.2, enhancements in Reactive programming, and the growing importance of Kotlin and coroutines in Spring applications.

The keynote served as a crucial update for the Spring community, highlighting how the framework continues to evolve to meet modern application development needs, from high-performance reactive systems to seamless integration with modern languages like Kotlin.

Spring Framework 5.2 Themes

Juergen Hoeller, co-founder and project lead of the Spring Framework, presented the key themes for Spring Framework 5.2. These themes focused on refining existing capabilities and introducing new features to enhance developer experience and application performance. While specific details were covered, the overarching goal was to continue Spring’s tradition of providing a robust and flexible foundation for enterprise applications.

Improvements to Reactive: Core/UX, R2DBC, RSocket

Ben Hale and Violeta Georgieva discussed the ongoing advancements in Reactive programming within the Spring ecosystem. They highlighted improvements to the core Reactive capabilities, focusing on enhancing user experience (UX) and developer productivity. The session also delved into R2DBC (Reactive Relational Database Connectivity), a specification for reactive programming with relational databases, and RSocket, an application-level protocol for reactive stream communication. These developments underscore Spring’s commitment to building highly scalable and responsive applications.

Kotlin and Coroutines

Sébastien Deleuze focused on the deepening integration of Kotlin and coroutines within Spring. Kotlin’s concise syntax and functional programming features, combined with the power of coroutines for asynchronous programming, offer significant benefits for modern Spring applications. Deleuze demonstrated how these technologies enable developers to write more expressive, performant, and maintainable code, further solidifying Kotlin as a first-class language for Spring development.

The Evolution of the Spring Ecosystem

The keynote collectively showcased Spring’s continuous evolution, driven by innovation and community feedback. The speakers emphasized how Spring is adapting to new paradigms in software development, such as reactive programming and multi-language support, while maintaining its core principles of productivity and flexibility. The discussions provided a roadmap for developers to leverage the latest features and best practices for building next-generation applications.

Conclusion

The Spring I/O 2019 Keynote offered a compelling vision for the future of Spring, demonstrating its adaptability and continued relevance in the rapidly changing landscape of software development. Attendees gained valuable insights into key areas of focus and practical applications of the latest Spring technologies.

PostHeaderIcon [ScalaDays 2019] Scala Best Practices Unveiled

At ScalaDays Lausanne 2019, Nicolas Rinaudo, CTO of Besedo, delivered a candid and insightful talk on Scala best practices, drawing from his experience merging Node, Java, and Scala teams. Speaking at EPFL’s 10th anniversary conference, Nicolas shared pitfalls he wished he’d known as a beginner, from array comparisons to exceptions, offering practical solutions. His interactive approach—challenging the audience to spot code issues—drew laughter, applause, and questions on tools like Scalafix, making his session a highlight for developers seeking to write robust Scala code.

Array Comparisons and Type Annotations

Nicolas began with a deceptive array comparison using ==, which fails due to arrays’ reference equality on the JVM, unlike other Scala collections. Beginners from Java or JavaScript backgrounds often stumble here, expecting value equality. The fix, sameElements, ensures correct comparisons, while Scala 3’s immutable arrays behave sanely. Another common error is omitting type annotations on public methods. Without explicit types, the compiler may infer overly broad types like Some instead of Option, risking binary compatibility issues in libraries. Nicolas advised always annotating public members, noting Scala 3’s requirement for implicit members, though the core issue persists, emphasizing vigilance for maintainable code.

Sealed Traits and Case Classes

Enumerations in Scala, Nicolas warned, are treacherous, allowing non-exhaustive pattern matches that compile but crash at runtime. Sealed traits, with subtypes declared in the same file, enable the compiler to enforce exhaustive matching, preventing such failures. He recommended enabling fatal warnings to catch these issues. Similarly, non-final case classes can be extended, leading to unexpected equality behaviors, like two distinct objects comparing equal due to inherited methods. Making case classes final avoids this, though Scala’s default remains unchanged even in Scala 3. Nicolas also noted that sealed traits aren’t foolproof—subtypes can be extended unless final, a subtlety that surprises learners but is manageable with disciplined design.

Exceptions and Referential Transparency

Exceptions, common in Java, disrupt Scala’s referential transparency, where expressions should be replaceable with their values without altering behavior. Nicolas likened exceptions to goto statements, as their origin is untraceable, and Scala’s unchecked exceptions evade compile-time checks. For instance, parsing a string to an integer may throw a NumberFormatException, but most inputs fail, making it a common case unsuitable for exceptions. Instead, use Option for absent values, Either for errors with context, or Try for Java interop. These encode errors in return types, enhancing predictability. Scala 3 offers no changes here, so Nicolas’s advice remains critical for writing transparent, robust code.

Enforcing Best Practices

To prevent these pitfalls, Nicolas advocated rigorous code reviews, citing research showing reduced defects. Automated tools like WartRemover, Scalafix, Scapegoat, and Scalastyle detect issues during builds, though some, like WartRemover’s strict defaults, may need tuning. Migrating to Scala 3 addresses many problems, such as implicit conversions and enumeration ambiguities, with features like the enum keyword and explicit import rules. Nicolas invited the audience to share additional practices, pointing to his companion website for detailed articles. His acknowledgment of Scala contributors, especially for Scala 3 insights, underscored the community’s role in evolving best practices, making his talk a call to action for cleaner coding.

Hashtags: #ScalaDays2019 #Scala #BestPractices #FunctionalProgramming