Recent Posts
Archives

Posts Tagged ‘DomainDrivenDesign’

PostHeaderIcon [NDCMelbourne2025] Preventing Emu Wars with Domain-Driven Design – Lee Dunkley

In an engaging and humorous presentation at NDC Melbourne 2025, Lee Dunkley explores how Domain-Driven Design (DDD) can prevent software projects from spiraling into chaotic, unmaintainable codebases—likening such failures to Australia’s infamous Emu War. By drawing parallels between historical missteps and common software development pitfalls, Lee illustrates how DDD practices, such as event storming and ubiquitous language, can steer teams toward solving the right problems, thereby enhancing maintainability and extensibility.

The Emu War: A Cautionary Tale for Coders

Lee begins with a whimsical analogy, recounting Australia’s 1930s Emu War, where soldiers armed with machine guns failed to curb an overwhelming emu population devastating crops. The emus’ agility and sheer numbers outmatched the military’s efforts, leading to a humbling defeat. Lee cleverly translates this to software development, where throwing endless code at a problem—akin to deploying infinite soldiers—often results in a complex, bug-ridden system. This sets the stage for his argument: without proper problem definition, developers risk creating their own unmanageable “emu wars.”

He illustrates this with a hypothetical coding scenario where a client demands a solution to “kill all the pesky emus.” Developers might churn out classes and methods, only to face mounting complexity and bugs, such as emus “upgrading to T-Rexes.” The lesson? Simply writing more code doesn’t address the root issue, much like the Emu War’s flawed strategy failed to protect farmers’ crops.

Modeling Smells in E-Commerce

Transitioning to a more practical domain, Lee applies the Emu War analogy to an e-commerce platform tasked with implementing an “update order” feature. Initially, the solution seems straightforward: create an endpoint to modify orders. However, as Lee demonstrates, this leads to bugs like customers receiving too many items, being undercharged, or getting empty boxes. These issues arise because the vague “update order” requirement invites a cascade of edge cases and race conditions.

By examining the system’s event timeline, Lee highlights how an “order updated” event disrupts critical processes like payment capture and stock reservation. This modeling smell—where a generic action undermines system integrity—mirrors the Emu War’s misaligned objectives. The real problem, Lee argues, lies in failing to define the business’s true needs, resulting in a codebase that’s hard to test and extend.

Refining with Domain-Driven Design

Here, Lee introduces DDD as a remedy, emphasizing techniques like event storming and the five whys to uncover the true problem space. Revisiting the Emu War, he applies the five whys to reveal that the goal wasn’t to kill emus but to secure employment for returning soldiers. Similarly, in the e-commerce case, the “update order” request masks specific needs: ensuring shoppers receive only desired items, adding forgotten items, and canceling orders.

By reframing these needs, Lee proposes targeted solutions, such as a “supplementary order” endpoint for adding items and a time-bound “order received” event to allow cancellations without disrupting the system. These solutions, rooted in DDD’s ubiquitous language, reduce complexity by aligning the code with business intent, avoiding the pitfalls of generic actions like “update.”

Simplicity Through Abstraction

Lee challenges the notion that complex problems demand complex solutions. Through DDD, he shows how elevating the level of abstraction—by focusing on precise business goals—eliminates unnecessary complexity. In the e-commerce example, replacing the problematic “update order” endpoint with simpler, purpose-specific endpoints demonstrates how DDD fosters maintainable, extensible code.

He acknowledges the challenges of implementing such changes in live systems, where breaking changes can be daunting. However, Lee argues that aligning solutions with the problem space is worth the effort, as it prevents the codebase from becoming a “Frankenstein’s monster” burdened by accidental complexity.

Conclusion: Avoiding Your Own Emu War

Lee wraps up by urging developers to wield their coding “superpower” wisely. Instead of burying problems under an avalanche of code, he advocates for DDD practices to ensure solutions reflect the business’s true needs. By employing event storming, refining ubiquitous language, and questioning requirements with the five whys, developers can avoid fighting futile, unmaintainable battles.

This talk serves as a compelling reminder that thoughtful problem definition is the cornerstone of effective software development. Lee’s blend of humor and practical insights makes a strong case for embracing DDD to create robust, adaptable systems.

PostHeaderIcon [DevoxxBE2023] REST Next Level: Crafting Domain-Driven Web APIs by Julien Topçu

At Devoxx Belgium 2023, Julien Topçu, a technical coach at Shadow, delivered a compelling session on elevating REST APIs by embedding domain-driven design principles. With a rich background in crafting software using Domain-Driven Design (DDD), Extreme Programming, and Kanban, Julien illuminated the pitfalls of traditional REST implementations and proposed a transformative approach to encapsulate business intent within APIs. His talk, centered around a fictional space travel booking system, demonstrated how to align APIs with user actions, preserve business workflows, and enhance consumer experience through hypermedia controls. Through a blend of theoretical insights and practical demonstrations, Julien showcased a methodology to create APIs that are not only functional but also semantically rich and workflow-driven.

The Pitfalls of Traditional REST APIs

Julien began by highlighting a pervasive issue in software architecture: the loss of business intent when translating domain logic into REST APIs. Typically, business logic resides in the backend to avoid duplication across consumers like web or mobile applications. However, REST’s uniform interface, with its limited vocabulary of CRUD operations (Create, Read, Update, Delete), often distorts this logic. For instance, in a train reservation system, a user’s intent to “search for trains” is reduced to “create a search resource,” stripping away domain-specific semantics like destinations or schedules. This mismatch, Julien argued, stems from REST’s standardized approach, formalized by Roy Fielding in his PhD thesis, which prioritizes simplicity over application-specific needs. As a result, APIs lose expressiveness, forcing consumers to reconstruct business workflows, leading to what Julien termed “accidental complexity of adaptation.”

To illustrate, Julien presented a scenario where a user performs a search for space trains from Earth to the Moon. The traditional REST API translates this into a POST request to create a search resource, devoid of domain context. This not only obscures the user’s intent but also couples consumers to the backend’s implementation, making changes—like switching from “bound” to “journey index” for multi-destination trips—disruptive. Julien’s live demo underscored this fragility: altering a request parameter broke the API, highlighting the risks of tight coupling between consumers and backend models.

Encapsulating Business Intent with Semantic Endpoints

To address these shortcomings, Julien proposed aligning REST endpoints with user actions rather than backend models. Instead of exposing implementation details, such as updating a sub-resource like “selection” within a search, APIs should reflect behaviors like “select a space train with a fare.” This approach involves using classifiers in URLs, such as POST /searches/{id}/spacetrains/{number}/fares/{code}/select, which clearly convey the intent of selecting a fare for a specific train. Julien emphasized that this does not violate REST principles, debunking the myth that verbs in URLs are forbidden. As long as verbs align with HTTP methods (e.g., POST for creating a resource), they enhance semantic clarity without breaking the uniform interface.

This shift decouples consumers from the backend’s internal structure. For example, changing the backend’s data model (e.g., using booleans instead of a selection object) no longer impacts consumers, as the API exposes behaviors rather than state. Julien’s demo further showcased this by demonstrating how a frontend could adapt to backend changes (e.g., from “bound” to “journey index”) without modification, thanks to semantic endpoints. This approach not only preserves business intent but also simplifies consumer logic, reducing the cognitive load of interpreting CRUD-based APIs.

Encapsulating Workflows with Hypermedia Controls

A critical challenge Julien addressed is the lack of workflow definition in traditional REST APIs. Typically, consumers must hardcode business workflows, such as the sequence of selecting outbound and inbound trains before booking. This leads to duplicated logic and potential errors, like displaying a booking button prematurely. Julien introduced hypermedia controls, specifically HATEOAS (Hypermedia As The Engine Of Application State), as a solution. By embedding links in API responses, the backend can guide consumers through the workflow dynamically.

In his demo, Julien showed how a search response includes links like select-outbound and all-inbounds, which guide the consumer to the next valid actions. For instance, after selecting an outbound train, the response provides a link to select an inbound train, ensuring only compatible options are available. This encapsulation of workflow logic in the backend eliminates the need for consumers to understand the sequence of actions, reducing errors and enhancing maintainability. Julien highlighted that this approach, part of the Richardson Maturity Model’s Level 3, makes APIs discoverable and resilient to backend changes, as consumers rely on links rather than hardcoded URLs.

Practical Implementation and Limitations

Julien’s live coding demo brought these concepts to life, showcasing a Spring Boot backend in Kotlin that dynamically generates links based on the application state. For example, the create-booking link only appears when the selection is complete, ensuring consumers cannot book prematurely. This dynamic guidance, facilitated by Spring HATEOAS, allows the frontend to display UI elements like the booking button based solely on available links, streamlining development and enhancing user experience.

However, Julien acknowledged limitations. For complex forms requiring extensive user input, the hypermedia approach may need supplementation with predefined payloads, as consumers must know what data to send. Additionally, long URLs, while not a practical issue in Julien’s experience at Expedia, could pose challenges in some contexts. Despite these constraints, the approach excels in domains with well-defined workflows, offering a robust framework for building expressive, maintainable APIs.

Conclusion: A New Paradigm for REST APIs

Julien’s session at Devoxx Belgium 2023 offered a transformative vision for REST APIs, emphasizing the power of domain-driven design and hypermedia controls. By aligning endpoints with user actions, encapsulating behaviors, and guiding workflows through links, developers can create APIs that are both semantically rich and resilient to change. This approach not only enhances consumer experience but also aligns with the principles of DDD, ensuring that business intent remains at the forefront of API design. Julien’s practical insights and engaging demo left attendees inspired to rethink their API strategies, fostering a deeper appreciation for REST’s potential when infused with domain-driven principles.

Links:

PostHeaderIcon [PHPForumParis2022] Exploring DDD and Functional Programming Practices – Benjamin Rambaud

Benjamin Rambaud, an accomplished PHP engineer at ekino, delivered an engaging presentation at PHP Forum Paris 2022, inviting developers to explore Domain-Driven Design (DDD) and functional programming to enhance their craft. With a nod to the collaborative spirit of the event, Benjamin adopted a market-like metaphor, encouraging attendees to “pick and choose” principles from DDD and functional programming to enrich their PHP projects. His talk, informed by his role as a co-organizer of AFUP Bordeaux, offered practical insights into improving code quality and project communication, drawing from established methodologies while urging developers to adapt them thoughtfully.

Foundations of Domain-Driven Design

Benjamin opened by demystifying DDD, a methodology focused on modeling complex business domains with precision. He emphasized the Ubiquitous Language, a shared vocabulary that aligns developers, stakeholders, and domain experts, fostering clearer communication. By prioritizing domain logic over technical details, DDD isolates business rules, making code more maintainable and expressive. Benjamin illustrated this with examples from his work at ekino, showing how DDD’s strategic patterns, like bounded contexts, help developers encapsulate business logic effectively, reducing framework dependency.

Leveraging Functional Programming

Shifting to functional programming, Benjamin highlighted its synergy with PHP’s multi-paradigm nature. He introduced concepts like pure functions, immutability, and value objects, which enhance testability and predictability. By integrating these principles, developers can create robust, error-resistant codebases. Benjamin drew from his experience with Drupal, demonstrating how functional programming complements DDD by isolating domain logic from framework-specific code, allowing for greater flexibility and maintainability in PHP projects.

Practical Implementation and Hexagonal Architecture

Delving into practical applications, Benjamin advocated for hexagonal architecture as a cornerstone of DDD in PHP. This approach uses ports and adapters to decouple business logic from external systems, enabling seamless integration with frameworks like Symfony. He cautioned against rigid adherence to frameworks, referencing resources like Mathias Verraes’ blog for deeper insights into DDD patterns. Benjamin’s practical advice, grounded in real-world examples, encouraged developers to experiment with repositories and interfaces tailored to their project’s needs, fostering adaptable and resilient code.

Balancing Frameworks and Principles

Concluding, Benjamin urged developers to understand their frameworks deeply while embracing external paradigms to avoid being constrained by default configurations. He emphasized that DDD and functional programming are not rigid doctrines but flexible tools to be adapted contextually. By encouraging exploration of languages like Elixir or OCaml, Benjamin inspired attendees to broaden their perspectives, enhancing their ability to craft high-quality, business-aligned PHP applications through thoughtful experimentation.

Links:

PostHeaderIcon [PHPForumParis2022] Breaking Out of the Framework – Robin Chalas

Robin Chalas, an architect at Les-Tilleuls.coop, captivated attendees at PHP Forum Paris 2022 with a thought-provoking exploration of decoupling code from the Symfony framework. Stepping in for another speaker, Robin challenged developers to rethink their reliance on frameworks, advocating for architectures that prioritize maintainability and flexibility. Drawing from his experience with API Platform and Domain-Driven Design (DDD), he offered practical strategies for creating sustainable, framework-agnostic codebases.

The Pitfalls of Framework Dependency

Robin began by addressing a recurring question in Symfony projects: “Should I modify the framework’s defaults?” He argued that tight coupling to Symfony’s conventions can hinder long-term maintainability, especially as projects evolve. By relying heavily on framework-specific features, developers risk creating codebases that are difficult to adapt or migrate. Robin emphasized the need to balance Symfony’s convenience with architectural independence, setting the stage for a deeper discussion on decoupling strategies.

Embracing Domain-Driven Design

Drawing inspiration from Mathias Noback’s Recipes for Decoupling, Robin introduced DDD as a methodology to reduce framework adherence. He explained how DDD encourages developers to focus on domain logic, encapsulating business rules in standalone entities rather than framework-dependent components. By structuring code around domain concepts, developers can create applications that are easier to test and maintain. Robin highlighted practical examples from Les-Tilleuls’ work with API Platform, demonstrating how DDD enhances code portability across frameworks.

Practical Steps for Decoupling

Robin shared actionable techniques for reducing framework dependency, such as abstracting service layers and using dependency injection effectively. He advocated for modular architectures that allow components to function independently of Symfony’s ecosystem. Referencing Les-Tilleuls’ DDD-focused workshops, Robin encouraged developers to experiment with these patterns, emphasizing their benefits in creating maintainable code. He also addressed the trade-offs, noting that while decoupling requires initial effort, it yields significant long-term gains in flexibility.

Inspiring Community Collaboration

Concluding, Robin invited developers to engage with Les-Tilleuls’ open-source initiatives and explore DDD through resources like Mathias Noback’s writings. He emphasized the cooperative’s commitment to mentoring teams in adopting advanced architectures. By sharing his expertise, Robin inspired attendees to rethink their approach to Symfony, fostering a community-driven push toward more resilient and adaptable codebases.

Links:

PostHeaderIcon [KotlinConf2018] Crafting Fluent Internal DSLs in Kotlin: Venkat Subramaniam’s Guide to Domain-Specific Languages

Lecturer

Dr. Venkat Subramaniam is an award-winning author, founder of Agile Developer, Inc., and a professor at the University of Houston. He mentors developers globally and has authored books like Practices of an Agile Developer. Relevant links: Agile Developer Website (publications); LinkedIn Profile (professional page).

Abstract

This article delves into Venkat Subramaniam’s exploration of creating internal domain-specific languages (DSLs) in Kotlin. Set in the context of reducing code ceremony, it analyzes Kotlin’s features like infix notation and implicit receivers. Methodologies for fluent APIs and implications for domain-driven design are highlighted, emphasizing Kotlin’s suitability for expressive DSLs.

Introduction and Context

Venkat Subramaniam presented at KotlinConf 2018 on crafting internal DSLs, which offer concise, context-aware syntax for specific domains. Kotlin’s low-ceremony nature and behavioral injection make it ideal for DSLs, unlike Java’s rigidity. This narrative unfolds where developers seek to encapsulate domain logic fluently, enhancing readability and maintainability in agile projects.

Methodological Approaches to DSL Creation

Subramaniam began with DSL characteristics: fluency, conciseness, and implicit context. He used Kotlin’s infix functions for natural syntax (e.g., 1 plus 2). Lambda-with-receiver enabled context objects, allowing methods like left or right within a scope. Extension functions injected behavior, while lexical scoping resolved properties dynamically. Examples included a report DSL, where configurations were set declaratively, and a context-switching DSL for flexible execution.

Analysis of Innovations and Features

Kotlin’s infix notation innovates by mimicking natural language, reducing syntactic noise. Implicit receivers create intuitive contexts, unlike Java’s explicit calls. Extension functions enable seamless domain extensions. Compared to external DSLs, internal DSLs leverage Kotlin’s compiler safety. Limitations include working within Kotlin’s constraints, requiring careful design to avoid ambiguity.

Implications and Consequences

Subramaniam’s DSLs imply more readable domain code, aligning with business logic. They enhance maintainability in complex systems, though require upfront design effort. Consequences include broader adoption of Kotlin for domain-driven projects, with open-source examples fostering community contributions.

Conclusion

Subramaniam’s guide underscores Kotlin’s prowess for internal DSLs, offering a blueprint for fluent, maintainable domain code that elevates software design.

Links

PostHeaderIcon [DevoxxUS2017] The Hardest Part of Microservices: Your Data by Christian Posta

At DevoxxUS2017, Christian Posta, a Principal Middleware Specialist at Red Hat, delivered an insightful presentation on the complexities of managing data in microservices architectures. Drawing from his extensive experience with distributed systems and open-source projects like Apache Kafka and Apache Camel, Christian explored how Domain-Driven Design (DDD) helps address data challenges. His talk, inspired by his blog post on ceposta Technology Blog, emphasized the importance of defining clear boundaries and leveraging event-driven technologies to achieve scalable, autonomous systems. This post delves into the key themes of Christian’s session, offering a comprehensive look at navigating data in microservices.

Understanding the Domain with DDD

Christian Posta began by addressing the critical need to understand the business domain when building microservices. He highlighted how DDD provides a framework for modeling complex domains by defining bounded contexts, entities, and aggregates. Using the example of a “book,” Christian illustrated how context shapes data definitions, such as distinguishing between a book as a single title versus multiple copies in a bookstore. This clarity, he argued, is essential for enterprises, where domains like insurance or finance are far more intricate than those of internet giants like Netflix. By grounding microservices in DDD, developers can create explicit boundaries that align with business needs, reducing ambiguity and fostering autonomy.

Defining Transactional Boundaries

Transitioning to transactional boundaries, Christian emphasized minimizing the scope of atomic operations to enhance scalability. He critiqued the traditional reliance on single, ACID-compliant databases, which often leads to brittle systems when applied to distributed architectures. Instead, he advocated for identifying the smallest units of business invariants, such as a single booking in a travel system, and managing them within bounded contexts. Christian’s insights, drawn from real-world projects, underscored the pitfalls of synchronous communication and the need for explicit boundaries to avoid coordination challenges like two-phase commits across services.

Event-Driven Communication with Apache Kafka

A core focus of Christian’s talk was the role of event-driven architectures in decoupling microservices. He introduced Apache Kafka as a backbone for streaming immutable events, enabling services to communicate without tight coupling. Christian explained how Kafka’s publish-subscribe model supports scalability and fault tolerance, allowing services to process events at their own pace. He highlighted practical applications, such as using Kafka to propagate changes across bounded contexts, ensuring eventual consistency while maintaining service autonomy. His demo showcased Kafka’s integration with microservices, illustrating its power in handling distributed data.

Leveraging Debezium for Data Synchronization

Christian also explored Debezium, an open-source platform for change data capture, to address historical data synchronization. He described how Debezium’s MySQL connector captures consistent snapshots and streams binlog changes to Kafka, enabling services to access past and present data. This approach, he noted, supports use cases where services need to synchronize from a specific point, such as “data from Monday.” Christian’s practical example demonstrated Debezium’s role in maintaining data integrity across distributed systems, reinforcing its value in microservices architectures.

Integrating Apache Camel for Robust Connectivity

Delving into connectivity, Christian showcased Apache Camel as a versatile integration framework for microservices. He explained how Camel facilitates communication between services by providing routing and transformation capabilities, complementing Kafka’s event streaming. Christian’s live demo illustrated Camel’s role in orchestrating data flows, ensuring seamless integration across heterogeneous systems. His experience as a committer on Camel underscored its reliability in building resilient microservices, particularly for enterprises transitioning from monolithic architectures.

Practical Implementation and Lessons Learned

Concluding, Christian presented a working example that tied together DDD, Kafka, Camel, and Debezium, demonstrating a cohesive microservices system. He emphasized the importance of explicit identity management, such as handling foreign keys across services, to maintain data integrity. Christian’s lessons, drawn from his work at Red Hat, highlighted the need for collaboration between developers and business stakeholders to refine domain models. His call to action encouraged attendees to explore these technologies and contribute to their open-source communities, fostering innovation in distributed systems.

Links:

PostHeaderIcon [ScalaDaysNewYork2016] Domain-Driven Design and Onion Architecture in Scala

Wade Waldron, a senior consultant at Lightbend and co-author of Applied Akka Patterns, presented a compelling case for combining Domain-Driven Design (DDD) and Onion Architecture at Scala Days New York 2016. Using the relatable example of frying an egg, Wade illustrated how these methodologies enhance code clarity, maintainability, and portability, leveraging Scala’s expressive features to model complex domains effectively.

Defining the Core Domain

Wade Waldron introduced DDD as a methodology that prioritizes the core domain—the sphere of knowledge central to a system—over peripheral concerns like user interfaces or databases. Using the egg-frying case study, Wade demonstrated how Scala’s case classes and traits enable rapid prototyping of domain models, such as eggs, frying pans, and cooking processes. By focusing on domain rules rather than technology, developers can create stable, reusable code. Wade emphasized that DDD does not require CQRS or event sourcing, though these patterns complement it, allowing flexibility in implementation.

Leveraging Onion Architecture

Onion Architecture, Wade explained, organizes code into concentric layers, with the domain model at the core and infrastructure, like databases, at the outer layers. This structure ensures portability by isolating the domain from external dependencies. In the egg-frying example, repositories and services abstract interactions with external systems, allowing seamless swaps of databases or APIs without altering the core logic. Wade showcased how Scala’s concise syntax supports this layering, enabling developers to maintain clean package structures and focus on business logic.

Enhancing Portability and Testability

A key benefit of combining DDD with Onion Architecture, as Wade highlighted, is the ability to refactor implementations without impacting consumers. By defining clear APIs and using repositories, developers can switch databases or rewrite domain models transparently. Wade shared real-world examples where his team performed live migrations and database swaps unnoticed by users, thanks to the abstraction layers. This approach also simplifies testing, as in-memory repositories can mimic real data stores, enhancing test efficiency and reliability.

Engaging Stakeholders with Domain Language

Wade stressed the importance of using a ubiquitous language in DDD to align developers and stakeholders. In the egg-frying scenario, terms like “fry” and “cook” bridge technical and non-technical discussions, ensuring clarity. However, Wade acknowledged challenges in large organizations where stakeholders may focus on technical details. He advised persistently steering conversations back to the domain level, fostering a shared understanding that drives effective collaboration and reduces miscommunication.

Links: