ALTERNATE UNIVERSE DEV

Serverless Chats

Episode #42: Better Serverless Microservices using Domain Driven Design with Susanne Kaiser

About Susanne Kaiser:

Susanne Kaiser is an independent Tech Consultant from Hamburg, Germany, and was previously working as a startup CTO transforming their SaaS solution from monolith to microservices. She has a background in computer sciences and experience in software development & architecture for more than 15 years and regularly presents at international tech conferences.

WATCH THIS EPISODE ON YOUTUBE: https://www.youtube.com/watch?v=eGYlTfBJBJQ

Transcript:

Jeremy: Hi everyone. I'm Jeremy Daly and you're listening to Serverless Chats. This week, I'm chatting with Susanne Kaiser. Hi Susanne, thanks for joining me.

Susanne: Hi. Thanks for having me.

Jeremy: So, you are an independent tech consultant, so why don't you tell the listeners a little bit about your background and what you've been up to lately.

Susanne: Mm-hmm. So, as an Independent Consultant, I am helping organizations within the broad spectrum of software architecture and design including development to software delivery, or in other words or in shorter terms, helping organizations in building and shipping their digital products. I was also previously working as a startup CTO and I have a background in software development and software architecture of more than 17 years and I also regularly present at international tech conferences as a speaker.

Jeremy: Well, speaking of international tech conferences, I saw one of your talks at ServerlessDays Belfast before we shut down all conferences so no one can get together in person anymore. And, you did a talk about domain driven design and how that applies to serverless and serverless microservices. So, I'd love to talk to you about that today, because I think that is one of those things where software developers ... I don't want to say all software developers ... but a lot of software developers are just really bad at software design, and not just design of architecture and things like that which are in our wheelhouse, but more from the business side of things and understanding what the business needs are, understanding what the technical needs are, and then where that comes together in the middle, and what people should actually be building to solve those customer needs. So, I think that is domain driven design in a nutshell, but maybe you could tell the listeners a little bit about what domain driven design actually is.

Susanne: Yeah, so domain driven design is a software philosophy or methodology created by Eric Evans and it's about to capture the business domain as closely as possible into your software and it comes with a lot of strategic and technical design patterns and practices that I am happy to share with you in a moment. But, it's also, I would like to mention also, from the very beginning, it's not applicable everywhere. So, you should focus on your core domain ... I will explain it in a minute, hopefully, too ... where it makes sense that focusing on complex business logic and have to do with solving problems that have complex business logic behind.

Jeremy: Yeah, and so you had mentioned in your talk, the cost of poor software quality, and the number you gave here was, I want to say it's $2,840,000,000,000 a year in poor software quality, so what are some of these indicators of poor software quality?

Susanne: So, there are no simple measures for bad or good software quality, but there are several metrics that can be used as indicators. For example, an increasing curve of defect trend over the time is an indicator of poor quality software or low test coverage, assuming that as there is good test quality or cyclomatic complexity or large dev of inheritance and high degree of class coupling could also be indicators. Also the amount of effort it takes to understand a piece of code or badly engineered software resulting, for example, from immature or undisciplined practices and using less qualified software engineers or also and one thing is also really important to mention is the lack of domain knowledge and also poor communication and coordination issues and teams, specifically if one of the teams are growing.

Jeremy: Yeah, so that lack of domain knowledge, I would think that sort of gets to the crux of it, right? Because like I said in the beginning, we think we know how to solve a problem and we know how to solve it technically but what we're really trying to do is solve a problem that's very specific to a group of customers, whatever that group of customers might be and those different models could be your inventory system, right, and your inventory teams think of ... They think of inventory in a certain way and then you need software engineers to be able to build a system that makes sense for them -- that uses the same language, that uses the same sort of communication patterns or styles or things like that. What goes into building good software, then? Like what are the main components of building good software?

Susanne: So your domain driven design comes with a core statement that in order to build better software we have to align its software design with the business domain, with the business needs, and the business strategy. So domain driven design helps you with aligning your software design with the business domain needs and the strategy and it's very crucial for building your software solution, because otherwise, you are building something that, for example, are matching the requirements of your users. Instead you have to collaborate intensively with your domain experts to gain domain knowledge and to understand the problem first before you're solving it. We are tending to jump directly into solving a problem technically and, yeah, yeah, we can just let's deploy it on a cubinated cluster, but we have not understood the problem first. That's really crucial to the build better software.

Jeremy: Well, you mentioned the word strategy, which is one of those things where, I don't think a lot of people know what that exactly means. Like what is the strategy and you had talked a lot about Wardley Maps and sort of understanding this landscape and being able to use that to sort of plan your strategy and we can get into some of that more but can you explain Wardley Maps. We've talked about it before but just sort of in the context of domain driven design, how does that help you?

Susanne: Yeah, I really like to combine domain driven design with Wardley Maps, because at first, like when you start the journey to a domain driven design, it's really overwhelming. It was for me, very overwhelming, because there's a lot of new terms and it requires some time to grasp and understand it, and since it's not applicable everywhere, Wardley maps helps you to visualize the journey to domain driven design and so Wardley Maps has been created by Samuel Wardley, a researcher from the UK and a Wardley Map is a representation of the landscape the business is operating in and it's really simple. So it consists of an Y axis for the value chain and then X axis for the evolution stages. A Wardley Map visualizes the evolution of a value chain, so the first question is so what is a value chain? So behind every user need, there is a value chain and start off with the questions like who are your users, who are going to approach you to get their problem solved, and what kind of user needs do these users have. Like what kind of problems they would like to get solved by you and what are the components and activities that are necessary to fulfill these user needs directly or indirectly by facilitating other activities. You have on the Y axis, at the top, we have those components and activities that are visible to your users, so where your users are touching your system and then at the bottom of the Y axis where it becomes more and more invisible to the users. And why you have to identify every component and activity that your value chain is composed of, you take these components and activities and plot it along an evolution axis, the X axis, going from left to right. And at the left of the X axis, we have genesis with brand new things that have never existed before, then custom built, then product and rental such as off the shelf products or open source software and then on the very right like commodity and utilities. The movement of a component or activity along the X axis is determined by its stage of evolution. So it comes also with, Wardley Maps comes also with patterns and principles, too, and for example, one of the pattern is that the map is never steady, they are very dynamic, so everything evolves from left to right, so with the force of supply and demand competition and as the components evolve from left to right, their characteristics change. For example, from the uncharted domain from the left, would be undefined market, it's uncertain, unpredictable, constantly changing and becoming more and more industrialized, going to the right where we enter the domain of the market of known, mature, widespread, commonly understood market itself. And also, one other pattern is like that efficiency enables innovation, so that means that the industrialization of one component enables the, for example, new features of existing products to appear or the evolution of other components or that new components can emerge enabling new user needs. So the evolution of one component and its efficient provision enables the innovation of others. But also that it comes with principles. For example, that you should use appropriate methods per evolution state, so what component should be built in house? These are the components that were residing in the genesis, in the custom built evolution stage, or where to use, buy off the shelf products and open source software so that other components and activities that are residing in the product and rental evolution stage and where to outsource to utility suppliers and these are the components and activities that are located in the commodity and utility evolution stage. And it's really important in order to know, like to use the appropriate methods because it's also like we don't want to ... We'd like to avoid too custom built commodities because we would like to custom build those components and activities that belong to our core domain and that's why I can make then the link to domain driven design later on. But it's also important to know your users and focus on your user needs.

Jeremy: Right.

Susanne: Because the user needs, they are the subject area of what we build software for, right? They are the reason, they are the why of our business domain but before we develop a solution that solves the user needs, we need to understand the problem domain first and that's why I would like bring in domain driven design where the ...

Jeremy: But before we get to that, though, because I don't want to get too far ahead ...

Susanne: Yeah.

Jeremy: Because I think like what you just said, again, like I said, we've talked about Wardley Maps quite a bit before and this idea of moving from this custom built stuff to all the way up to where you just outsource it and it's electricity, right? It's a complete utility. This is really where I think Serverless comes in with how we're planning on building some of these products, because it always used to be, again, you write some custom software that did something. Like right now, it would be crazy for someone to write their own database software, unless for their own company, unless they were building a new product but if you're just, if you need a database, you're not going to say, "I'm just going to write my own database software." Like that's done, like there's a lot of solutions out there and you're going to pick something off the shelf and you're going to run that and then it even has gotten to this point now with a lot of the tools that AWS has is to say, it would be crazy for you to install your own MySQL Cluster, for example, on EC2 instances or on VM somewhere. That would just be crazy because you have RDS and that whole process is not only commoditized in terms of the software that's running but then almost, sort of a utility at this point, by running the actual RDS cluster in the background and managing all the updates and all that kind of stuff for you. That's sort of that great ... and you had mentioned this, you said, this idea of building versus buying versus outsourcing, this is the thing where there are so many pieces of the infrastructure now that have become commoditized in a sense, whether that's SQS or it's even compute with Lambda or Fargate or things like that, that now really I think we're at a time where as technologists, we can focus on building just the things our customer needs and let all that heavy lifting go up to the cloud provider.

Susanne: Yeah, exactly, so it shifts the focus back on the things that are really important to our business and to our customers, right? So instead of handling all these infrastructure and operational complexities, without serverless, for example and that for example, if we are a small team and handle all these infrastructure operational complexities all by ourself, then we don't have time to solve our users' problems and to focus on our core domain and provide, yeah, and focus on our competitive advantage, instead our focus is blurred away and handling all these infrastructure and operational complexities. With serverless, we have the possibility to shift our focus back solving our user's problems first and getting, as you mentioned the undifferentiating heavy lifting and outsource this to cloud providers using serverless technologies for the time being.

Jeremy: Right. Right, so I interrupted you, you were getting into more about domain driven design.

Susanne: Exactly, so one of the principles of a Wardley Map is that we know our users, and focus on our user needs and because that's the why of our business domain, right, but before we develop a solution, because I can talk of myself. I tend to jump in, right into the technical solution without understanding the problem first and-

Jeremy: Right, I think a lot of us do that, yes.

Susanne: It's like, "Oh, yeah, yeah," like first to wire something together and then, "Oh, no" it's not really matching the requirements that our users are looking for.

Jeremy: Right.

Susanne: So we need to understand the problem domain first and that's why I would like to bring in domain driven design, where the collaboration between the domain experience and development teams is an essential part to obtain domain knowledge, and which is described in terms of a shared language, the ubiquitous language. And the domain knowledge is really free of any technical terms itself. It's just the shared language between domain experts and development team. The domain knowledge is very crucial because as mentioned earlier the lack of such can have a huge impact caused by poor quality software.

Jeremy: Right.

Susanne: Yeah, so that's the reason why...

Jeremy: Yeah, no, I was just going to say that's one of those things you keep talking about these sort of two sides, right? You've got the domain driven model or the domain expertise and then you have the technical expertise, and so in terms of taking an approach to building a product, right, there's that ... and this is something you mentioned in your talk where there's sort of those two sides to it, right? There's strategic design side and then there's the tactical design side.

Susanne: Yes.

Jeremy: So maybe we could get into those a little bit.

Susanne: Exactly, and that's also why I would love to combine it with Wardley Maps, domain driven design, combine it with Wardley Maps, because ... so domain driven design comes with patterns and practices and those can be categorized into strategic design and tactical design patterns and practices. And when we entered the field of strategic and tactical design and would like to combine it with Wardley Maps and use the Y axis to visualize that position, and the value chain going from top, the strategic design to further down the tactical design patterns. As I mentioned before, we tend to jump directly into the tactical at the bottom first, before we have covered strategic design and I would like to avoid it by putting Wardley Maps in place, starting from top to down, starting with the strategic design first. So we start at the strategic design within the problem space and that's where we analyze the problem domain and then like discover sub-domains. And problem domain or business domain is a business overall activities, for example, the services a business is providing to its customers and the problem domain is composed of sub-domains. The sub-domains represent a set of interrelated use cases or business processes where ... and we are distilling this problem domain and partitioning them into smaller sub-domains and by partitioning it, the problem domain into smaller sub-domains, we are on the one hand reducing complexities but on the other side we also have to consider that not all sub-domains are equal and some sub-domains are more important and more valuable to the business domain than others. So we have three different kinds of sub-domains, so we have the core, the supporting, and the generic sub-domain. The core sub-domain, that's the essential part of our problem domain, providing the competitive advantage, that are those parts of the system that makes it a success and should be hard for competitors to copy or imitate, so they are supposed to be quite complex, they are supposed to have a complex business logic and they tend to change often. That's the core domain, that's where we have to strategically invest most and innovate on. And that's the sub-domain we need to build in house and this, the core domain that's supposed to go into the genesis and custom build evolution stage of the Wardley Map.

Jeremy: Mm-hmm.

Susanne: And then the other sub-domain type that we have is the supporting sub-domain, so that helps to support the core sub-domain, but does not provide any competitive advantage. So they are quite simple, but do not change very often and if possible, you should look out for buying off the shelf products or open source software. If that's not possible for what reason ever, you should not, you're supposed not to invest heavily in these systems. They should be quite simple, but look ... So these are the supporting sub-domain that should go into the product and rental evolution stage of a Wardley Map. Then the generic sub-domain, these are sub-domains that many large business have. For example, authentication, payment handling, or something like that, so they are on call usually, and provide no competitive advantage but the businesses cannot work without them. So you cannot work without authentication in most cases, but they are generally complex but they are already solved by someone else. The generic sub-domains supposed to go into the commodity and supplier evolution state of a Wardley Map, so we should focus on buying ... or to open to outsource or to utility supplier or if that's not possible, at least have it then part of the ... Can be combined like going into the product and rental or commodity and utility evolution stage. So either buy off the shelf products or use the open source software or outsource to commodity suppliers. So that's how I would like to handle the strategic design combined with Wardley Maps and further down we enter then the tactical design patterns that I will probably talk later about it like that supports making low level design decisions to architect and implement a solution but first we should go, when we go from top to down, we should start with the strategic design first and then go further downward into the technical design later. I mean, it's not necessary to use the technical design, but at least we have to understand the problem domain first, using the strategic design. After we have analyzed the problem domain and distilled the problem domain into sub-domains and also discovered our core domain where we strategically, we have to strategically invest most, we can go further down and switch to the solution space of strategic design and that's where we come to the domain model and later on to the bounded context. So the domain model is at the center of domain driven design and within each sub-domain, a domain order can be created representing the domain logic and the business rule that are relevant to that area of the system, and the domain model comes in different shapes. For example, in the beginning it's formed as analysis model during the collaboration between the domain experts and the development teams. For example, it could be UML diagram or product sketches and later on it can result in a code model when we come to the technical design. And the domain model is described in terms of ubiquitous language and is free of any technical complexities but a model, a domain model cannot exist without a boundary and that's where we come to the bounded context so in that--

Jeremy: Sorry, before we get into that though, because this is one of the things that I think some people get hung up on. It's this idea of ubiquitous language. So I think I mentioned this earlier but I think we should be clear on what exactly we mean by that, because I think for a developer, if you say, "This is a customer," or "This is an order," like that seems pretty straightforward but to a domain expert, something that is, say, a particular status of something, like an order that is pending, that may mean something completely different to a domain expert than it does to a developer. Like a developer says, "Oh, the order's pending." That means, "I just flag it with a pending status." But there could be a whole bunch of other stuff that's involved around what may seem like a very, very simple term. Can you expand more on that ubiquitous language thing, because I think that's really important?

Susanne: Yeah, so it's also like to build in the common understanding, the shared understanding of the domain itself and then through the collaboration, in terms of collaboration between the domain experts and the development teams. During that collaboration, so this misunderstanding has to be to cleared out like for example, what do we understand for like what is a pending status? Like in terms of it's not only a flag in a database, it also comes with business rules.

Jeremy: Right.

Susanne: For example, if an order is pending, then it means, for example, we cannot delete it or something like that. So there are some invariance that we have to check when ... and that are applicable to specific ... yeah, to its domain model and so that means that it comes with a lot of new ... With business rules or invariance that's what they call it in domain driven design, and we have to make it sure that we keep the domain model consistent to protect its integrity within this bounded context and so that means that not only a flag, but also it comes with new, yeah, with a lot of rules and invariance that we have to check.

Jeremy: Alright, I interrupted you. You were talking about bounded context.

Susanne: Yeah, so as mentioned that a domain model cannot exist without a boundary, then that's where we come to bounded context and a bounded context provides different types of boundaries for a domain model so it forms, it form a consistency boundary around the domain model and protects its integrity and it could also form a linguistic and semantic boundary so that the language's terms are only consistent inside of its bounded context. So for example, pending in one bounded context could have a different meaning than another bounded context, for example. And it also serves as an ownership boundary, so for example, bounded context could be implemented and evolved and maintained by one team only and a single team can, on the other hand, can also own multiple bounded context but it's really, really relevant that multiple teams are working on the same bounded context, because this enables a ton of teams working at their bounded contexts independently at their own pace and with minimal impact across other teams.

Jeremy: Yeah.

Susanne: And this also serves as a physical boundary and can be implemented as a separate solution and can be deployed independently as separate artifacts and also enables separate data stores which are not accessible by other bounded contexts and, for example, also the source code could, of each bounded context, can be maintained in separate git repositories with their own CICD pipeline. And also each bounded context can have separate architecture patterns applied and that's where we enter the tactical design area.

Jeremy: Right, and before we get to that though, I just wanted ... Because I think we hear this term bounded context quite a bit when we're talking about microservices and this is exactly what we're talking about here. But that is certainly one of those things where when people move to microservices, it's always how do I ... What is a bounded context? What does that mean? Should I create a billing service? Should I create an inventory service? Should I create an alerting service? Where are the separations there? This is exactly what you want to follow, right? You want to think about all these different ideas, you want to talk about the language barrier. Like if you have two domains that are trying to work with one another, you don't put those into the same bounded context, because the language could be different. The infrastructure could be different, all kinds of things like that. The physical boundary, the ownership boundary, these are all great things, so if you're thinking about building microservices start paying attention to everything that Susanne is saying right now, because this is super important. Sorry, continue.

Susanne: Yeah, no problem at all. So yeah, and each bounded context can have separate architecture or patterns applied. That's what I was mentioning that we enter now the technical design patterns and practices and, for example, one bounded context can go with the layered architecture or where you split your source code into layers such as presentation, business logic and persistence layer, or as a hexagonal architecture, a specific form of the layered architecture ... I'll come to this in a minute ... or for example, I'll CQRS command queries responsible segregation where you split your source code into command models and read models and for updating the state of your domain model or reading the state of your domain model. I would like to highlight the hexagonal architecture a little bit. I know that you have already covered this in a previous podcast already, but it's specifically also combined with serverless when you transform the value chain going from open source to, for example, to serverless. Combined with domain driven design, hexagonal architecture is really helpful because it aims for separation of concerns. It's also called ports and adapters and what it does it creates a loosely coupled software components that can be easily connected to the software environment and by using ports and adaptors. And your softer components are categorized into an outer and inner part where your ports and adapters are used to connect from the outside to the inside and from the inner part to the outside and its core, the inner part, there is the business logic.

And hexagonal architecture makes your components exchangeable and so matter what kind of infrastructure you are using at the outside, the business logic at the inside can remain the same and makes your business logic adaptable for future evolution. So for example, when you started with your core domain, using open source software like MongoDB and using Key Cloak for authentication, something like that, so and you are now shifting to AWS using DynamoDB and using serverless Lambda functions to provide and back end API and in domain driven design your domain model remains the same so it's representing your business logic including your rules, but the infrastructure can be exchanged without touching the inner part of your system.

Jeremy: Yeah, so I mean, ports and adaptors and the hexagonal architecture like we did talk about that before but this is a super important way to build software, especially with serverless. I started doing this actually, after I talked to Slobodan Stojanovic. He was a big fan of it and I said, "Ah, I'll give it a try." Because I would often build in a lot of logic right in Lambda functions or you have some of those calls that aren't quite separated out and I've always been a big fan of building like data access layers, right? So you always build some simple interface to your database so that you don't have to always be writing sequel queries or queries against DynamoDB or something like that. But this great, because it does help you evolve, right? Like as you said, like if you are using MongoDB and then you decide, "Hey, I want to go to DynamoDB," forget about moving data which is a different problem, but in terms of your software, and the architecture that you build or I should say the models that you build, those can stay the same and then you just have to again, sort of swap out that adaptor and have it access X Database, rather than Y Database. So yeah, so then how do you implement some of these business pattens themselves?

Susanne: Yeah, so ...

Jeremy: Or I should say, how do you implement some of these business logic patterns?

Susanne: Each bounded context can be implemented by different business logic implementation patterns. So for example, for our core domain, it could be implemented as a domain model related to our domain driven design, with its building blocks of aggregates, entities, value objects and so on. And so the domain model is an object model of the domain, which incorporates both behavior and data ... but it should not be applied to everywhere. So it copes very well with cases of complex business logic and complex business rules and it's very well suited, as I mentioned for implementing the core sub-domain, which goes into Wardley Maps into the genesis and custom built evolution stage. And so the domain model should be free of technological and infrastructure complexities and I come a bit later to the building blocks of the domain model but I would also like to highlight other business logic implementation patterns that are possible. So there are a lot of ... I just want to highlight two others like the active record, for example. This active records represent a role in a database table of you and they encapsulate the database access and also adds domain logic to the data and it's ... so it carries the data and the behavior and the access to the database itself. So the active record supports cases where business logic is quite simple, but operates a more complex data structure and it's very usable for the supporting sub-domain, and domain design so ...

Jeremy: Yeah, that's what I was just going to say is that a lot of ... That's one of the things I think you mentioned earlier was you don't use domain models or core models for everything, right?

Susanne: No.

Jeremy: Like that's the whole point of the build versus buy versus outsource type thing is you want to make sure that when there's something simple that needs to be done like simple stored database record and there's not a lot of complexity to that, that using something like active record is a better choice than trying to ... Because you don't want to reinvent the wheel, essentially.

Susanne: Exactly, and so if you try to apply domain driven design to cases with less complex business logic, then you're over engineering it.

Jeremy: Right.

Susanne: And so domain driven design is really very well suited for complex business logic cases and these are supposed to go, these are supposed to be your core domain, right, which is in the genesis and custom built evolution stage of Wardley Map. So there it fits very well, but domain driven design, I would not recommend to you to use it for generic sub-domain. Sometimes they can use transaction scripts, for example, not a business logic implementation pattern where you organize your business logic by procedure and where each procedure handles a single request from the presentation, so it works very well with small applications that does not implement any complex business logic and they can just, yeah, for example importers or authentication using Cognito or something like that.

Jeremy: Yeah.

Susanne: So you don't have to apply domain driven design into that generic sub-domain case.

Jeremy: You mentioned the building blocks of domain model, so what are those?

Susanne: Yes, and they could be kind of like overwhelming, because there are a lot of building blocks but I guess it's ... and if you start, like it could be the case that you have the impression, "Oh, this, my first model does not look very nice," and that's okay, because when you start at the beginning, first versions, it's kind ... an iterative approach, right?

Jeremy: Sure.

Susanne: While you're collaborating with your domain experts, while you're gaining more knowledge, your domain model is evolving as well and also like, you can't do it right from the very beginning but ... Well, that's at least my experience. I don't want to ...

Jeremy: No, I think with anything, it's like designing a DynamoDB table. You're going to get it wrong the first time, and you just got to keep working through it until it ... I mean it's with all software. An iterative approach to anything it typically what we do because we think we're better than we are and we just make a decision and then we realize, "Oh, that was a bad decision," a couple of weeks later.

Susanne: Exactly, and you're always smarter after we have gained all the experiences, right.

Jeremy: Exactly.

Susanne: Specifically with DynamoDB details.

Jeremy: Right, exactly.

Susanne: "Why is it so expensive?" And so, yeah, domain driven design comes with building blocks and I would like to highlight a few of them. So for example, we have ... I guess the most simple building block is the Value Object. A Value Object is an immutable object, which can be identified by its value and when you change this value, you will replace the entire object instance. For example, a common example that the people are bringing us, like the address of the a customer, that could be a value object, but I also like to go in more fine grained but I talk to that one later one. The next building block is an Entity and an Entity is identified by a unique ID and it can change its state over time. So like, yeah, that's something that comes, it's incorporated into an aggregate, so an aggregate itself is composed of, represents a hierarchy of objects and it's composed of one or more entities and one or more value objects and where one entity is called the aggregate root and an aggregate root is designated as the aggregate's public interface, that you can use like when you, for example, when you use a domain model that is an aggregate, when you load it from the database you are going through its aggregate root by its unique entity ID, load it into a ... and also ply then the ... Like renaming it or rescheduling or something like that that's applicable to the domain the logic. That's usually then the aggregate roots matters that you are using. Then you also have the repository that can save and retrieve entities, aggregates from the underlying storage mechanism and you also have an application servers. These are only, their purpose is to only orchestrate use cases and manage transactions. So they do not contain any business logic but they are the gateway to the domain model, to the aggregates that are building your domain model, and another thing also is domain event. This is a message that describes a significant event that has happened in a new business domain, for example. So there are a lot of building blocks and they are kind of like, oh, really, not really tangible at the very beginning, but the more you try to use them, for example, also like, during a workshop I was building a conference solution and I tried to compose my domain model of aggregates and the aggregates were composed of value objects and each of them is taking care of keeping the invariance, the business rule was its integrity. So that you can make sure even though you might have a lot of classes and compressed together with each other and it says, "Yeah, why do I need so many classes?" Because each of them is ensuring that your aggregate composed of these components, of these value objects and entities, you can make sure that they are consistent and they are valid every time in your system, because they take care of it. They take ... Whenever you compose it, at that time, they are valid. They have matched the validation restrictions, for example.

Jeremy: Well, I mean, even just object-oriented design, I mean that software pattern of creating a new object that has a very specific structure, and then specific methods that can interact with it. It's very similar I think in a sense to what, sort of what you're talking about with these individual bounded context, only a lot more complex, but that ability for you to create these things and make sure that when they're created, and the things that they can do. But these are all very specifically prescribed, like it's very restrictive in terms of what these things can do so they can follow all those business rules.

Susanne: Yes, and so for example, when you have, when your domain model that is composed of ... it could be one aggregate, it could be multiple aggregates, for example, and they are having methods, for example, that are really matching consistently with the terms of your ubiquitous language.

Jeremy: Right.

Susanne: You don't have a domain model that consists just of setter and getters and changing state, instead they have methods that are reflecting the shared language. For example, if you have ... I don't know, for example you have a customer aggregate and you are ... The company name is changing. You will have a method that's called rename and containing them the name as a parameter or for example when the address has changed, you're not saying, "Okay, set address." Instead you say, "Relocate," or something like that.

Jeremy: Mm-hmm.

Susanne: So that it's really reflected to the domain language, to the ubiquitous language so when you talk to your domain expert, you share the same language so that you don't have to translate it, your technical terms to the domain experts' terms. Instead you are using the same language and this also allows you to get rid of a lot of misunderstandings.

Jeremy: Well, and you had mentioned, too, like that relocate. Like sort of let's say I have a functionary method that allows me to relocate a customer. It's not as simple as just saying, "Okay, change the address," right? Like there may be rules in place where you have to keep X number of past address or you have to make sure you have to keep all addresses or you can only relocate the customer if the customer is active or they've been active within a certain amount of time.

Susanne: Yeah, yeah.

Jeremy: So all of those business rules, all those things that tie together with that domain model, all of that ties together with these methods that you talk about, so I think that is ... I think that's super important for people to think about it that way. It's not just update a record in the database.

Susanne: Exactly. It's also like trying to ... It's also matching the invariance, the business logic, the business rules.

Jeremy: Yeah, that's important. Alright, so if we want to use domain driven design, how can we use it to help us build say serverless like back ends, for example?

Susanne: So when I entered the field of serverless, I was with its fine grained short list function triggered by a variety of events, and I was kind of overwhelmed in terms of if you design a system composed of countless functions that might be the risk of losing sight of each function's purpose or it also be is the risk that we accidentally introduce a big bowl of mud. You two coupling functions together by accident or accessing resources that we should not access from various functions itself and one approach could be to introduce domain driven design. Because domain driven design allows you to organize the serverless functions and Lambda functions, for example, if you build a back end API. So it allows you to organize your functions together so that you, as I mentioned, like bounded context provides different forms of boundaries in terms of like also physical boundaries like that you, for example, you can organize all your functions that belongs to one bounded context, your module in terms of like your system, and it allows you to organize your functions, for example, that they all go in one good repository, for example.

Jeremy: Yeah.

Susanne: And that also allows you to organize your Lambda functions if you go on AWS, it allows you to organize them in terms of like what access rights do I have for the DynamoDB table, for example that I'm using, so only those functions that goes into one bounded context and located at one good repository, they are allowed to access the DynamoDB table that is saving the state of our domain model, but not other serverless functions that are relevant or that are responsible for another bounded context. They are not allowed to access my DynamoDB table directly. Instead, they have to figure out what kind of integration patterns we have between these bounded contexts like event driven, like for example submitting an event or into an SNS topic and our other boundless contexts and external bounded context is subscribing to this topic and then is reacting on these ends appropriately. But it's not accessing the data storage components of an external bounded context. So that allows us to get an overview, which serverless functions are solving what problem, what part of our problem, what bounded context, and they help us to organize which function skills into one good repository and also help us to organize what access rights do we have, that we are not allowed to access resources that are where other bounded contexts are in charge of.

Jeremy: Right, and that actually creates sort of that physical boundary, right? I mean in the sense where you can have ... Well, physical boundaries and ownership boundaries that we talk about earlier, because you can have a team that goes and just works on one bounded context and a group of functions and I think we've been seeing that quite a bit, that's sort of been the approach when people are taking a microservices approach to serverless that what they're doing is they're taking a single stack and they're putting all their related functions for that service in the single stack, have a separate DynamoDB table or other whatever their data store of choice is that they're sort of doing that. I think that makes a ton of sense and certainly the domain driven design approach to all of this and really thinking about that ubiquitous language. I know I'm hung up on this, but that to me is hugely important because I think a lot of people miss that and I think as you said, you know, sort of what's important for the customer is the most important thing and I know a lot of technologists who say, "All right, we just want to focus on what's good for the customer, but what we really want to do is figure out how to install Kubernetes," right?

Susanne: Exactly.

Jeremy: Like we want to figure out how we can do this cool technological thing, whether or not ... I mean it eventually will have some benefit to our customer and that's I think what slows down a lot of software and I think what you said right from the beginning is that's why we have so much poor software. Anyways, if people want to learn more about domain driven design, I know there are some books out there, but you're working on a workshop for this, right?

Susanne: Yes, yeah, so I have created a workshop but it's still under development and I have created a workshop that is focusing on an example, because I guess you can learn best when you have a practical example.

Jeremy: Sure.

Susanne: It's also a simple example, but it's for example a conference solution, where we identify the bounded contexts that are necessary to, for example, manage a conference event, including starting a CFP, a call for papers, evaluating the submissions, and create a schedule and choose and submit a session proposal from the speaker and something like that. And this, I was creating a workshop out of it in terms of like, okay, how to use ... One thing, like how to use Wardley Maps, how to identify what shall be core domain and combine with domain-driven design and what goes into the other evolution stages and also evolving the value chain going first from, okay, "What happens when we implement this solution using also the tactical design patterns after we have started with the spreadsheet sheet design." But how can we evolve the value chain in terms of like starting first with an open source solution, going on premise, and how does it evolve going then at the end to serverless, using ... providing serverless and back end API with Microfunctions, for example. And, yeah, it's a kind of like multi-stage workshop where we try to, yeah, going also from the strategy, like how can we outsource those components and what does it mean for our ... so for architecture and our software design and what kind of impact does it have and then we at the end, we figured out, okay so the business logic remains the same but ... and hexagonal architecture but the infrastructure components they are then replaced. For example, in one case, we are using a rest API to kind of communicate with another bounded context. In, for example, in the serverless example, I'm using then ... an SNS topic, as in forms communication via events and still the core, the inner part remains the same and I try to make it tangible for the audience, for the participants, how it looks like. Yeah, evolving the value chain.

Jeremy: Awesome, well that's going to be a very, very good resource, so thank you for putting that effort in and thank you, Susanne, for coming on the show and talking about this, because I think this is something that isn't talked about a lot on a lot of development teams and it should be more because we would be building better software and of course, I'm quite fond of serverless, right? So the idea of the things that you can do to reduce that build or that sort of implement yourself type projects is something that serverless just blows everything else out of the water, at least in my opinion, so anyways. Thank you very much for coming on the show.

Susanne: Thank you.

Jeremy: If people want to get in touch with you or find out more about your workshop and some of the other things you're working on, how do they do that?

Susanne: They can contact me via Twitter, for example, so my Twitter handle is @suksr. So I am also my direct messages are open and also I am having my own website it's www.susannekaiser.net and also you can reach me over LinkedIn as well.

Jeremy: Awesome. I will get all of that into the show notes. Thanks again.

Susanne: Thank you.



Episode source