- "Connecting model and implementation has to be done at the detail level."
- Associations
- "For every traversable association in the model, there is a mechanism in the software with the same properties."
- "In real life, there are lots of many-to-many associations, and a great number are naturally bidirectional. The same tends to be true of early forms of a model as we brainstorm and explore the domain. But these general associations complicate implementation and maintenance. Furthermore, they communicate very little about the nature of the relationship."
- Three ways of making associations more tractable
- Imposing a traversal direction
- "The United States has had many presidents, as have many other countries. This is a bidirectional, one-to-many relationship. Yet we seldom would start out with the name "George Washington" and ask, "Of which country was he president?" Pragmatically, we can reduce the relationship to a unidirectional association, traversable from country to president. This refinement actually reflects insight into the domain, as well as making a more practical design. It captures the understanding that one direction of the association is much more meaningful and important than the other. It keeps the "Person" class independent of the far less fundamental concept of "President."
- Adding a qualifier, effectively reducing multiplicity
- "Very often, deeper understanding leads to a "qualified" relationship. Looking deeper into presidents, we realize that (except in civil wars, perhaps) a country has only one president at a time. This qualifier reduces the multiplicity to one-to-one, and explicitly embeds an important rule into the model. Who was the president of the United States in 1790? George Washington."
- Eliminating nonessential associations
- "Of course, the ultimate simplification is to eliminate an association altogether, if it is not essential to the job at hand or the fundamental meaning of the model objects."
- Entities (A.K.A. Reference Objects)
- "Many objects are not fundamentally defined by their attributes, but rather by a thread of continuity and identity."
- "many things are defined by their identity, and not by any attribute. In our typical conception, a person [...] has an identity that stretches from birth to death and even beyond. That person's physical attributes transform and ultimately disappear. The name may change. Financial relationships come and go. There is not a single attribute of a person that cannot change; yet the identity persists."
- "Some objects are not defined primarily by their attributes. They represent a thread of identity that runs through time and often across distinct representations. Sometimes such an object must be matched with another object even though attributes differ. An object must be distinguished from other objects even though they might have the same attributes. Mistaken identity can lead to data corruption.
- Modeling Entities
- "[T]he most basic responsibility of entities is to establish continuity so that behavior can be clear and predictable. They do this best if they are kept spare. Rather than focusing on the attributes or even the behavior, strip the entity object's definition down to the most intrinsic characteristics, particularly those that identify it or are commonly used to find or match it. Add only behavior that is essential to the concept and attributes that are required by that behavior. Beyond that, look to remove behavior and attributes into other objects associated with the core entity. [...] Beyond identity issues, entities tend to fulfill their responsibilities by coordinating the operations of objects they own."
- Designing the Identity Operation
- "Each entity must have an operational way of establishing its identity with another object -- distinguishable even from another object with the same descriptive attributes. An identifying attribute must be guaranteed to be unique within the system however that system is defined -- even if distributed, even when objects are archived."
- Value Objects
- "Tracking the identity of entities is essential, but attaching identity to other objects can hurt system performance, add analytical work, and muddle the model by making all objects look the same.
"Software design is a constant battle with complexity. We must make distinctions so that special handling is applied only where necessary.
"However, if we think of this category of object as just the absence of identity, we haven't added much to our toolbox or vocabulary. In fact, these objects have characteristics of their own and their own significance to the model. These are the objects that describe things." - "When you care only about the attributes of an element of the model, classify it as a value object. Make it express the meaning of the attributes it conveys and give it related functionality. Treat the value objects as immutable. Don't give it any identity and avoid the design complexities necessary to maintain entities."
- Designing Value Objects
- "We don't care which instance we have of a value object. This lack of constraints gives us design freedom we can use to simplify the design or optimize performance. This involves making choices about copying, sharing, and immutability."
- To safely share or copy value objects, they must be immutable.
- You can choose either to share or to copy, depending on what constraints you are trying to optimize for.
- Designing Associations that Involve Value Objects
- Bidirectional associations between two value objects make no sense.
- Without identity, it is meaningless to say that an object points back to the same value object that points to it.
- "Try to completely eliminate bidirectional associations between value objects. If in the end such associations seem necessary in your model, rethink the decision to declare the object a value object in the first place. Maybe it has an identity that hasn't been explicitly recognized yet."
- Services
- "Some concepts from the domain aren't natural to model as objects. Forcing the required domain functionality to be the responsibility of an entity or value either distorts the definition of a model-based object or adds meaningless artificial objects."
- A service is an operation offered as an interface that stands alone in the model, without encapsulating state, as entities and value objects do.
- A good service has three characteristics:
- The operation relates to a domain concept that is not a natural part of an entity or value object.
- The interface is defined in terms of other elements of the domain model.
- The operation is stateless.
- Services and the Isolated Domain Layer
- Services are used in other layers than just the domain layer.
- "It takes care to distinguish services that belong to the domain layer from those of other layers, and to factor responsibilities to keep that distinction sharp."
- Granularity
- The service pattern can be used as a mean of controlling granularity in the interfaces of the domain layer.
- "Medium-grained, stateless services can be easier to reuse in large systems because they encapsulate significant functionality behind a simple interface."
- Access to Services
- "Distributed system architectures [...] provide special publishing mechanisms for services, with conventions for their use, and they add distribution and access capabilities. [These] architectures should be used only when there is a real need to distribute the system or otherwise draw on the framework's capabilities."
- Modules (A.K.A Packages)
- "Everyone uses modules, but few treat them as a full-fledged part of the model. Code gets broken down into all sorts of categories, from aspects of the technical architecture to developers' work assignments. Even developers who refactor a lot tend to content themselves with modules conceived early in the project.
"It is a truism that there should be low coupling between modules and high cohesion within them. [...] There is a limit to how many things a person can think about at once (hence low coupling). Incoherent fragments of ideas are as hard to understand as an undifferentiated soup of ideas (hence high cohesion)." - "Choose modules that tell the story of the system and contain a cohesive set of concepts."
- "Give modules names that become part of the ubiquitous language. Modules and their names should reflect insight into the domain."
- Agile Modules
- "Modules need to coevolve with the rest of the model. This means refactoring modules right along with the model and code."
- This refactoring often doesn't happen because there are many difficulties in refactoring modules.
- "Whatever development technology the implementation will be based on, we need to look for ways of minimizing the work of refactoring modules, and minimizing clutter in communicating to other developers."
- The Pitfalls of Infrastructure-Driven Packaging
- Many frameworks encourage package structures that reflect the infrastructure.
- This can lead to a business object being split across multiple packages, causing low cohesion.
- This can also lead to packages that have a high number of calls between them, causing high coupling.
- "Use packaging to separate the domain layer from other code. Otherwise, leave as much freedom as possible to the domain developers to package the domain objects in ways that support their model and design choices."
- Modeling Paradigms
- Why the Object Paradigm Predominates
- Object modeling strikes a nice balance of simplicity and sophistication.
- It also has significant circumstantial advantages deriving from maturity and widespread adoption.
- It has a mature developer community.
- Nonobjects in an Object World
- "Whatever the dominant model paradigm may be on a project, there are bound to be parts of the domain that would be much easier to express in some other paradigm."
- "When there are just a few anomalous elements of a domain that otherwise works well in a paradigm, developers can live with a few awkward objects in an otherwise consistent model."
- "But when major parts of the domain seem to belong to different paradigms, it is intellectually appealing to model each part in a paradigm that fits."
- "[M]aking a coherent model that spans paradigms is hard, and making the supporting tools coexist is complicated."
- Sticking with Model-Driven Design When Mixing Paradigms
- "Without a seamless environment, it falls on the developers to distill a model made up of clear, fundamental concepts to hold the whole design together."
- "The most effective tool for holding the parts together is a robust ubiquitous language that underlies the whole heterogeneous model."
Technology is always changing. It makes the industry interesting and exciting to work in, but it also makes it hard for you, as a developer, to keep up with the changes, let alone get ahead. And yet staying on top of these changes, and thriving because of them, is a rewarding and worthwhile goal, because by doing so, you unlock the potential of what you can accomplish. Here, I explore the how of doing just that.
Wednesday, May 27, 2020
Domain Driven Design Chapter 5 Summary
Chapter 5: A Model Expressed in Software
Labels:
domain-driven-design