Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Tactical/technical DDD patterns should only be used for parts of the code where there is a lot of business agility required, so the behavior of your code changes a lot, and you have a tight feedback loop with your business unit.

Your story sounds like they implemented a "technical DDD top-level architecture" (TM), whatever that may be. (I'd assume layers of abstractions coupled with logic spread all over the place, without any added benefit.)

You see this a lot when people read some stuff about DDD, and they start experimenting with the technical/tactical patterns, because this is the aspect that makes most sense to a technical audience.

In reality the tactical/technical DDD patterns should only be applied in the core part of your business (i.e. the thing that gives you a strategic advantage over your competitors.), because that typically needs to change a lot, so having a common language/model with the business tends to be worth the extra upkeep required when opting for more flexible models.

Identifying what the core part is of your business (most likely it's not authentication, billing, invoicing, content management, ...) is one of the more important (and most difficult) aspects of DDD.



I attended the Domain Driven Design Exchange conference in London years ago. They keynote was by Eric Evans (author of the DDD Blue Book)

He said if he wrote the book again, he'd have put all the patterns as an appendix

He thought people concentrate on applying the patterns rather than seeing DDD as a way to communicate. Between developers but also to the business


Right, communicating to the business is actually the core message of DDD. It should potentially be called “anthropological design” since the “domain experts” are a synonym for your non-technical users of your software (the domain is the business domain, which is whatever your software is trying to do for them). The message is that you have to observe your users in their natural habitat.

Let me put it this way, when Twitter started out, they did not have tweets. They had posts, and the act of posting to Twitter was called twittering. They were not associated with birds (actually more with whales lol). The idea of birds and tweeting actually came later with a third-party client interacting with their API.

Eric Evans in the early aughts now makes a big splash with this outrageous statement, where many of us graybeards would instead say “if it ain't broke don't fix it”: Eric Evans would recommend that the posts table in the database be renamed to the tweets table. Version 2 of the API should not reference “posts” or post_ids, but rather tweets and tweet_ids.

Why?! Those sorts of migrations are painful and clumsy! Yes, Eric says. (He is not stupid.) Maybe it's a lost cause. But, Eric remarks on two things:

1. There is no reason to believe, given software’s previous performance, that any amount of upfront planning is going to generate the most consistent useful model before the software is built and we can interact with it. So you're going to want to iterate. What are the systematic obstacles to renaming the table and the API, and can we overcome them so that we can do lots of little experiments?

2. Something else that is clumsy and painful, is when your users come to you reporting a problem with Widgets or whatever, and you go off and you fix the FactoryService to add some new functionality to widgets, tell the user that their problem is fixed, and they go and do the thing again and run into the same problem that they ran into, “it's not fixed yet!”. Why did this happen? One big reason is that the word “widget” means something different in the database versus the backend, or in the backend versus the frontend, or in the frontend versus the real world. Twitter might get some other notion of “topics” and they roll it out and everyone starts to call them “posts”, now the topic table holds posts and the posts table holds tweets, and you're always looking for “posts” in the wrong table now.

So, you should rename the table because first, this should be a possible thing for you to do and building up that sort of leverage is going to pay dividends later, and second, the less friction we can have by transforming the way we developers speak into the way that our users speak, is going to pay dividends too.

This anthropology is kind of the core part of DDD, I don't understand why people try to do DDD as design patterns rather than saying that it's the users who unwittingly dictate the design, as we redesign around them to reduce friction.

It's similar to, I don't understand why people find it hard to draw context boundaries in DDD. So bounded contexts are a programming idea, in programming we call them namespaces, they exist to disambiguate between two names that are otherwise the same. DDD says that we need to do this because different parts of the business will use the same word to refer to different things, and trying to get either side of the business to use some different word is error-prone and a losing proposition. So instead we need namespaces, so that both of our domain experts can speak in their own language and we can understand them both because in this context we use this namespace, in that context we use that namespace. So: where do you draw the boundary? In other words how big should your modules be? (Or these days, for “module” read “microservice”.)

Simple: you partition users into groups, based on the sorts of things that they seem to care about when they are interacting with the system, and the different ways that they talk about the world. The bounded context is not an “entity” or a “strong entity” or a service-discovery threshold, rather it is an anthropological construct just like everything else in DDD. “The people in shipping care about this for one reason, the people in billing care about it for another, they don't usually talk to each other, but I guess sometimes they do...” sounds like you've got a shipping module/microservice and a billing module/microservice. The boundary is the human boundary.

Similarly for “should I use events or RPC?” ... Does someone from shipping ever come up to the billing department and say “The delivery costs a ton more because XYZ, the customer said they preferred to pay more rather than cancel the order, I am gonna stay here in billing until this critical task is complete,” or whatever, or would they prefer an asynchronous process like email, “we will just put it on the shelf until we can pay to safely ship it.” Different industries would have different standards here! If it's something that has no shelf life, that delivery does not want to keep in the shelves for one second longer than it has to, then that drives the different behavior. Only way you can know is by observing your users in their natural habitat.


DDD technical patterns are a weird bunch.

On one hand, there are quite a few smart concepts in there. Everyone should know what aggregates are, for example.

On the other hand, many of them have little to do with the basic premise of DDD. You can have DDD without these specific patterns.

On the third hand, people start applying every single pattern everywhere, like they did with GoF patterns.


I'd advice people new to DDD to involve themselves with understanding the Strategic Design parts first. The rationale, pros and cons for using it etc. And stay well away from tactical patterns until you know the role of DDD wrt the objectives you want to achieve. Strategic vs. tactical are completely different concerns. The problem with a lot of DDD information is that people tend to dive into tactical way to early and introduce all kinds of architecture that is not needed. Note that result of strategic analysis may well be to conclude that a simple CRUD design is the best way forward (for a subdomain or even the entire project). The non-technical domain understanding is most important, and also helps heaps in keeping your (non-technical) stakeholders in the loop throughout the development process.


I found this book very good in that regard. The first half of the book is on strategy and emphasizes its importance. It also makes it clear that only a subset of your system is suitable for DDD (for example, not the CRUD bits). I also found it much clearer and less verbose than the Evans book.

https://www.wiley.com/en-us/Patterns%2C+Principles%2C+and+Pr...


Yes, this is a very good introduction to DDD proper, with the primary focus on when to apply what parts of it!


> On the other hand, many of them have little to do with the basic premise of DDD.

Honestly, I see no relation at all. Those technical patterns can be applied the same way whether you model your code after the domain or not, and you don't need them at all to model your code after the domain.

They look a lot like "true Agile" 2.0.


Good post. The technical patterns are nigh useless unless you're going all in on event sourcing and/or CQRS - and perhaps even then. KISS > DDD.

To me, what matters are the strategic patterns, i.e. how you think and talk about your domain. What a lot of (microservice) software gets wrong is bounded contexts and APIs, which can be improved through event storming (discussing what kind of things happen in your domain) and context mapping (how that [sub]domain interacts with others). And then there's ubiquitous language, or calling the thing what it is to the business, not some programmer gobbledygook.


All you need is a common vocabulary around English proper nouns and some idea of how they work together.

And then the client data has all fields named in Spanish with abbreviations, lettering and numbering everywhere.


I'm an Argentine Spanish-English bilingual programmer. I try to program exclusively in English, but when developing integrations to Argentine systems I often have to fall back to spanglish code.

In general it's preferable to use only english because the code is more readable (because the language's keywords and APIs are in english), but also to maintain consistency with noun-adjective order, verb tenses, etc. Some local concepts can be easily translated (or at least it would seem so) like invoice-factura ... but then inevitably I arrive at concepts for which there is no obvious translation (so I could make one up, but it would not be clear enough for others) or for which the translation doesn't exactly line up.


I think this is common all around the world. For example, the more my teams get close to money and regulations the more we have to use words of our own language. It would be pointless trying to invent a translation of very precise legal words for concepts that exist only in our own country.


I generally treat all country-specific stuff as data.


Any tips on to persuade a stakeholder , senior leader, or your team lead that their area of focus is not a core part of the business without them feeling defensive about their status within the company?

Any tips of how to do DDD when every area is considered a core priority of the business because uncomfortable conversations are hard?


Frame it in terms of money.

"There is some benefits to what you're proposing. My primary concern is cost. I see no technical difficulties with doing it <this other way>, and one of the benefits of that is that you'd have it ready in a tenth of the time. If I'm wrong, we can always change our minds and build it your way. That would barely take any additional time at all, since what I'm proposing is so simple to begin with.

"So, what do you say? Would you like to try to get it done by November, or should we labour over it until next June? If I understand the business figures right, if we can get it out in November, we'll make $6,000,000 more – and it would all be because you made the right technical decision here."


> "So, what do you say? Would you like to try to get it done by November, or should we labour over it until next June? If I understand the business figures right, if we can get it out in November, we'll make $6,000,000 more – and it would all be because you made the right technical decision here."

... <End of Year Review>

"We were able to get this out by end of November, thanks to your good technical decision. $6,000,000 saved! Congrats and great job. Accordingly, you've qualified for an annual bonus of a $100 Amazon Gift Card and the default 1.5% raise.

Keep up the good work!"


> Any tips on to persuade a stakeholder , senior leader, or your team lead that their area of focus is not a core part of the business without them feeling defensive about their status within the company?

To get buy-in you have to provide value for them that aligns with their needs. If they desire a delusional feeling of outsized importance within an organization then you need to be quite creative. It's more likely that their needs are simpler though. They need to feel they are getting value from you, even if the other parts of the business hold more of the cards.

Try to find simple things to fix for them, choose to build out features with their input, and when building new features for the main stakeholders try and prioritize items which help multiple stakeholders. This is good practice in any case because in the long-term things can change quite significantly within organizations and you don't want to be perceived as only an ally of some within the business.

UPDATE: Beware of quantifying too much. This really impresses some people but will make others feel really small. You may completely lose a connection with one of the smaller stakeholders by quantifying every detail and calling out big numbers around the large stakeholders. You need to work qualitatively for the most part for them. If you want to use numbers, pilot something with a small stakeholder and make a 25% increase to their sales (or a cost reduction). If big holders can get a similar percentage then that translates to big numbers. It feels like a big number to both groups.


I have a few ideas, in fact I gave a talk about that a long time ago [0], but I think one of my friends Marijn gave a good suggestion on twitter [1]: don't sell DDD, but fix your the problem your boss has.

[0] https://www.slideshare.net/TomJanssens1/selling-ddd

[1] https://twitter.com/huizendveld/status/1440683623628230665


I think the question was more how to sell not-doing-DDD.

Reasonable people (including DDD advocates) clearly understand that tactical patterns can easily be misapplied, and that the strategic part of it is more important, but inexperienced programmers jump in on the "new" fad (it's not even that new, which is most perplexing to me), and misapply all the patterns they possibly can.

I see there's a lot of similar sentiment here, so I think the question really is: how to convince inexperienced "converts" where the right boundary of applying tactical DDD solutions is?


One cause of misapplying tactical patterns is learning. When people start learning something, they do it badly and in inappropriate contexts. The solutions to this are:

A. Don't learn things.

B. Dedicate some amount of time to learn something in a sandbox before using it on the job.

C. Once you've learned something well enough to see the error of your ways, dedicate some amount of time to clean up your old work.


I know A is a tongue-in-cheek, but I think you underestimate human's ability to apply things by learning from good learning materials.

B and C are a single thing, and unfortunately, C does not happen, which is why any particular methodology gets a bad rep. And it's obviously already happening with DDD (judging by the polarized sentiments around here).

And finally, while I do believe abstraction is the ultimate tool of the human mind (and mathematics is the purest form of abstraction we are capable of), I do not think it suits all brains equally, and not everybody will be equally capable of ever getting the right understanding. Basically, your architecture can be _too smart_ if you are looking to hire actual, real-world developers and software engineers, and have them be efficient.


> Your story sounds like they implemented a "technical DDD top-level architecture" (TM), whatever that may be. (I'd assume layers of abstractions coupled with logic spread all over the place, without any added benefit.)

Exactly :)


> In reality the tactical/technical DDD patterns should only be applied in the core part of your business [...]

I cannot imagine anything where it would make sense unless you're implementing an actual framework such as Spring in javaland.

And at that point I'd say you're wasting effort and just using spring boot should be preferable.

It does make sense with these super low level frameworks though, but which corporation makes them in-house at this point?


Think about for example a planning component for hospital beds... There are a lot of parts that are really straightforward to implement, but for these planning components it might make more sense to develop an in-house component. (Assuming existing constraint solvers and/or rule engines are not a viable solution for you in this particular scenario.)

If your business is talking about updating/deleting/inserting data, you are not describing the actual reasoning behind the change. For DDD, it makes sense to figure out why exactly you are doing the things you do, and model these explicitly in your systems for those parts that matter.

The stereo-typical example for this is an address change: if you model this as an "AddressUpdated", you might as well use CRUD, as this does not specify the intent of the change.

You could change an address because it contained a typo, but you can also change it because someone moved. These might lead to different outcomes, so in DDD you would typically model these as "AddressTypoCorrected" and "ContactMoved".

There are other fine-grained aspects, for example the need of an identity for an object: physical money is considered a value object (so it has no specific ID per instance) in almost all contexts, unless you are the national bank: all of a sudden the identity (serial number of the bill) does matter, so the same "thing" might have different "models" within different parts of the business.

Other examples might be value objects for specific areas, for example weight. Typically weight starts out as a number, and all of a sudden there might be a need to add a precision, mark it as an estimate, or have it "unknown". In order to avoid if-statements all over the code, you construct a "weight value object" that properly manages all of these peculiarities in a single place (i.e. what's the result of an estimate+undefined etc.)


You clearly have some positive experience with DDD, and I'm definitely not trying to say that DDD is broken by design or anything like that.

I'm sure there are successful and maintainable projects that utilize this design approach.

Nonetheless, the only thing I could think of after reading your example is just how many subtle bugs and inconsistent behaviors this engine will have with various edgecases, so I'm still pretty convinced I'd rather implement it with less abstraction/indirection.

It might just be a difference of character at the end of the day, because I do agree that what you write sounds great. I just see it more like a triangle in the CAP theorem, where the edges are speed, abstraction/extensibility and stability/consistency


> Nonetheless, the only thing I could think of after reading your example is just how many subtle bugs and inconsistent behaviors this engine will have with various edgecases, so I'm still pretty convinced I'd rather implement it with less abstraction/indirection.

This example clarifies the intent behind DDD: make the implicit explicit and make sure there is awareness about all the edge cases.

It might be as simple as contacting a user in case you have an uncovered edge case, but at least you'd be aware that your system is unable to handle edge case X. (In non-DDD scenarios this would just be a bug that emerges - implicit behavior.)


Yes! When the project becomes large enough, a lot of value loss can be prevented by discovering edge cases before implementation, and DDD practically forces that to happen. Less things discovered by devs means less design cycles, which means less effort lost in design and implementation—of course only as long as proper grooming is done to avoid implementing things out of customer priority.


> Nonetheless, the only thing I could think of after reading your example is just how many subtle bugs and inconsistent behaviors this engine will have with various edgecases, so I'm still pretty convinced I'd rather implement it with less abstraction/indirection.

This line of reasoning cuts both ways: how many bugs and inconsistent behaviors often pop up because developers rushed to write code without gathering enough requirements on the domain, how many productivity problems are caused by growing the system by accretion where it can, and how many rewrites were required just to fit the system's domain to the problem and shed technical debt from the accretion.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: