5

I'm learning about DDD and in many places it's stated that the domain model classes should have properties with private setters and explicit methods to change the model's state.

I wonder the reasons of that claim. Isn't the whole idea of the C#'s property to simplify the getter and setter?

4
  • 8
    The recommendation does not come from DDD but from OO programming principles; it is not saying to replace property setters with setField() methods - that's still a setter (conceptually, in the language-independent sense). It's saying not to treat all objects as behaviorless data structures; getters and setters are a symptom of that. Instead, provide methods that represent some higher level operation, some domain concept; they would potentially take parameters, including other objects and/or functions, and change any state they own internally, never exposing it to callers directly. Commented Jul 1, 2021 at 3:16
  • 3
    E.g., when you use the Random class, it just exposes the Next method and its variants, it doesn't allow you to set (or get) internal state of the underlying RNG. It conceptually embodies a source of random numbers that allows you to ask for one. If MS wanted to ship a better implementation, they could do it because of this hiding. In some sense, it's the same reasoning as for the aggregate root idea; there are well-defined entry points that control the internals and keep everything consistent, as opposed to relying on client code all over the codebase to leave everything in a consistent state. Commented Jul 1, 2021 at 3:16
  • @FilipMilovanović very fruitful information, thanks. If I may, could you name and briefly explain another use cases which would be correct to use the plain old data scheme on models and let them with the classic public get/set accessors? Commented Jul 1, 2021 at 13:31
  • 1
    @FilipMilovanović, those two comments should have been an answer. Can you convert them to one? Commented Jul 2, 2021 at 5:34

3 Answers 3

14

Why DDD models should have private setters?

You'll find some arguments that DDD models shouldn't have setters at all.

Context: Evans published the original DDD book in 2003. It is largely a patterns book, influenced by Alexander, Beck, Cunningham, the "Gang of Four", Fowler, etc.

In that community, it was a largely accepted assertion that Anemic Domain Models were a bad idea.

The catch comes when you look at the behavior, and you realize that there is hardly any behavior on these objects, making them little more than bags of getters and setters.... The fundamental horror of this anti-pattern is that it's so contrary to the basic idea of object-oriented design; which is to combine data and process together. -- Fowler, 2003

(Note: "object-oriented" should probably be understood here to mean the "best practices" of Java/C++/C# programming, rather than Alan Kay's "the big idea is messaging" sense).

Setters conflict with a couple of important ideas. One is that the model acts as a module in the Parnas sense; in particular that it hides the design of its data structure. Another is the notion that the api of our model should reflect the language of the domain that we are modeling; Get/Set, like Create/Read/Update/Delete, are not the natural language of business.

Expressed another way: general purpose storage and retrieval methods are appropriate for a data model, but are not appropriate for a domain model; instead, we should be using the domain language to share information with the domain model, and allow that model in turn to decide how its internal data model should be used.

The different tends to be more important when you are dealing with complex models, where changes to different parts of the data model need to be coordinated to maintain one or more "invariants". We therefore arrange the code such that all changes to the domain model must pass through a checkpoint that maintains the invariant.


This discipline tends to be a lot more important for models that are the authority for some information. When we're just storing a local copy of information from the outside world (like "customer name"), we're more likely to be able to get away with a "property" oriented design.


So we should avoid public getters as well? I thought that constraint was only related to public setters.

This one is more complicated.

If you can't get information out of the model, somehow, then the model is a waste of everyone's time: /dev/null is a lousy database.

But also: handing out references to your internal data structure makes a real mess of encapsulation.

Handing out copies of information will normally be safe; at which point you are in a style battle over whether getInformation is the best spelling to use.

Interface segregation can enter the picture as well, as not all clients of the model will need access to all of the information.

You'll see more discussion of this sort of thing in the communities, where additional models are sometimes introduced for specific read/query concerns.

3
  • Perfect, so besides this notion coming from an OO foundation, in the real world we will see this approach being more prominent being applied to DDD models, right? Commented Jul 1, 2021 at 13:29
  • I'm sorry - I'm having trouble understanding this question. If you're asking do I think this principle is applied more to DDD models than elsewhere? Not often enough to make a practical difference: Sturgeon's Law. Commented Jul 2, 2021 at 12:41
  • 1
    @VoiceOfUnreason A fair answer. One point however: Avoiding getters is not "more complicated". It is the same thing. If you have behavior there is no need to access "data". You don't "get information out of the model", you tell it what to do. That is the whole point. Commented Jul 7, 2021 at 20:47
6

I am going to answer the question from another point of view.

When you have public setters in your Domain Model classes, you allow other processes to change the internal state of the Domain Model without its supervision which means that you transfer the business rules and invariants out of the Domain Model. It causes your Domain Model to suffer from a sickness that is called Anemic Domain Model.

Eliminating public setters from Domain Model classes forces you to have some methods that apply business rules and invariants inside the Domain Model.

Constructors and Factories are responsible to set the initial state of Domain Model classes; those methods should validate the initial data and keep the internal state valid.

You may say, I can encapsulate the business rules and invariants inside the setters. This is right, but in this case, you lose the power of the ubiquitous language that is a powerful aspect of DDD. Nouns that are used to name the properties of a class cannot carry all meaning of ubiquitous language in a Domain Model.

2

The domain model classes should relate to things in the real world as much as possible. For example some model classes are; a computer, a keyboard, a screen these are for a model of a desktop computer.

So given that a model class represents a thing and the methods associated with it relate to its behaviour.

For example for a computer object.

Name: Computer

Methods:

  1. Turn On.
  2. Turn Off.
  3. Open disk tray.
  4. Insert USB stick.
  5. Connect to power socket.

Here now we can see if you add Getters and Setters they don't contribute to the model you're creating. They just provide useful access to the objects properties. However, Setters and getters are fine, if your model needs them then use them, but always prefer proper methods like the computer object above.

3
  • Interesting. So we should avoid public getters as well? I thought that constraint was only related to public setters. Commented Jul 1, 2021 at 20:58
  • @underthevoid, the Computer model shown by @Richard would probably also have methods like Is Turned On or Is disk tray open. Those count as getters (even if their implementation doesn't directly map to a single member variable). Commented Jul 2, 2021 at 5:42
  • @underthevoid yes avoiding getters will enrich the model too. Bart can Ingen Schenah is correct, getters should be replaced by "questions" like Is Turned On, Is Plugged In, Number Of Usb Ports.etc
    – r0k1m
    Commented Jul 2, 2021 at 7:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.