Domain-Driven Design And Elixir - EMx 185
In today’s all-panelist episode, we take a shot at demystify domain-driven design. We discuss several books and some concepts that stand out in those texts. How easy or hard do Elixir and Phoenix make it to apply DDD principles? We give our experience with taking these concepts and putting them into practice, and give some tips and resources for getting started.
Show Notes
In today’s all-panelist episode, we take a shot at demystify domain-driven design. We discuss several books and some concepts that stand out in those texts. How easy or hard do Elixir and Phoenix make it to apply DDD principles? We give our experience with taking these concepts and putting them into practice, and give some tips and resources for getting started.
Some of the topics covered:
- Tactical vs. strategic domain-driven design
- Event Storming
- Bounded Contexts
- Accidental vs Intentional complexity
Sponsors
Links
- Domain-Driven Design: Tackling Complexity in the Heart of Software
- Domain-Driven Design Distilled
- Domain Modeling Made Functional: Tackle Software Complexity with Domain-Driven Design and F#
- EventStorming
- DDD, Hexagonal, Onion, Clean, CQRS, ... How I put it all together
Picks
- Adi- GitHub - sasa1977/boundary
- Adi- Mix: Using Xref to Enforce better Design
- Adi- Macro - Elixir v1.13.4
- Adi- digraph
- Adi - Three people looking for jobs - reach out to me to connect with them (sr. Elixir engineer, two Jr. Elixir engineers, and others too)
- Adi- Assassin's Creed Valhalla for Xbox One, PS4, PC & More | Ubisoft (US)
- Sascha- Virtual Domain-Driven Design
- Sascha- KanDDDinsky - The art of business software
- Sascha- Citizen Sleeper on Steam
Transcript
Sascha_Wolf:
Hey everybody and welcome to another episode of Elixir Mix. This week on the panel we have Adi Aiyengar.
Adi_Iyengar:
Hello.
Sascha_Wolf:
And me. That's it. It's a small and cozy panel this week. I'm Sascha Wolff. And this week, we are going to talk about, and that people probably already know it because it's the title of the episode, Domain Driven Design and Elixir and how these two belong together or not or whatsoever, right? What kind of relationship they're standing. And the prompt for that was actually that at my current employer, we had a workshop last week with organized and facilitated by Marco Heimershoff. That name would probably don't tell anybody anything, but Marco is basically a very well-known name in the DDD space in Germany. So he's also organizing the Kandinsky, which is basically the German domain design conference. And there were three days of lots of wisdom, lots of learning, lots of discussions. We actually all met in Berlin where the offices of Micro Deployer are, which is also kind of nice because we have a very remote workforce. So that was pretty neat. And yeah, now the question is also in that company among colleagues, okay, how do we put these things into action? And as we are a company using Elixir, that has relevance for this podcast. So maybe first things first, Adi, what is your relationship to the range of design and maybe... If you want, you could define it for our listeners who have no fucking clue what I'm talking about now.
Adi_Iyengar:
Yeah, I mean, I'll try. So my familiarity with it is I read the book in 2017. And around that time, there was talks in the Likster community about a web folder not being a separate folder, and how repo functions in the Ecto world should be called from Phoenix. And then Phoenix 1.3? or 1.5, I can't exactly remember. That's what came out. And that gave to bounded contexts, so that we have in the context modules. So I think that term is clearly taken from DDD. I think that having read that book and having around the same time where Phoenix was making that change was very helpful. It kind of put things in perspective. But yeah, I mean, I'll try to define them into a design. It's really like, as Sasha and I were talking before, it's like a set of principles, right? Basically, mainly around context where, you know, If as you approach your application from a specific domain, the context of that module that talks to that domain or determines what needs to be done is the context of that domain, right? That's like, I guess like the most simplest conclusion of the whole DDD book. There's different models and all that. I mean, I don't even remember all the terms that were like entity, which has, I mean, anything that has an ID is an entity. or there are services that are not an entity but have some functionality and stuff like that. So there's different, there's a huge kind of array of models and principles along with it. But yeah, if you read the book and you try to follow basic conclusions of that for a few months, for a few projects, you'll internalize that book. And then you will not need all these, you know. words and jargon, I guess. But it's helpful, right? When you talk to other people to know what they're talking about. Anyway, I don't think I answered the question. I don't think I defined it properly for people. But. Ha ha ha.
Sascha_Wolf:
But I think it's a good starting point because from where I'm standing, what you just laid out is probably what a lot of people in the Elixir community but also beyond that is like, okay, I've heard this thing, recommender of a design, this is what it seems to be about. And I would have probably given a maybe bit more expanded answer, but not that much before this workshop with Marco last week. Because I've read if for example just to maybe circle back to the book You're talking about what is written by Eric Evans and it's literally called domain-driven design, right? Like that's the type of a book and this is kind of what started all of this But there has now been published a whole slew of other books. For example, there's also domain-driven design distilled by Vaughan Vernon Which I think I also picked at some point in this podcast. I think it's a very good introduction into this subject because Eric Evans book is great and everything but it was the first book in the space, so it's a bit...
Adi_Iyengar:
It's huge.
Sascha_Wolf:
It's huge and it's difficult to follow along at spots, so it's not necessarily the best book on Dremendive Design, which again makes sense when you consider it was the first. He was the guy who kind of pioneered all of this. So I always tend to recommend Dremendive Design Distilled as a good starter. But there's also a pretty good book from Scott Blushing, which is called Dremain Modeling Made Functional, which by the name you would think has a huge relevance for elixir. so much because it's about how you can use types to model your domain, which in Elixir is possible, but in the code example he's using F sharp. So he's more using a statically typed language and using the type system to then spec out boundaries and expectations and so on and so forth, even without writing a single line of code, which is kind of cool and good to read. The thing, especially now with my newly found knowledge from last week, is that Or what I've just talked about and what you talked about is what it's called usually tactical domain-driven design. And tactical domain-driven design is about, okay, how do you take all of these things and put them in code, right? Like what are patterns? What are things you can do? But there's also this whole slew of strategic domain-driven design, which is really more about understanding the domain. And domain is a word now because we use it so much. What the fuck does that actually mean? And domain is basically a boundary of knowledge. So insurances could be a domain. Car repair could be a domain. Cinema operation could be a domain, so on and so forth. There's basically any kind of area where you can somewhat draw a boundary around and say, hey, people care about this thing inside of here and they have specific knowledge about this thing inside of here, that's a domain. And domain-driven design, as the name suggests, is really about, okay, let's take this knowledge inside of this domain and let it drive the design of a system, drive the design. of the software. And then there's a whole slew of other words like I write entity, aggregate, blah, blah, blah, blah, blah, blah, blah, blah. But what it boils down to is really this. It's like, okay, at the end of the day, you have people who work inside of these domains who work, for example, inside of a cinema, and they really know how the cinema operates. They know, okay, we have payment, you have tickets, which have to be sold, you have movies to be shown. And all of those are parts of running a cinema. And all of this is specific knowledge these business experts, which is also a word from Domain Design, have. And you usually, as a software developer, don't. And in the best possible world, if you wanted to write software, for example, for a cinema, you would kind of take a business expert from cinema and put his head into, I don't know, like some kind of machine and say, hey, extract the knowledge from this guy and make working software out of that. That would be the best case, right? Because then you'd have all the kind of hidden nitty grits, parts of business rules. inside of this person's head and extract them into working software. But we don't have this, that's what software engineers do. But they usually do not have the kind of knowledge the business experts have. And that is really what at the end of the day domain design boils down to is like, okay, take this knowledge from people who really know this domain inside out and turn it into working software and how you can do that. And then at some point, of course, it boils down to well, Okay, now we have this thing that people care about, but we have to somewhat translate it into code. And there are some patterns which are more viable than others, which are then entities, aggregates, value objects, so on and so forth. But all of this is then this tactical design, and which you would use at a point where you already have a somewhat well enough understanding about the domain and about all of the different parts involved in there. So yeah, that is a longer answer I would give now after having been... having showered in the wisdom of other people. Does that make
Adi_Iyengar:
Yeah,
Sascha_Wolf:
sense?
Adi_Iyengar:
that's that's yeah, it makes a lot of sense. I mean, that's really cool how you separated the technical and strategic. That's actually so important because, you know, there's also the planning and planning was implementation, right? Like phase of the project, like thinking of domain DDD, even in planning side, when you are, you know, questioning interviewing people, right? To build a product and like creating the roadmap. That's a that's a very, very fair point. I think I think that should be done for like all of these. Not all, but like most of the software. Like you should make sure to follow those both in the planning and the implementation side. I think one more thing I would add, which really, you might disagree here with me, but this is my conclusion in 2017. My bad, in 2018. I read the book twice. I think I should read it a third time. It's a book you'll add, Sasha, a point, and it's a lot. So you read it multiple times. So the second time I read it, my conclusion was it's like an extension of two solid principles. The... I, interface segregation, and a bit of the D, dependency inversion. Interface segregation because you don't want your clients to depend on interfaces that they don't need to. So your client should, your interface should be very thin and specific to your client in a very similar way where your context should talk to the domain directly and the details of the implementation are hidden behind the context. an extension of interface segregation and a bit of the dependency inversion where you're hiding the implementation details from the abstraction. So again, if you really follow and understand and have thought through solid principles, DDD should make sense even if you think of it as an extension of a couple of those principles. I don't know, what do you think of that, Sasha?
Sascha_Wolf:
I think that that would very well belong alongside other tactical design patterns. Because at the end of the day, if you could take a business expert and somehow extract an insanely messy auto-generated bunch of code, which still encodes all of this knowledge this person had, then by DDD standards, that would be fine. But we don't have this machine. So at the end of the day, all of these... patterns, all of these tactics, all of these architecture styles, we even talk about boil down to us humans being very bad at dealing with complex things. So yeah, and for example, one idea, and I think that's where you're getting at in the domain of design, in some of the technical patterns is that you don't want to concern yourself with the complexities which belong to Well tech in as a whole right like at some point you're gonna have to purchase data at some point You're gonna have to communicate with some service over the internet on all of those are technical details Which are completely irrelevant for the domain at hand right for example if if I run a cinema And I want to run often a reservation service through phone or for web like as a cinema I don't care that there's HTTP one or HTTP two or whatever right like I don't fucking care This is all of the implementation you disperse still these complexities need to be handled that is then where there are certain design patterns. For example, there's also like the onion architecture or the cleaner architecture or the hexagonal architecture, which kind of, for my understanding, have a lot of overlap, which are DDD related. They're not strictly core of DDD, right? But the principles of those boil down to, hey, encapsulate the actual business rules without having to care. about the technical details, right? Like I don't want to care in my business rules that this request came in from a mobile device or that this was an email or that this was whatever, right? I just want to have my business rules nice and clear here and don't have to muddle it with technical details because I think we all probably who've worked in this industry for a while have dealt with code bases where the technical complexities are intermixed and entangled with the business rules. And it's so hard that like at some point, like, hey, but now we want to also trigger it. I don't know. Through an email, you're like, wait, what? Right. Because you maybe have some business code, business rules, kinda inside of your web controller and rails or whatever, and you have it in a sidekick job and you have it somewhere over there, but there's no place you can go to and say, Hey, do this business thing. And this is what
Adi_Iyengar:
Yep.
Sascha_Wolf:
then boils down to, okay. inside of my domain. I don't care about emails. I don't care about web requests unless this is literally my domain. I just want to reserve a ticket for this movie, right? So why shouldn't think why can't there be a piece of code which says reserve a ticket for this movie?
Adi_Iyengar:
Right, right, right. Yeah, I mean, yeah, I think besides that last part of why can't there be a piece of code that does this, your entire model, you could cut that and paste it and someone can hear that and they might say, oh, he's talking about separation of concerns. Besides that last part saying that there should be one module talking to your domain directly. But yeah, I guess at that point, like, I mean, yeah, the D2D is, you know, one of these principles. from a domain perspective. What was it called? Was it aspect-oriented programming or something where you need to, it's like modularizing everything. Again, it's aspect-oriented programming from a domains perspective. A lot of times people say domain, they also mean end user, which is not completely true, but true in most cases.
Sascha_Wolf:
Yeah, I think this opens up an interesting tangent. Also, Marco and the workshop went into is that the main design of itself is a kind of of a gravity funnel, right? Because this end idea is really about, okay, let's take this knowledge from business experts and that's what matters, right? That's what we want to put on to automate around. And every tool which helps us alongside... helps us in that effort is potentially a tool you can use to do domain-driven design. The interesting thing there, for example, is that in the original book, right, from Eric Evans, he never talked about things as, I'm not sure if he never did, but like, he only briefed, tangentially talks about events, for example. Also, he never talks about the thing called event storming. And event storming is a technique actually invented by Alberto Brandolini, which is now the de facto modeling. technique used inside of a DDD community, because it's just very good at getting this information out of the business experts head like it's really good at that. So it's something the community kind of gathered around and said, Hey, this this is a good tool for this job. But it's not. It wasn't in the original book, right? It's not the thing. It came from people trying to do momentum design, trying to solve these difficult problems about okay, how can I as a software engineers find this some kind of language just talk to business people, how can I learn the things they know to a degree to an understanding that I can actually put this in production? Because there's also this I think it was also a better one, but you said that it's not the some something like that. I'm going to paraphrase because I don't remember exactly, but it's not the knowledge of a business expert, which goes into production. It's the assumptions of the developer. And that's that's the truth right there, right? Like at the end of the day, it's what Beep as a software engineers understand this is what ends up in production. Not the perfect knowledge of a business experts about all the kind of weird edge cases they are in the real world, but whatever the software engineer understood. And which in one quote basically underlines why this idea about, okay, you have this business experts, you have software engineers, software engineers write the code, but you kind of want the knowledge of business experts ending up in the code. So how can you do that? This is why on the lines, why this is important, why this matters. And at the end of the day, why also all of these patterns we now mentioned probably briefly like aggregates, value objects, the inversion of control, all of those are only tools for this end goal, for this to achieve this means. Where did I wanna go with this? It kind of went on a rambling here. But yeah, again, exactly, Gravity Funnel and event solving. So it just shows that in theory, anything which helps you to get closer to that, it's a tool you can use for the main design. It's also, for example, events are something the community is very much embracing because at the end of the day, if you look at a business, most of the things which trigger actions inside of businesses, which mean... have rules associated to them are in some way or another an event, something which happened in the past, right? For example, user requested to reserve a ticket, right? It's potentially to get back to the cinema example, an event which might happen, the thing that happened in the past. And that is why also there's a lot of modeling techniques in the RemainDrivenDesign space say, hey, events are a good thing, but you don't have to use them. You can if you want them, but they're just a good tool for this job. for encoding this knowledge and for building your system around them. Does that make sense? Does that kind of answer your question, I guess, or was that incomprehensible, Sasha Ramblin?
Adi_Iyengar:
It wasn't completely incomprehensible. Yeah, I think the last bit definitely makes sense. I mean, we use events as a way to accomplish or have a better domain-driven design on our system too. Like having a clear, yeah, I mean, yeah. The events that are generated through the user-facing app are more domain-driven versus the events that are generated. because the result of consumption on those events are completely different. So that totally makes sense. Event storming, you mentioned, right? That's just like the brainstorming methodology where people just talk through, you know, sequentially what happens, you know, as a request is started from a domain perspective. Is that correct?
Sascha_Wolf:
Yeah, it's a bit more than that, but it boils down to this. It's a collaborative modeling exercise where you get together, as Pandolini puts it, he says, get people with questions and get people with answers in the room, and you use a lot of sticky notes in that process.
Adi_Iyengar:
Right.
Sascha_Wolf:
And at the end of the day, like simplified, you basically have a timeline. And the best case, you actually have an infinite modeling surface, which of course in practice never have, but. really as big as possible because the bigger it is, the easier it is for people to say, I'm just gonna model this here because I don't take up space, but like there's enough space.
Adi_Iyengar:
Great.
Sascha_Wolf:
But it tried to get all of the events on that wall and it's okay in a somewhat sequential chronological order which model whatever currently you are trying to model. You can do like a big picture event storming where you really say, hey, let's model the business as a whole. And then you probably will have parallel things don't have a clear connection between each other because at the end of the day, businesses are still messy places where there's no clear link between each and every single thing a business does. Um, but you can also use it to really model out one specific process, right? Say for example, Hey, I want to model out our onboarding flow. For example, you can redo it. And the nice thing about it is that it, um, like the main purpose of it, it's not the artifact at the end you produce, like the sticky notes, but it's about this collaborative modeling where you actually synchronize everybody in the room about them. the model and the terminology you're talking about. Because there's also one part, which is called the narrative, the narration, where you really start at the beginning and then I try to narrate a cohesive story about the events on the wall. And it very clearly becomes obvious when something is missing. Very quickly becomes obvious. Like, okay, why this happens and then this happens. Like, this makes no sense. What's the link here, for example, right? And... This is really what it boils down to. And that can easily take up a whole day. This was for example, what we did on day two, in this three day workshop
Adi_Iyengar:
Bye.
Sascha_Wolf:
we did. And we had like the CEO in the room. We had this, we had somebody from B2B, we had somebody from marketing, so on and so forth. We had lots of people from the product development team. And then we really mapped that out. Right. And that was quite a learning experience. And lots of sticky notes being used.
Adi_Iyengar:
Nice.
Sascha_Wolf:
So yeah, that's what event storming is. And the nice thing about the methodology is that you can actually then take
Adi_Iyengar:
Thanks
Sascha_Wolf:
some
Adi_Iyengar:
for
Sascha_Wolf:
of
Adi_Iyengar:
watching!
Sascha_Wolf:
these events you put on that wall and take them, for example, and say, okay, now we actually use literally this event in this name and use it in the code. Because why not? I mean, like it's a thing you modeled. It's a thing you aligned on. Everybody agrees that this is a thing that happens inside of your domain. So
Adi_Iyengar:
Right.
Sascha_Wolf:
why not use it in the code? So yeah,
Adi_Iyengar:
next class.
Sascha_Wolf:
that is. But to maybe also circle back to where we started, because we talked about Elixir and Phoenix introducing the spawner context. Why are we talking about all of this design stuff? And the episode is after all called the Medium Design and Elixir. So where does Elixir maybe come into here? And maybe to take one step back and explain that Phoenix introduced these contexts, right? What does that actually mean? And for example, in the... inside of domain-driven design, there is this terminology called bounded context. And the bounded context is something where you say, okay, you have a sub part of your domain. And in the example of the cinema I had earlier, right, you could say you have a sub part of your domain, which is payment. You have a sub part for your domain, which is tickets. You have the sub part of your domain, which is movie showing. And yes, they have a relationship instead of each other, but each of those sub domains, they have, again, things they care about. The others don't. Instead of payment, for example, you, like for example, tickets might only care, hey, a ticket needs to be purchased, right? The customer needs to buy it. But if you does it with cash, with Bitcoin, with PayPal, with, I don't know, by bringing a bunch of eggs and offering, it doesn't care, right? That's a ticket has to be paid for. But instead of payment, of course, yeah, you care. Okay, you have a cash system that's completely different from a PayPal system. It's completely different from a Bitcoin system. All of those things. that have their own intricacies. And then at the end of the day, when you actually, because this is right now, it's the problem space, it's the problem space of your domain. But at some point you might actually want to put that into, like you want to build a system around that, you're entering solution space, and then you can say, okay, we have these bounded contexts. And inside of that context, things have their own meaning, and you can draw a boundary around it, which is why it's called a bounded context. So for example, inside when you would want to build software for a cinema place, you could have a bounded context, which is payment. You could have a bounded context, which is tickets. You could have a bounded context, which is movie showing. And they have then again, relationships between each other, but they are bounded. They have their own little view on the world and can model clearly inside of that without having to care about the nitty gritty details of how, for example, a ticket has been paid for. And that is From my understanding, also where Phoenix then comes from, it says, OK, we have these context modules. We have, for example, accounts. We have, for example, I don't know, let's say tickets. Stick with the example, right? We have a payments context. And it's decoupled from the actual web logic. It's just, OK, this is what the business boy is down to. The Elixir community, from my understanding and from what I can see, also what the generators do is then take some more pragmatic approach and says, OK. We're still going to generate a bunch of actor things here, which, if we circle back to what we said earlier, would be more of an implementation detail. If you wanted to really do full blown domain-driven design, you might not necessarily want to do. But that's also something, again, where domain-driven design says, hey, if this is good enough for your particular thing, for your particular part of the domain, sure, then do actor whatever, right? But maybe you also have a part of your domain. which is so insanely complex that it's worth the effort to say, I want to extract all of those technical details out. I actually really only want my business logic here because we are, I don't know, we're doing some high speed financial trading, which is an insane amount of legal obligations and all of those need to be modeled in code. And then it's easier to understand if we don't have to care about database details, for example. But that's all again, trade-offs and things you have to decide on a case-by-case basis.
Adi_Iyengar:
That makes sense. That totally makes sense. And yeah, I think I think it's case by cases, perfectly said. And also, just because they decide that something doesn't need to be part of a boundary doesn't mean in future it will not change. Right. So it's also important to reevaluate and be open to, you know, rethinking things.
Sascha_Wolf:
Yeah.
Adi_Iyengar:
But I think one thing I'm always a fan of, if you have if you are, if you have a pattern, you should have a way to enforce it. In a look, Sasha, have you used anything to enforce such a pattern, right? For example, not using repo in view, you know, classic case of an n plus one query, right? So have you used anything to kind of enforce that?
Sascha_Wolf:
Um, indirectly, because what, which is not necessarily I did it, but for example, if you actually would want to go into this modeling, right. I mentioned earlier, then for example, this, uh, you
Adi_Iyengar:
Okay.
Sascha_Wolf:
might actually want to look into an area we'd already talked about in the past, which is like event sourcing. And then again, see curious because those again have a, quite an overlap with some of the ideas behind design. When you look, for example, at what Commanded, which is like this popular library, right, and Lixir to do security and event sourcing does. You also have aggregates there and they trigger events, but the aggregate itself, actually, it's really just a module. It's a module which holds state, but there's nothing associated to that aggregate, which has, hey, this is a Commanded thing, right? This is really just a module with a bunch of functions returning events. And then all of those are then used by Commanded. So it's actually somewhat a good example of. You have this business logic, you have this thing which encapsulates business logic, uh, which, which at the smallest atomic level, so to speak, this aggregate, which aggregates its data from a bunch of events and, um, it's an, and, but it doesn't have any technical details in it. It's really not, it doesn't have, I am, I'm saved in the database over here with this table, but it's really okay. I am this one module, I have a state and I return events and I somewhat come, uh, react to commands. So while I haven't done it myself, this would be somewhat, this is like I've worked in a code base which uses command and which then at the end of the day, kinda enforced this pattern on how you want to mutate your state and how you want to model things changing inside of your system.
Adi_Iyengar:
Nice. I mean, that's definitely a good way of doing that. I was thinking more even in terms of like a module. Have you heard of boundary? Sasha Yurik wrote that. It's like a way to make sure, for example, just like add a dependency and say, hey, egg toe, read book and only be called. x not x.xweb, right? So like a namespace restriction. So like, that's kind of what I was looking at.
Sascha_Wolf:
Mm-hmm.
Adi_Iyengar:
Before I think boundary was written, I used mix as a cross refs, x ref is what it's called, an x ref task. Yeah, that's also a good way of like getting all the references at compile time and seeing what modules call what modules and making sure nothing gets outside of the boundaries you defined. I don't have that in my current code base. I think it's too simple and small because we are very microservices-y right now. So we're even driven microservices, so what he said, Sasha, it's like the separation is beyond the application layer, so we don't need. to have that compile time thing, but if any of the listeners have a big, more monolithic sort of application, you should definitely check out Boundary to enforce these kind of patterns.
Sascha_Wolf:
Yeah, that makes a lot of sense. I wonder if as, for example, I mean, I could imagine that Credo could in theory have a check for that, or you could write a custom check for that. I'm not familiar with it having that. But from what I've seen Credo being doing, it would not be unfeasible. I say, hey, for example, I mean, if you wanted to have a big monolithic code base and then you maybe to circle back, you actually would want to say, hey, we have these different bounded contexts and they should only really communicate through like top level modules, right? For example, you have maybe, let's say we would write code base for the Elixir Mix podcast, right? Then you would have a top level Elixir Mix module and below that we may maybe have, I don't know, listener or subscribers or an episode recording whatever is a modern context. And there's like a link between those. And then for example, inside of a subscribers bound context, it would only want to call to the recording. bounded context on like a top level, right? I can not use modules below that. That's potentially something I could easily see inside of Credo or I mean, if not, I've never used boundaries, so I can't really say anything about it, but yeah. I have not ever used anything like that. At the end of the day, depending on the size of your team, this is also something which humans in code reviews can easily enforce if everybody is on the same page there. Right, this is which. was also one of the reasons we did that workshop in the first place, because while I myself already was quite familiar with certain ideas about the main design, most of the team were not. And the CTO and me, we were both thinking, hey, this is actually a thing which could be useful for us as a company, for us as a team. So let's do this product, this workshop also to get everybody on board. And now everybody is like has an alignment about why these ideas are important. Yeah. And it was also like to... Go back to something you just said briefly, Adi, because you said, okay, instead of these boundaries, how you can do change, right? How it makes easy to change things. And this is also why maybe some of the listeners might not think, yeah, but why should I care, right? Why should I do all of this effort? I write this code and it works, what's up, right? Why does it matter how I write it? And that is where change actually becomes important because we all know businesses are... things which are changing. There's probably no business out there which is not changing a little bit and if there is they're probably going to go out of business soon, right? So that also means that the understanding of business experts changes about what the business at hand is and in the best possible case if you have a system which is really aligned with a domain with a problem space and with like the subdomains and so on so forth and you actually have a changing business rule There's one place you go to in your code base to change it. There's one thing, you say, OK, this one thing changed in this particular way. OK, now I have this. I know exactly where to look in my code base because it's well aligned. The solution space is well aligned with the problem space. And that's one of the major strengths about doing all of this, where you can then actually, it becomes easier to change the system. It becomes easier to work with whatever change you require. And of course, then you sometimes have Kraken like GPR, which says, oh, you have to be compliant. They're like, well, fuck me, I guess. But then again, it also impacts the business as a whole, right? I mean, there were business outs, OK, GPR is coming around. OK, but it impacts every possible every part of the business. And then it's no surprise that it would also potentially impact every part of software. But if you have this alignment between, OK, this is what the business looks like and this is what the code looks like, it becomes easier to model change. So yeah,
Adi_Iyengar:
Yep, makes sense.
Sascha_Wolf:
this is, I think, which is like what the hidden strength kind of is, I feel, about all of this. Yeah, and I think if everybody followed along to this point, you're probably not surprised when I say Elixir at that point is not necessarily better or worse for doing domain-driven design. It's potentially just a tool and it might, yeah, there might be some things inside of Elixir which make certain patterns easier, right? aggregates which have stayed encapsulated and only really care about that. You can easily model that as a process. So that's like a nice alignment there. But if you, I don't know, if you, if you can achieve perfect alignment between your business problem space and your solution space in JavaScript. Yeah, then sure. Do it. Um, so yeah, but maybe then to, to, to also to, to give, to give all listeners a bit more. me a bit more things to chew on. So we now talk about, OK, this is where Phoenix comes from with its context. These are the ideas. We talked about boundaries. What are some other things? I mean, you also talked about more of the patterns you know from domain-driven design. So how was your experience, Adi, with actually putting these things into action then? Let's assume, OK, you actually. You have this perfect understanding of a business as a whole, right? You know what your business experts think. And you already said earlier that you read the book two times. So how was your experience and then actually taking these patterns, these ideas and building a system with that? Any war stories to tell?
Adi_Iyengar:
Yeah, I mean the capacity that I've worked in mostly is, you know, small companies sponsored a startup. So generally the impulse for everyone, including myself, is like not to overthink over engineer, right? So I think it's mostly like trying to find that balance really, a place where it's good enough to help us release. But, you know, Yeah, I mean, good enough so we can release a feature and also not spend a lot of time maintaining it in the near future. So yeah, generally it stops at building a new application. It stops at that bounded context, right? And moving communication to outside of the application layer, like you were talking about, like events or even HTTP, provides that implicit boundary, really. worry about the boundary. At that point, yeah, combination of these two things helps. Although GraphQL messes it up quite a bit, but that's a different conversation altogether.
Sascha_Wolf:
How does GraphQL mess it up? Now I'm curious.
Adi_Iyengar:
I mean, you're giving them the control over all the details of the API, right? The point of GraphQL is giving more control to the client, which works in certain cases, but then with control comes like responsibility, right? With great power comes great responsibility. So the clients need to have more information and more knowledge about some... part of implementation. Of course, you can apply the Unity in designing the GraphQL API itself, but generally in my experience, people start off with a one-to-one database to GraphQL, which is not the Unity.
Sascha_Wolf:
Yeah, yeah, 100% agree with me. But at the end of the day, it also is... Like I said earlier, I was just hinting at how the database looks like. It's really an implementation.
Adi_Iyengar:
Right.
Sascha_Wolf:
If you had the perfect DDD code base applying all of these principles because you want to really to model the complexity and only the complexity, then the... database is really an implementation detail. And it might be MongoDB, it might be Postgres, it might be Cassandra, whatever is best for the job at hand for your particular
Adi_Iyengar:
Right.
Sascha_Wolf:
use case
Adi_Iyengar:
Yeah.
Sascha_Wolf:
there. So yeah, but what I often see is also DDD, which is like database driven design.
Adi_Iyengar:
Yeah, that's exactly, I think generally when people do absent and GraphQL, that's the first impulse people go with. And kind of absent helps you do that too with like actual data loaders and stuff. It encourages that, which makes sense. Again, I think you said perfect Unity. I think that's another learning I would say. If you're like, you know, late junior, early mid-level I mean, there's two categories of engineers, right? One who, one who cares, one who don't as much. And you, your fact that you're listening to this podcast probably means that you're in that caring category. And for you, a good thing to like, kind of like, internalize early on in your career would be, no code is perfect, right? And like, it's an ongoing evolution, even though the code might look perfect at that instance of time to you, it might not look, the same code might not look perfect in that instance of time. to a different view, right? So if you time travel back to that time, it might not look perfect, right? So I think that's something to kind of like, for engineers to learn, when have you hit that point of diminishing returns, right? And there's so many variables, the kind of company you work at, the kind of problems you're solving, your timeline, the size of your engineering team, so many variables that go into that. So it's... fun as engineers to give into our impulse of engineering. And oftentimes over engineer, but yeah, you're never gonna write perfect code. There is no such thing as perfect.
Sascha_Wolf:
Yeah, they agreed. And also I like how you phrased it because you said no code is perfect. And you can also understand it as no code is perfect. So like if you can get away
Adi_Iyengar:
Yeah,
Sascha_Wolf:
with
Adi_Iyengar:
yeah,
Sascha_Wolf:
not writing code, it's also good,
Adi_Iyengar:
yeah,
Sascha_Wolf:
right?
Adi_Iyengar:
that's that's that's yeah, that's exactly true If you write no code, that means I have no code to maintain,
Sascha_Wolf:
Exactly.
Adi_Iyengar:
right?
Sascha_Wolf:
This is also something, in one of his talks, Marco Heimelshoff, the guy who did the workshop, he's saying, if you can get away with writing less code, that's good, because code is costly to write, to maintain and to educate. Right?
Adi_Iyengar:
Right.
Sascha_Wolf:
So less code is actually a good thing.
Adi_Iyengar:
Yeah.
Sascha_Wolf:
So,
Adi_Iyengar:
Exactly.
Sascha_Wolf:
yeah.
Adi_Iyengar:
I mean, another thing is if you have great code, great piece of code, and you add great piece of code to it, you're decreasing how great that old code is.
Sascha_Wolf:
Yeah, yeah.
Adi_Iyengar:
Just because you add good code to good code doesn't mean you're messing up the other good code, too. That's just how it works. That's
Sascha_Wolf:
Yeah, yeah.
Adi_Iyengar:
just how complexity works.
Sascha_Wolf:
Yeah, and it's also what, I mean, this is like now kind of getting into really big picture thinking of architecture, but it's like also something we talked about in this workshop, it's which is like there's accidental, or I forgot how other word was, accidental complexity, and there is inherited complexity, yeah. And accidental complexity is what we just talked about earlier and all those like, I don't know, you have. to deal with databases, you have to deal with web requests, you have to deal with authentication, whatever. All of these things which are necessary to make the system run, but are not essential. Yeah, I read the words about essential complexity, accidental and essential complexity. And there's essential complexity. And essential complexity is really, it's the complexity of your domain. It's the complexity of the business problem. And you want, in the best possible world, you want a system which is high on essential complexity, just as high as it needs to be to model the complexity of your business. basically equal to that, and which is as low as possible on accidentally complexity. And the best, I mean, as I said earlier, if you have a change in your business, in the best case, you have one place to change your code. It can even make it further if you say, for example, I have a description, I have a thing which exactly explains how a certain feature or how a certain business problem works and how a solution to that works. And you change one sentence in that. In the best case, there's one line of code you need to change. Right? It's like a one-to-one mapping. That's probably unachievable every time. But the closer you get to that, the easier it is also to maintain that system, because there's a very clear understanding. And then again, there's technical design patterns in DDD which make that easier. And you can somewhat, if you want, get close to an ideal where you have some code which is even somewhat readable to a business expert with a bit of hand-holding. And And like I said, I'm not going to say that this is worth it all the time, which is one thing I wanted to mention is this is like also an idea from domain-driven design that you have these different sub domains. And like I said, payment, movie showing, tickets, but not each of those is equally important to your domain. For example, payment is a thing you need to handle, but if you become the best cinema, which handles payment in the best possible way on the planet, it's probably not that much business differentiation, right? Like you're not gonna differentiate that much from competition. But maybe ticket reservation, tickets, that is the thing you can really differentiate. You can really make it easy for people to, super simple to get the ticket and get it and get it in cinema. So that is the thing where you can then say, hey, this also has like high business differentiation opportunity, but also. Maybe it has some level of complexity, so it's not super easy to copy. But, um, and then we can really say, okay, this is the part, for example, of our business, where, of our software, where we want to put all of these things into practice, where we want to really pour in the effort to differentiate as much as possible while also Not having it so complex, it's overwhelming, but complex enough so it's not easily coupleable. And those are then potentially your subdomains which are core to your business where you can really differentiate. But for example, payment very likely is not unless you're PayPal. So yeah, it circuits back to what I said earlier with like you don't want to do that everywhere, but there are potentially parts of your business, of your code base where it makes sense to go with extra money, where it makes sense to invest this extra effort, but that really depends on your domain. That is, I guess, a sentence both software engineers who have been in the business for a while are familiar with. Well, which part of the domain is it? Yeah, it depends. So yeah, so if you want, maybe like one last section, because I also need to put this to a close. I have a follow-up meeting after this. I need to go to the headrest up with my son. So if you would want to get started, what would you like if you have like an engineer who maybe has heard about the main design, I'd be like, doesn't really understand all the buzz. And yeah, I think we gave somewhat a roundabout. view on why these ideas are important and how to put them into action into Elixir. What would be a resource you would recommend? Hey, I have a basic understanding. I know I've listened to this episode, but now how can I take this from here on? Any resources you would recommend?
Adi_Iyengar:
I mean, it's very tough. I think DDD is one of those meta concepts that you understand by doing, but that's the thing with software architecture. It's hard to get opportunities to do that because side projects probably would not be big enough in scope for you to play with different architectures.
Sascha_Wolf:
Yeah.
Adi_Iyengar:
And if you don't get that kind of opportunity at work, it's very hard to do something that kind of mimics that. But I mean... Try to design systems. Start by watching some system design videos, right? And then try to design parts of it which have complex boundaries. Just try to write code for parts that have complex boundaries. That's what I did. I watched some system design videos. I forget this guy's name. He's an Indian guy on YouTube. Boy, I forgot his name. I think he does pretty good system design stuff. He used to do it at least three, four years ago. And I think he did like... Twitter and other things, like pick a part that's most connected, has most connections, and try to write code for that. And try to design interfaces for that code and just like mock them. I know, I mean, that's the best answer I can give. You can read books and stuff, but all of this will only, you'll only kind of like, every person understands this in a different way for you to understand this you have to code. And it's, side projects of this scope are very hard. I have only two side projects with a scope and I have it at least 500 applications and I have only a couple. It's hard to write side first suspect.
Sascha_Wolf:
Yeah, I agree 100%. And it's also, if you actually have a side project of this scope, then you will probably mostly practice the tactical side, right? Because it's still the side project from your head, right? And like actually
Adi_Iyengar:
Right.
Sascha_Wolf:
getting to the, you're not the, you are basically in the same, the business expert and the developer in the same person. So you're not gonna practice all of this methodologies too well and get the knowledge from business experts. So yeah, my recommendation would be for the tactical side, I would actually recommend the book. As I mentioned earlier, Domain of Indolence is scaled. It's a lot smaller than Eric Evans' book. And it catches the essentials about the tactics and how about a bottom context explains what an entity is, it explains what an aggregator is. We didn't really talk about that in detail because there are so many resources out there. It doesn't make sense to repeat all of that. So this is a book I would recommend. And then for, well, to the more strategic side, I would, to be honest, I would actually recommend either go to Meetups. or go to conferences and talk to people who have put this into practice and maybe they participate in workshops there. That's arguably the most effective way to get started on this. Also, maybe you'll watch some talks. There's also an event Stormin' book from Alberto Bandolini, which I think is still unfinished and he probably will never finish it because the methodology also changed over time. And he's like this queerly Italian guy. I've actually met him at some point. So I'm not surprised the book never got finished. But it's also, it's a good start if you actually want to do it to get into, okay, what does the event actually mean? Like what are all of the different ideas there? And then on the middle level, like architecture, like basically strategy, meeting technical, there's a pretty good article I also mentioned in the past episode, which is DDD, Hexagonal Onion Clean Architecture, how I put it all together, I'm also going to link it, link it in the show notes. But at the end of the day, it boils really, like DDD, as I said earlier, it's like a set of principles. It's really a way of. approaching software design and software building software and solving problems at the end of the day on a really holistic perspective and There's not one single source you can point it and say hey, this is this is exactly it. It's kind of to that related to what agile like not the Everything is certified agile thing but like the original ideas behind agile is very much related to that I get was with set of principles a set of ideas you want to put into action to be better in doing projects and DDD is some on that front very much related. It's not this one thing you do it and then you do DDD but it's a set of things which can potentially help you achieve this goal better. So yeah, in a nutshell, technical domain driven design is still by Vaughan Vernon this article DDD Hexagonal Online Clean Architecture how I put it all together and go to meet apps go to go to conferences and I mean If you actually have maybe somebody who you wanted to make a project with, who has like maybe some kind of business expertise, business expert level expertise, and they've been bugging you to do the side project and you kind of want to, that could be a good opportunity to practice some of that. But I mean, I'm as a working dad, I'm not going to tell you now new side projects because well, I don't, I don't have time for that. So yeah, those were my recommendations. Okay, then I would say let us go to pics. So, Adi, what are your pics for this week?
Adi_Iyengar:
Yeah, I guess I can put boundary as one of the picks. Check it out. Good way to enforce some of the patterns we talked about. I also wrote a blog post before boundary came out about how I used xref to do something like that. If you want to check that out, see really how Elixir implements xrefs, that might be fun. Another thing, I had a few days off. And one of the things I did just I the documentation of macro module in Elixir. And it's pretty awesome. It's evolved a lot. Last year I read through that was probably 1.1 or 1.0 or something. And I, yeah, I thought it was, yeah, anyway, yeah. It was really, it was really, it has really evolved. And what you could do really now, I just, you know, just want to test its power. you could literally just use the macro modules and call the functions and macros in there and write a brain-fuck compiler, write a Turing-complete-languages compiler, which is pretty powerful. So try it out. It's actually pretty evolved a lot. And again, if you guys want like a nice, fun, hour-long project or maybe two-hour-long project, try to write a BF compiler using macro module. Another thing, I've been really... I've been really craving some data structures stuff. So I've been reading through some Erlang types, digraphs, entries. Erlang has some really good data structures too. We should check out some Erlang documentation, at least a links to all of these things for full check. Diagram especially is really good. And it's like, I think it uses ETS as a... you know, storage mechanism, which is also really cool. Awesome, so I have a couple people who are looking for jobs. I have a lot of people who are looking for jobs, but a couple especially who are very, very talented engineers. Well, three. One is one of my best friends, someone who has mentored me and is one of the best engineers I've worked with. And I've worked with quite a few good engineers. He's looking for a job. He... didn't want me to, all of these didn't want me to say their name directly. They're a little shy. So, if you're looking for a senior Elixir engineer with 80s of experience, who, and who writes awesome code, greater testing, greater pedal stack, live view and all that, reach out to me. Yeah, reach out to me and I'll connect, and I'll connect you with him. There's a couple of junior engineers, one with a lot of reals experience. even though they graduated a couple years ago, but they've been doing Rails since their first year. So they have a lot of Rails knowledge, but have been fascinated with Elixir for a while. They've been attending a mentorship session that I do weekly, Brewstate, so Fiji Benedetto, they are mentors as well there along with me. And this mentee has been attending that for a while, has a couple of years of Rails experience professionally, but has been doing Rails for Israel, looking for an Elixir job. Very talented. They're much more ahead of where I was in two years. So again, if you're looking for like a mid, junior mid Elixir engineer with Elixir interest and some Elixir knowledge with a lot of real experience, reach out. And yeah, I have a few other great engineers too. I was telling Sasha, I'm helping eight people look for jobs and potentially nine. by time this episode gets published. So reach out if you're looking for especially mid-level looks at engineers.
Sascha_Wolf:
nice. I really admire how you're helping people in the digital community finding jobs out here. I think that's great work, seriously. So yeah, I can't compete with that last, like, those picks. But I want to reiterate, like, on the resources I just mentioned, so there are two concrete things I can point you to. There is a virtual DDD community. They also have a Meetup, which is Just that, Virtual DDD meet up, they have speakers from around the world, I think they meet monthly or bimonthly, I'm not quite sure. So maybe that is something you might want to check out. But the authors have a Slack and a Twitter, so on and so forth, so that's potentially an interesting source to get started on some of these things. And I also definitely want to pick the Kandinsky, Kandididinsky, which is, it's by the way, fun fact why it's called Kandinsky, because the original art from the DDD book Domain, Different Design from Eric Evans was a Kandinsky painting. So that is why the conference is called Kandinsky. Um, and there's a Domain, Different Design conference in Germany, in Berlin. It's end of October, start beginning of November. I will be there. So, um, maybe any of you who is like living around Europe, listening to this and is interested in getting the hand study of Domain, Different Design. That could be. something you might want to check out. It's also one of these conferences, which is not super expensive. They deliberately are designed to be somewhat more affordable. They're not cheap by any means, but they're definitely not 2000 euros kind of expensive, like some of very big conferences. So yeah, Kandinsky. And to stick to my history of picking games, I have started playing... a game which is called Citizen Sleeper and it's a narrative cyberpunk science fiction game and I guess I found it in my Steam discovery queue and I was like oh this looks interesting enough I'm going to check it out and then it went on sale and I was like yeah let's get it and then some evening I was like you know what I'm not really in the mood for my usual games I'm just going to check this thing out real quick I'm going to play like an hour then it was 2am that happened If you're into cyberpunk, if you're into science fiction, if you're into narrative games with more lightweight gameplay It's not a walking simulator by any means, like not super lightweight. It has still some campaign mechanics But it's really more of a read-heavy side narrative-heavy side. I'm really enjoying it so far. Citizen Sleeper. It's on Steam. It's also available on Go.Games, but I think also for the Switch So it's available on my platform, so you might want to check it out Those are my picks for this week
Adi_Iyengar:
That actually reminded me I have one video game picked too.
Sascha_Wolf:
Hehehehe
Adi_Iyengar:
I had a few days off as I mentioned earlier and I replayed a game that I was really unimpressed with in 2020, Assassin's Creed Valhalla. Just because it was following almost a perfect game, Assassin's Creed Odyssey. I replayed it last week and I realized it's a pretty pretty solid game. It's a solid 8 out of 10. 8.5, 8 or 8.5 out of 10. So yeah, if you guys haven't played AC Valhalla, you found open world RPG, Assassin's Creed games, you should give it a try. It's actually, I think its price dropped significantly. It's like 20 or 25 bucks on at least a PS store. So yeah, check it out. It's a great game.
Sascha_Wolf:
nice i love that we stick to it's picking games okay then then this was it for this week we're actually exactly under one hour so that's nice and tune in next time with another episode of elixir mix bye bye
Domain-Driven Design And Elixir - EMx 185
0:00
Playback Speed: