More on this book
Community
Kindle Notes & Highlights
by
Evans Eric
Read between
May 28, 2022 - September 10, 2023
A deadly divide opens between analysis and design so that insight gained in each of those activities does not feed into the other.
When a model doesn’t seem to be practical for implementation, we must search for a new one. When a model doesn’t faithfully express the key concepts of the domain, we must search for a new one.
The modeling and design process then becomes a single iterative loop.
The code becomes an expression of the model, so a change to the code may be a change to the model.
Development becomes an iterative process of refining the model, the design, and the code as a single activity (see Part III).
What the script writers were trying to do was to supplement the tool’s domain model with the concept of “bus.”
Their implementation infers the bus’s existence through sorts and string matches, but it does not explicitly deal with the concept.
Now we need to organize those concepts explicitly into a model we can base software on.
With these objects implemented in an object-oriented language, the core functionality becomes almost trivial.
Most of the advice and examples go to the problems of having separate analysis models and design models, but here we have a problem arising from a different pair of models: the user model and the design/implementation model.
The material in the following three chapters is organized as a “pattern language” (see Appendix A), which will show how subtle model distinctions and design decisions affect the domain-driven design process.
Isolating the domain design from the mass of other concerns in the software system will greatly clarify the design’s connection to the model.
Following proven patterns for individual elements helps produce a model that is practical to implement.
We need to decouple the domain objects from other functions of the system, so we can avoid confusing the domain concepts with other concepts related only to software technology or losing sight of the domain altogether in the mass of the system.
Creating programs that can handle very complex tasks calls for separation of concerns, allowing concentration on different parts of the design in isolation.
At the same time, the intricate interactions within the system must be maintained in spite of the separation.
The essential principle is that any element of a layer depends only on other elements in the same layer or on elements of the layers “beneath” it.
Communication upward must pass through some indirect mechanism, which I’ll discuss a little later.
But that user interface could be replaced by a wire request in XML without affecting the application layer or any of the lower layers.
This decoupling is important not because projects frequently need to replace user interfaces with wire requests but because a clean separation of concerns keeps the design of each layer easy to understand and maintain.
Layers are meant to be loosely coupled, with design dependencies in only one direction.
But when an object of a lower level needs to communicate upward (beyond answering a direct query), we need another mechanism, drawing on architectural patterns for relating layers such as callbacks or OBSERVERS (Gamma et al. 1995).
For our purposes, all approaches are fine as long as they maintain the isolation of the domain layer, allowing domain objects to be designed without simultaneously thinking
about the user interface that might interact with them.
I think this is what react redux does - it makes the global state observable by wrapping the react components with an higher order component that subscribes to global state changes and trickles down the state to its wrapped component as imuttable properties. This forces the wrapped component to re-render with up-to-date properties derived and synchronized with global state.
But not all infrastructure comes in the form of SERVICES callable from the higher layers.
Some technical components are designed to directly support the basic functions of other layers (such as providing an abstract base class for all domain objects) and provide the mechanisms for them to relate (such as implementations of MVC and the like).
(It may seem counterintuitive for a subclass to be in a layer higher than that of the parent class, but keep in mind which class reflects more knowledge of the other.)
But frameworks can easily get in the way, either by making too many assumptions that constrain domain design choices or by making the implementation so heavyweight that development slows down.
When applying a framework, the team needs to focus on its goal: building an implementation that expresses a domain model and uses it to solve important problems.
For example, early J2EE applications often implemented all domain objects as “entity beans.” This approach bogged down both performance and the pace of development.
Instead, current best practice is to use the J2EE framework for larger grain objects, implementing most business logic with generic Java objects.
Newer frameworks will automate or prefabricate more and more of the technical aspects of an application.
elaborate frameworks can also straitjacket application developers.
Unfortunately, there are influences other than infrastructure and user interfaces that can corrupt your delicate domain model.
You have to cope with other development teams who use different models of the same domain.
Chapter 14, “Maintaining Model Integrity,” deals with this topic, int...
This highlight has been truncated due to consecutive passage length restrictions.
as BOUNDED CONTEXT and ANTICORRU...
This highlight has been truncated due to consecutive passage length restrictions.
Next, we’ll look at the nuts and bolts of co-evolving an effective domain model and an expressive implementation.
This discussion will start with the issues of designing and streamlining associations.
Associations between objects are simple to conceive and to draw, but implementing them is a potential quagmire.
we’ll focus on making distinctions among the three patterns of model elements that express the model:
ENTITIES, VALUE OBJECTS, and SERVICES.
A bidirectional association means that both objects can be understood only together.
When application requirements do not call for traversal in both directions, adding a traversal direction reduces interdependence and simplifies the design.
Understanding the domain may reveal a natural d...
This highlight has been truncated due to consecutive passage length restrictions.
Very often, deeper understanding leads to a “qualified” relationship.
Looking deeper into presidents, we realize that (except in a civil war, perhaps) a country has only one president at a time.
This qualifier reduces the multiplicity to one-to-one, and explicitly embeds an impor...
This highlight has been truncated due to consecutive passage length restrictions.
Many objects are not fundamentally defined by their attributes, but rather by a thread of continuity and identity.
Identity is not intrinsic to a thing in the world; it is a meaning superimposed because it is useful.

