5

DDD teaches us to build our classes like their real-world prototypes.

So instead of using setters

job = new Job
job.person = person
job.since = time.Now()
job.title = title

we define well-named methods in our aggregation root

job = person.promote(title, /** since=time.Now() **/)

Now the tricky part

Assume we have an UI for an HR where he/she enters a new title via the HTML form and makes a typo like "prgrammer" (Of course in real application there'd be a select list, but here we have a text input), or selects a wrong date (like default today)

Now we have a problem. There are no typos in real world. Our John Doe is definitely a "programmer" and never a "prgrammer"

How do we fix this typo in our domain model?

Our Person has just promote, demote, fire, etc. methods, which reflect the HR domain model.

We could cheat a little bit and change the Job record directly, but now we have a Job.setTitle method, that doesn't reflect our domain model and also, setters are evil, you know.

That may look a little "academic", but that really bugs me when I try to build a good domain model for a complex application

dmzkrsk
  • 2,011
  • 2
  • 20
  • 30

4 Answers4

5

Another side of DDD is invariants - "always valid" entity. And when you try to break this invariant (some rule) you must stop execution and say "loudly" adout this (throw exception). So, you need to have a list of valid titles and when you try to change title (does not matter how) to invalid state, you must throw some usefull exception.

To "fix" typo situations you must separate operations in your domain promote is one operation (it may check something, sent contratulation email :) and so on). And edit operation - just to edit some properties. So, the differenece is in logic of operations. You can't call promote without some preconditions (for example, required experience of worker), but you can call edit and fix worker's name because of type. And usually this operations are separated between different users: only HR's can promote but a worker can edit his name, if it's wrong. This solution is very complicated for such example, but it's always with DDD. The main concept - separate operations. Each one with their own conditions, permissions, rules.

A question about invariants (rules).

Community
  • 1
  • 1
Backs
  • 24,430
  • 5
  • 58
  • 85
  • But what when the HR person chose the wrong title from a list of valid titles? – Alexander Langer Aug 14 '15 at 07:24
  • @AlexanderLanger HTML is just a view and it can have another model (ViewModel) and user theoretically (or by security violation) can select wrong value, but when you attempt to set this value to your entity, you must throw exception. The best way - don't allow to select wrong values (especially you have list ok right titles to validate entity) – Backs Aug 14 '15 at 07:28
  • Yeah, this works for a predefined list of titles. But what about people's names? You can't have a complete list of names or Sam and Pam are both valid names, but one of them could be a typo – dmzkrsk Aug 14 '15 at 07:28
  • @dmzkrsk ddd does not protect you from typo. Because, only user know, what is right Sam or Pam. It's a question about quality control, not ddd, i thnik – Backs Aug 14 '15 at 07:31
  • 2
    The question is not about protection from typos, but about **fixing** typos in a _DDD way_ – dmzkrsk Aug 14 '15 at 07:32
  • `edit` is quite a CRUDdy operation to be DDD-oriented. Perhaps data corrections are CRUD by nature in some contexts and for those a CRUD solution in a separate BC could be appropriate. However, If you wish to give more importance to how and why mistakes were made CRUD is not appropriate, but you could find a better operation name than `edit` which doesn't tell the what and the why and is not any better than `update`. Also, the first-half of the answer about always-valid entities is not relevant to the question at all. – plalx Aug 17 '15 at 15:15
  • @plalx `edit` is simplified description of opertation, and, of couse, is not the best name – Backs Aug 18 '15 at 02:57
  • @dmzkrsk hi, have you found answer? – Backs Oct 04 '15 at 06:17
1

If a client is purely entering data, then the underlying domain in this (bounded) context is not very deep. In these cases, it's fine to use a CRUD style application and allow titles to be changed (setTitle()).

Just make sure dependent BCs (e.g., billing, vacation planning, ...) where no such thing as "invalid data" exists, can react to changes in your CRUD context appropriately.

Alexander Langer
  • 2,883
  • 16
  • 18
1

The application should enforce input correctness before it reaches the domain layer, no garbage input. If that means using a dropdown for the job titles then so be it. You can validate the title against existing titles.

In my company of 18 thousand employees, typo happens all the time. You are going to have to be pragmatic about this and accept that there will be setters in your code (one way or another)

Pragmatic thinking is very much at the core of the domain driven design, and is what keep things simple.

"Purity is good in theory, but in practice it can be very difficult to achieve, and sometimes you must choose the pragmatic approach" - Patterns, Principles, and Practices of Domain-Driven Design (2015)

Yorro
  • 11,445
  • 4
  • 37
  • 47
1

"There are no typos in real world", I get what you mean, but that's not true, there are human mistakes in real world scenarios and they should be accounted for in your domain if they are frequent.

If data entry errors aren't frequent it may not be worth the extra modeling efforts and those could perhaps just get fixed directly in the DB. It also depends if the business wishes to learn something about those mistakes or not.

However, if data entry errors are frequent, it might be an indicator that the system is perhaps not offering enough guidance and the business may wish to learn more about those errors in order to make processes more efficient and less error-prone.

You may wish to implement an operation such as job.correctTitle(...), perhaps in a BC dedicated to data corrections? Also, it's probably very rare that each and every piece of information will be erroneous so corrective operations can be segregated. That means you probably do not need a job.correctAllInformation(...) kind of operation.

This whole scenario is very fictive since job titles would usually be managed in a separate BC from where they are used and they would probably get picked from a list, therefore typos would be less frequent, but you will always have to deal with data entry errors. Choosing the appropriate solution is not always easy and will vary from case to case, but try to stay pragmatic and not strive for the perfect model in every sphere of your domain.

plalx
  • 42,889
  • 6
  • 74
  • 90