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.