Sławek Sobótka

Ports and Adapters architecture

This video was recorded on http://wrocloverb.com. You should follow us at https://twitter.com/wrocloverb. See you next year!

Ports and Adapters architecture is a synthesis of the modern software engineering.
In its flexible Micro Kernel we will find a place for Domain Driven Design, Command-query Responsibility Segregation, Event Sourcing and plugins.
Kernel is protected by hard shell of Ports, which provides testability, scalability and SOA-Ready strategy. However, the outer aura made of Adapters opens system for: multi-device capability, Event Driven Architecture, Rest and Saga.
Everything is integrated within elegant "Hexagon" where there is "A place for everything and everything in its place".
During the presentation, I'll encourage you to communicate and solve problems using visualizing techniques and your visual intelligence.

wroc_love.rb 2013

00:00:18.320 Hello, everyone! My name is Sławek Sobótka, and I'm going to talk about two topics today.
00:00:23.680 The first topic will be basic techniques of Domain Driven Design modeling.
00:00:29.320 The second topic will be Ports and Adapters architecture, according to the language topic from the last presentation.
00:00:37.760 As you can hear, English is not my native language, so I will try to use simple syntax and tenses to make it easier for everyone.
00:00:45.600 Let's start with a short introduction and a little bit of history.
00:00:52.239 My first name is a concatenation of two words from an ancient Slavic language. In Polish, 'slav' means 'slavo', which means someone who cherishes peace.
00:01:05.680 So, I'm a peaceful guy. My last name in this ancient language relates to 'Sabbath', something like Black Sabbath, which was a holiday celebrating the shortest night of the year in June.
00:01:13.200 That's enough about me. Have you ever been in a situation where you had a meeting with IT and business people, and the business side wanted to introduce just a minor change?
00:01:28.119 They need just one little checkbox on the screen, and you find it to be a total disaster from a technical perspective.
00:01:33.560 Have you ever experienced this? It’s a strange phenomenon where despite having the best language and being professional, you find yourself estimating an overly optimistic 100 story points.
00:01:43.320 What's the usual reaction from the business side? They just can't understand the significance of the change. Maybe the mental models of the problem in your head and in theirs are completely different.
00:01:58.360 Have you ever tried using the technical debt metaphor? You should read about it in books and conference papers.
00:02:08.959 Using the technical debt metaphor is useful because business people understand money.
00:02:14.200 Have you ever tried using it? Did anyone share their success stories?
00:02:28.800 What about technical debt? It works; why? Because business people often have a different mental model regarding the current state of the system.
00:02:36.840 In result, you might end up working over the weekend to fix issues.
00:02:43.840 In my career, I have worked on many different types of systems, frameworks, and embedded systems.
00:02:51.800 However, I have spent most of my time in business software as a developer, architect, and team leader.
00:03:02.560 Now, I’m trying to help teams as an outside observer and coach.
00:03:12.399 I've seen many situations where IT people meet with business people, and I can observe the same patterns over and over again.
00:03:26.040 I assume most of you create business software tools that support specific business cases, right?
00:03:31.560 Business software is not rocket science; it’s really not.
00:03:38.560 The only challenge is understanding the business problem.
00:03:46.000 And you don’t need fancy languages. I work in Java, and it’s enough.
00:03:53.840 The issue really lies in understanding what’s happening.
00:04:01.520 That's why I started looking for solutions to this problem about six years ago.
00:04:06.320 I became interested in Domain Driven Design (DDD). In my opinion, it is currently the only complete and coherent approach to handling business problems.
00:04:11.920 DDD focuses specifically on business software, making it a no-brainer for business cases.
00:04:17.759 How many people here have encountered DDD techniques? And how many actively use DDD?
00:04:24.200 What is DDD? Let’s break it down.
00:04:29.440 Our goal is to model business problems, not just the vision or nouns.
00:04:38.560 Have you seen entity-relationship diagrams? They're often just about data structures.
00:04:46.960 It's not just a database schema; it's about understanding what’s happening in the business.
00:04:55.200 In DDD, our model will be implemented directly in the source code: one to one.
00:05:01.240 It’s about driving your design based on the business model.
00:05:08.040 Sometimes, design can be user interface driven, which can lead to unexpected changes.
00:05:14.560 In DDD, we also invest our best resources in the core domains where we see competitive advantages.
00:05:21.760 The domain is basically the sphere of business knowledge.
00:05:27.640 In DDD, there's a process called knowledge crunching, which involves iteratively delving deeper into understanding the problem.
00:05:35.360 You cannot grasp non-trivial problems in one go, like in a waterfall approach.
00:05:42.919 We focus on the core domain, which usually constitutes about 5% of your source code.
00:05:48.760 This is why we create systems: to address supporting domains, which are mundane tasks necessary to add value.
00:05:54.720 For instance, you wouldn’t want to implement invoicing repeatedly across different systems.
00:06:01.440 We assume the core domain is the main source of system complexity.
00:06:09.040 According to complexity theory, there are two kinds of complexity: essential and accidental.
00:06:15.440 Essential complexity is the natural complexity of the problem, and you cannot reduce it.
00:06:21.600 Accidental complexity comes from your approach to solutions; it’s something you can manage.
00:06:32.080 In DDD, we focus on managing essential complexity because we aren’t building trivial operations.
00:06:39.760 The main goal of DDD is to manage essential complexity while avoiding accidental complexity.
00:06:48.640 So, DDD is all about the model.
00:06:55.360 Let's take a look at a sample model of a garage.
00:07:02.560 In DDD, a model is produced from conversations between two roles: the domain expert and the modeler.
00:07:10.480 The domain expert is someone who understands what is happening in the business.
00:07:17.120 You recognize them because when there is a problem, all the business people turn to the domain expert.
00:07:24.320 The modeler should be a hands-on developer since the model needs to be implemented one to one with the source code.
00:07:30.960 The model is the product of the collaboration between these two roles.
00:07:37.960 This process is not an ineffective one where business people write documents and hand them off to IT.
00:07:45.200 That often leads to misunderstandings.
00:07:54.480 Instead, we meet in a modeling session and use a process called modeling workshops.
00:08:02.160 In these workshops, the domain expert shares their knowledge with the modeler.
00:08:11.760 The modeler presents the model back to the domain expert and asks if it reflects their understanding.
00:08:18.240 The domain expert then can confirm or correct any discrepancies in the model.
00:08:27.600 What’s exciting about DDD is that knowledge also flows from the model back to the domain expert.
00:08:36.080 This allows business people to learn more about their own business through the model.
00:08:43.920 For instance, imagine a business that currently only uses phones to place orders.
00:08:51.600 Once you introduce new software, it fundamentally changes how the business operates.
00:08:58.160 The business will need to learn how to navigate this new environment.
00:09:06.400 Another key point from the Agile Manifesto is productive collaboration.
00:09:16.520 Now imagine a scenario where you want to put a landing pad for a helicopter.
00:09:22.960 Even non-technical stakeholders will realize it doesn’t make much sense.
00:09:30.240 When you have a common understanding of the problem through a shared model, it's easier to discuss technical depths.
00:09:40.560 This common model helps clarify what is possible and helps bridge the gap between technical and non-technical people.
00:09:48.960 So in DDD, we often split the application into layers.
00:09:56.640 We have a presentation layer, logic layer, and infrastructure data layer.
00:10:05.120 In DDD, the logic layer is divided into two: application logic and domain logic.
00:10:12.400 Application logic knows the 'what' of the scenario, while domain logic knows the 'how'.
00:10:20.080 Let's look at a sample model based on an order system.
00:10:26.080 In this model, an order has various line items.
00:10:31.080 Each line includes a product identifier, quantity, and pricing details.
00:10:36.480 It's important to communicate this model clearly, especially to those with traumatic experiences regarding UML.
00:10:44.960 A simple visual representation can often convey much more than complex technical specifications.
00:10:51.680 Throughout this presentation, I will be demonstrating Java, which should be familiar to most software developers.
00:10:59.080 When creating a model in DDD, you utilize standard building blocks. For example, aggregates represent groups of related objects.
00:11:08.560 An aggregate's focus should be on behavior rather than inner structure.
00:11:15.760 For instance, consider a sample aggregate of an order where behavior is prioritized.
00:11:22.960 A domain expert might state, 'I want to add a product to the order with a specified quantity.'
00:11:29.760 Here, 'add product' is a technical detail relevant to the aggregate.
00:11:35.360 While adding, you have to consider invariants: conditions that must hold true.
00:11:41.120 For example, you cannot have two lines in an order referring to the same product.
00:11:49.120 If an already added product is included, you would increase the quantity on the existing line.
00:11:54.320 Another invariant could dictate that each time you add a product, you must recalculate the total cost of the order.
00:12:01.600 Moreover, you cannot add a product to an order that is already closed.
00:12:07.520 So we need to model these invariants and protect them within a coherent aggregate.
00:12:13.760 This approach is basic but effective for defining the boundaries of an aggregate.
00:12:20.480 As the complexity of aggregates increases, we may utilize factories.
00:12:28.960 We can query our domain model to determine what is needed to create an order.
00:12:37.920 The domain expert may indicate that we need a client. Thus, we create the order using the client.
00:12:45.520 We also need to consider constraints such as age or residence, as well as financial requirements.
00:12:52.480 Next, we need to create an invoice, which can involve a bookkeeper.
00:12:59.520 Let’s take a look at a model for invoicing.
00:13:07.040 In this model, you can invoice a single order.
00:13:15.680 But what if requirements change and you need to invoice multiple orders?
00:13:22.640 Or what if you need to invoice only selected items from the order?
00:13:30.080 It's tempting to create an adapter class that composes these orders, but that may complicate your model.
00:13:37.520 Your domain expert might say, 'Don’t hack your model; change it instead.'
00:13:43.520 Adapting your model without re-evaluating its assumptions can lead to 'model hell'.
00:13:50.640 So it would be wise to ask the business people how they would handle various scenarios.
00:13:57.040 We could design an entirely new building block, known as a pricing plan.
00:14:04.640 A pricing plan could serve as a snapshot of a specific point in time.
00:14:11.920 You can present this pricing plan to the user, allowing them to accept the prices.
00:14:20.240 Once accepted, you can copy the state of the pricing plan into a separate aggregate, such as 'purchase'.
00:14:27.040 This can be used as proof of purchase.
00:14:34.440 This way, we’re changing the model instead of compromising it.
00:14:41.040 If we don’t hack our model with state fields, we maintain clarity.
00:14:48.640 For more complex situations, we can implement additional structure through further levels.
00:14:55.440 In DDD, we can conceptualize different levels of model capability.
00:15:02.640 At the foundational level, we have general business resources that remain stable.
00:15:09.760 For example, dealing with money is fundamental in many projects.
00:15:15.760 Many projects might not have a class for money in their standard libraries.
00:15:23.920 Instead, developers often use primitive data types.
00:15:30.400 This approach neglects the complexities that arise with financial calculations.
00:15:37.840 This is why creating a dedicated 'Money' class can be effective for encapsulating such mechanics.
00:15:45.600 This class can help model meaningful operations such as addition or comparison.
00:15:52.960 In DDD, policies can be introduced to model goals, rules, or constraints.
00:15:58.640 For example, a tax policy could be written as part of the invoicing process.
00:16:05.120 The invoicing algorithm could be standardized, while tax calculations might differ by jurisdiction.
00:16:12.480 This design can be implemented as a strategy pattern, allowing for flexible policy management.
00:16:19.760 This policy contains pertinent details required for tax calculation and integrates the feedback from domain experts.
00:16:28.720 In some domains, there might also be a decision support level.
00:16:36.440 For instance, if a product is unavailable, the system can suggest alternatives based on past purchases.
00:16:43.280 This represents a simplified model of how to handle intelligent system behavior.
00:16:50.080 So we outline core rules of the business, and on top of that, we have application scenarios.
00:16:56.560 Many developers prefer to use user stories to convey requirements.
00:17:01.520 While others may favor use cases.
00:17:08.880 Which is better? It often depends on the audience and their understanding.
00:17:14.920 Some prefer concrete examples, while others enjoy abstract discussions.
00:17:22.440 Both story and use case strategies are valid and useful in software development.
00:17:30.480 The application logic acts as an animator, directing domain actors to execute business processes.
00:17:38.160 The flow of requests is specific and structured.
00:17:41.840 This separation means domain knowledge doesn’t leak into application logic.
00:17:48.800 You can publish this as a web service without compromising the structure.
00:17:55.280 Services load aggregates from a repository, avoiding unnecessary complexity from architectural patterns.
00:18:02.720 Keep in mind that we must focus on usable solutions that serve business requirements.
00:18:09.840 Consider a scenario where you need to approve an order.
00:18:16.320 You load aggregates and check whether they meet the preset specifications.
00:18:23.920 If the order cannot be submitted, you might trigger an exception.
00:18:31.520 Then, you can generate an invoice according to your application logic.
00:18:39.840 Your application also decides the applicable tax based on context.
00:18:46.960 Now, let's switch the topic and discuss architecture.
00:18:53.040 What does architecture mean to you? Sometimes it can be jargon that adds no real value.
00:19:01.680 In our domain, architecture is akin to a general style that underpins software design.
00:19:09.359 For instance, hexagonal architecture is a well-known paradigm.
00:19:16.560 Originally, it was designed to support six ports, hence the name.
00:19:22.760 However, with advancements, we now support multiple ports, leading to the renaming of the concept to Ports and Adapters.
00:19:29.760 In this architecture, the kernel serves as a protective shell for the model.
00:19:36.400 Ports are designed to interact with the kernel; we differentiate between offered ports and required ports.
00:19:44.640 Offered ports allow users to operate based on the model, while required ports handle external data operations.
00:19:50.960 Your application can have diverse contexts where varying models may be necessary.
00:19:58.200 Some ports can be adapted to different environments, such as web applications.
00:20:05.760 We can have outer ports that act as repositories, providing flexibility with data storage.
00:20:12.400 For example, data can originate from a traditional database, API, or even other services.
00:20:18.880 These are robust ways to ensure your application is adaptable and efficiently integrated.
00:20:26.560 Within this architecture, an event-publishing mechanism can enhance communication across components.
00:20:35.680 Applying command-query separation helps define how data is handled in the architecture.
00:20:42.960 When we have our hexagonal model, we can easily introduce more modules.
00:20:48.920 In DDD, this is known as bounded context, an idea where the meaning of terms depends on their context.
00:20:56.560 For instance, 'product' may mean something entirely different in inventory management than in sales.
00:21:04.360 That's the reason we categorize these contexts to ensure clarity in communication.
00:21:11.440 This categorization also paves the way for module integration without confusion.
00:21:19.360 In a sample use case, we can have a client relationships management module.
00:21:26.080 Here, we manage events that signify changes in the client’s status.
00:21:33.920 These events are published, and other modules can react accordingly.
00:21:42.520 We also ensure that our domain model remains protected within its context.
00:21:51.240 When events travel across the system, we use lightweight objects to carry data, maintaining separation.
00:21:59.680 Adapters help to glue different contexts together accordingly.
00:22:07.360 Despite the integration, each domain can maintain its integrity and purpose.
00:22:15.120 Moving on next, let's discuss testing and its strategies.
00:22:24.240 Imagine a testing pyramid that suggests having many unit tests and few end-to-end tests.
00:22:30.960 Investing in unit tests is crucial for the kernel of your application.
00:22:39.120 To validate the accuracy of core logic, extensive tests are often necessary.
00:22:46.560 However, achieving high coverage by targeting upper layers might lead to various complexities.
00:22:53.680 Consequently, it's essential to prioritize your domain logic in tests.
00:22:59.760 End-to-end tests serve their purpose for general requirements but may not ensure logical perfection.
00:23:08.080 To summarize, business software isn’t rocket science; comprehension is the primary obstacle.
00:23:15.680 The crucial thing is establishing a common understanding of the problem.
00:23:23.440 Utilizing a shared model helps teams find alignment and clarity.
00:23:31.760 Thank you for your attention!
00:23:46.880 Are there any specific rules or techniques for gathering knowledge from the domain?
00:23:53.600 Yes, DDD encompasses a wealth of techniques, though many of these would take a few more hours to cover comprehensively.
00:24:01.680 Recommended reading is 'Domain Driven Design' by Eric Evans. Even after ten years, it's seminal work.
00:24:10.000 One more question before we conclude.
00:24:18.760 How do you manage persistence with events? Are your domain models aware of the persistence layer?
00:24:24.720 You raised a few important issues. Persisting events is a technique known as event sourcing.
00:24:32.000 However, it’s not suitable for most systems.
00:24:39.680 Typically, persistence utilizes a repository pattern.
00:24:48.000 For example, when creating an invoice, you call the repository to store it.
00:24:55.520 Underlying systems may use an object relational mapping framework.
00:25:03.760 In many scenarios, we encapsulate this in an infrastructure component.
00:25:12.200 I recommend looking into the book 'Implementing Domain Driven Design' by Vernon.
00:25:22.240 It reviews many of these concepts comprehensively.
00:25:28.280 Event sourcing stores a sequence of events that transpired on an aggregate.
00:25:35.760 This allows querying specific states of the aggregate at various points in time.
00:25:43.680 However, it is important to note that event sourcing has its own set of challenges.
00:25:51.520 Indeed, using it for business applications may not be necessary.
00:26:00.080 Thank you all for your engagement! I appreciate the opportunity to discuss these topics.