Friday, August 28, 2020

Domain Driven Design Chapter 16 Summary

 Chapter 16: Large-Scale Structure

    • "In a large system without any overarching principle that allows elements to be interpreted in terms of their role in patterns that span the whole design, developers cannot see the forest for the trees. We need to be able to understand the role of an individual part in the whole without delving into the details of the whole."
    • "A “large-scale structure” is a language that lets you discuss and understand the system in broad strokes."
    • "Devise a pattern of rules or roles and relationships that will span the entire system and that allows some understanding of each part’s place in the whole—even without detailed knowledge of the part’s responsibility."
  • Evolving Order
    • "Design free-for-alls produce systems no one can make sense of as a whole, and they are very difficult to maintain. But architectures can straitjacket a project with up-front design assumptions and take too much power away from the developers/designers of particular parts of the application. Soon, developers will dumb down the application to fit the structure, or they will subvert it and have no structure at all, bringing back the problems of uncoordinated development."
    • "Let this conceptual large-scale structure evolve with the application, possibly changing to a completely different type of structure along the way. Don’t overconstrain the detailed design and model decisions that must be made with detailed knowledge."
    • "Large-scale structure should be applied when a structure can be found that greatly clarifies the system without forcing unnatural constraints on model development. Because an ill-fitting structure is worse than none, it is best not to shoot for comprehensiveness, but rather to find a minimal set that solves the problems that have emerged. Less is more. "
  • System Metaphor
    • "Software designs tend to be very abstract and hard to grasp. Developers and users alike need tangible ways to understand the system and share a view of the system as a whole."
    • "When a concrete analogy to the system emerges that captures the imagination of team members and seems to lead thinking in a useful direction, adopt it as a large-scale structure. Organize the design around this metaphor and absorb it into the ubiquitous language. The system metaphor should both facilitate communication about the system and guide development of it. This increases consistency in different parts of the system, potentially even across different bounded contexts. But because all metaphors are inexact, continually reexamine the metaphor for overextension or inaptness, and be ready to drop it if it gets in the way."
    • The "Naive Metaphor" and Why We Don't Need It
      • "Because a useful metaphor doesn’t present itself on most projects, some in the XP community have come to talk of the naive metaphor, by which they mean the domain model itself.

        One trouble with this term is that a mature domain model is anything but naive. In fact, “payroll processing is like an assembly line” is likely a much more naive view than a model that is the product of many iterations of knowledge crunching with domain experts, and that has been proven by being tightly woven into the implementation of a working application.

        The term naive metaphor should be retired."
  • Responsibility Layers
    • "When each individual object has handcrafted responsibilities, there are no guidelines, no uniformity, and no ability to handle large swaths of the domain together. To give coherence to a large model, it is useful to impose some structure on the assignment of those responsibilities."
    • "Look at the conceptual dependencies in your model and the varying rates and sources of change of different parts of your domain. If you identify natural strata in the domain, cast them as broad abstract responsibilities. These responsibilities should tell a story of the high-level purpose and design of your system. Refactor the model so that the responsibilities of each domain object, aggregate, and module fit neatly within the responsibility of one layer."
    • Choosing Appropriate Layers
      • "As layers get switched out, merged, split, and redefined, here are some useful characteristics to look for and preserve."
        • "Storytelling. The layers should communicate the basic realities or priorities of the domain. Choosing a large-scale structure is less a technical decision than a business modeling decision. The layers should bring out the priorities of the business."
        • "Conceptual dependency. The concepts in the “upper” layers should have meaning against the backdrop of the “lower” layers, while the lower-layer concepts should be meaningful standing alone."
        • "Conceptual contours. If the objects of different layers should have different rates of change or different sources of change, the layer accommodates the shearing between them."
  • Knowledge Level
    • "[A knowledge level is] a group of objects that describes how another group of objects should behave. [Martin Fowler, “Accountability,” www.martinfowler.com]"
    • "Knowledge level untangles things when we need to let some part of the model itself be plastic in the user’s hands yet constrained by a broader set of rules. It addresses requirements for software with configurable behavior, in which the roles and relationships among entities must be changed at installation or even at runtime."
    • "In an application in which the roles and relationships between ENTITIES vary in different situations, complexity can explode. Neither fully general models nor highly customized ones serve the users’ needs. Objects end up with references to other types to cover a variety of cases, or with attributes that are used in different ways in different situations. Classes that have the same data and behavior may multiply just to accommodate different assembly rules."
    • "Create a distinct set of objects that can be used to describe and constrain the structure and behavior of the basic model. Keep these concerns separate as two “levels,” one very concrete, the other reflecting rules and knowledge that a user or superuser is able to customize. "
  • Pluggable Component Framework
    • "When a variety of applications have to interoperate, all based on the same abstractions but designed independently, translations between multiple bounded contexts limit integration. A shared kernel is not feasible for teams that do not work closely together. Duplication and fragmentation raise costs of development and installation, and interoperability becomes very difficult."
    • "Distill an abstract core of interfaces and interactions and create a framework that allows diverse implementations of those interfaces to be freely substituted. Likewise, allow any application to use those components, so long as it operates strictly through the interfaces of the abstract core."
  • How Restrictive Should a Structure Be?
    • "The large-scale structure patterns discussed in this chapter range from the very loose system metaphor to the restrictive pluggable component framework. Other structures are possible, of course, and even within a general structural pattern, there is a lot of choice about how restrictive to make the rules."
    • "A more restrictive structure increases uniformity, making the design easier to interpret. If the structure fits, the rules are likely to push developers toward good designs. Disparate pieces are likely to fit together better."
    • "On the other hand, the restrictions may take away flexibility that developers need. Very particular communication paths might be impractical to apply across bounded contexts, especially in different implementation technologies, in a heterogeneous system."
    • "The most important contribution of the large-scale structure is conceptual coherence, and giving insight into the domain. Each structural rule should make development easier."
  • Refactoring Toward a Fitting Structure
    • "A team committed to evolving order must fearlessly rethink the large-scale structure throughout the project life cycle. The team should not saddle itself with a structure conceived of early on, when no one understood the domain or the requirements very well."
    • "Unfortunately, that evolution means that your final structure will not be available at the start, and that means that you will have to refactor to impose it as you go along. This can be expensive and difficult, but it is necessary. There are some general ways of controlling the cost and maximizing the gain."
    • Minimalism
      • "One key to keeping the cost down is to keep the structure simple and lightweight. Don’t attempt to be comprehensive. Just address the most serious concerns and leave the rest to be handled on a case-by-case basis."
    • Communication and Self-Discipline
      • "The entire team must follow the structure in new development and refactoring. To do this, the structure must be understood by the entire team. The terminology and relationships must enter the ubiquitous language."
    • Restructuring Yields Supple Design
      • "[A]ny change to the structure may lead to a lot of refactoring. The structure is evolving as system complexity increases and understanding deepens. Each time the structure changes, the entire system has to be changed to adhere to the new order. Obviously that is a lot of work."
      • "This isn’t quite as bad as it sounds. I’ve observed that a design with a large-scale structure is usually much easier to transform than one without. This seems to be true even when changing from one kind of structure to another, say from metaphor to layers."
      • "So it seems to be with models that are transformed repeatedly with sound transformations. Ever-increasing knowledge is embedded into them and the principal axes of change have been identified and made flexible, while stable aspects have been simplified. The broader conceptual contours of the underlying domain are emerging in the model structure."
    • Distillation Lightens the Load
      • "Another crucial force that should be applied to the model is continuous distillation. This reduces the difficulty of changing the structure in various ways. First, by removing mechanisms, generic subdomains, and other support structure from the core domain, there may simply be less to restructure."
      • "The principles of distillation and refactoring toward deeper insight apply even to the large-scale structure itself. For example, the layers may initially be chosen based on a superficial understanding of the domain; they are gradually replaced with deeper abstractions that express the fundamental responsibilities of the system. This sharp-edged clarity lets people see deep into the design, which is the goal. It is also part of the means, as it makes manipulation of the system on a large scale easier and safer."