What is domain driven design?

    The best way to do it is to make software a reflection of the domain. Software needs
    to incorporate the core concepts and elements of the domain, and to precisely realize
    the relations between them. Sofeware has to model the domain.
    Somebody without knowledge of banking should be able to learn a lot just buy reading
    the code in a domain model. This is essential. Software which does not have its
    roots planted deep into the the domain will not react well to change over time.
    We need to create an abstraction of the domain. It is a <b>domain model</b>. It
    is not a particular diagram, it is the <b>idea</b> that the diagram is intended
    to convey. It is not just the knowledge in a domain expert's head, It is a rigorously
    organized and selective abstraction of that knowledge. It can be in the form a diagram
    , carefully written code or just english sentence.
    A specific domain could be more than a human can handle at one time. We need to
    orgainze information, to systematize, to divid it up in smaller pieces, to group
    those pieces into logical modules, and take one at a time and deal with it.
    A model is the essence of the software, but need to create ways to express it, to
    communicate it with others. We need to cummunicate the model. There are different
    ways to do that. One is graphical: diagrams, use cases, drawings, pictures, etc.
    Another is writing. We write down our vision about the domain. Another is language.
    We can and we should create a language to communicate specific issues about the
    domain. <b>The right way to design software is domain driven design. It combines design
        and development practice, and shows how design and development can work together
        to create a better solution. Good design will accelerate the development, while
        feed back coming from the development process will enhance the design.</b>
    You and the domain experts need to exchanging knowledge. You start asking questions,
    and they respond. While do do that, they dig essential concepts out of the domain.
    Those concepts may come out unpolished and disorganized, but nonetheless they are
    essential for understanding the domain. You need to learn as much as possible about
    the domain from the experts. And by putting the right questions, and processing
    the information in the right way, you and the experts will start to sketch a view
    of the domain, a domain model. This view is neither complete nor correct, but it
    is the start you need. Try to figure out the essential concepts of the domain. This
    is an important part of the design. Usually there are long discussions between software
    architects or developers and the domain experts. The software specialists want to
    extract knowledge from the domain experts, and they also have to transform it into
    a useful form. At some point, they might want to create an early prototype to see
    how it works so far. While doing that they may find some issues with their model,
    or their approach, and may want to change the model. The communication is not only
    one way, from the domain experts to the software architect and further to the developers.
    There is also feedback, which helps create a better model, and a clearer and more
    correct understanding of the domain. Domain experts know their area of expertise
    well, but they organize and use their knowledge in a specific way, which is not
    always the best to be implemented into a software system. The analytical mind of
    the software designer helps unearth some of the key concepts of the domain during
    discussions with domain experts, and also help construct a structure for future
    discussions as we will see in the next chapter. We, the software specialists (software
    architects and developers) and the domain experts, are creating the model of the
    domain together, and the model is the place where those two areas of expertise meet.
    This might seem like a very time consuming process, and it is, but this is how it
    should be, because in the end the software’s purpose is to solve business problems
    in a real life domain, so it has to blend perfectly with the domain.
    Model Driven Design</h1>
    After we create a great model, we need to implement the model in code, propertyly
    transfer it into code. Any domain can be expressed with many models, and any model
    can be expressed in various ways in code. For each particular problem there can
    be more than one solution. Which one do we choose? Having one analytically correct
    model does not mean the model can be directly expressed in code. Or maybe its implementation
    will break some software design principles, which is not advisable. It is important
    to choose a model which can be easily and accurately put into code. The basic question
    here is: how do we approach the transition from model to code?
    The disconnection between model and code design</h2>
    It happens that software analysts work with business domain experts for months,
    discover the fundamental elements of the domain, emphasize the relationshipbs between
    them, and create a correct model, which accurately captures the domain. Then the
    model is passed on to the software developers. The developers might look at the
    model and discover that some of the concepts or relationships found in it cannot
    be properly expressed in code. So they use the model as the original source of inspiration,
    but they create their own design which borrows some of the ideas from the model,
    and adds some of their own. The development process continues further, and more
    classes are added to the code, expanding the divide between the original model and
    the final implementation. The good end result is not assured. Good developers might
    pull together a product which works, but will it stand the trials of time? Will
    it be easily extendable? Will it be easily maintainable?
    Any domain can be expressed with many models, and any model can be expressed in
    various ways in code. For each particular problem there can be more than one solution.
    Which one do we choose? Having one analytically correct model does not mean the
    model can be directly expressed in code. Or maybe its implementation will break
    some software design principles, which is not advisable. It is important to choose
    a model which can be easily and accurately put into code. The basic question here
    is: how do we approach the transition from model to code?
    One of the recommended design techniques is the so called analysis model, which
    is seen as separate from code design and is usually done by different people. The
    analysis model is the result of business domain analysis, resulting in a model which
    has no consideration for the software used for implementation. Such a model is used
    to understand the domain. A certain level of knowledge is built, and the model resulting
    may be analytically correct. Software is not taken into account at this stage because
    it is considered to be a confusing factor. This model reaches the developers which
    are supposed to do the design. Since the model was not built with design principles
    in mind, it probably won’t serve that purpose well. The developers will have to
    adapt it, or to create a separate design. And there is no longer a mapping between
    the model and the code. The result is that analysis models are soon abandoned after
    coding starts.
    One of the main issues with this approach is that analysts cannot foresee some of
    the defects in their model, and all the intricacies of the domain. The analysts
    may have gone into too much detail with some of the components of the model, and
    have not detailed enough others. Very important details are discovered during the
    design and implementation process. A model that is truthful to the domain could
    turn out to have serious problems with object persistence, or unacceptable performance
    behavior. Developers will be forced to make some decisions on their own, and will
    make design changes in order to solve a real problem which was not considered when
    the model was created. They create a design that slips away from the model, making
    it less relevant.
    If the analysts work independently, they will eventually create a model. When this
    model is passed to the designers, some of the analysts’ knowledge about the domain
    and the model is lost. While the model might be expressed in diagrams and writing,
    chances are the designers won’t grasp the entire meaning of the model, or the relationships
    between some objects, or their behavior. There are details in a model which are
    not easily expressed in a diagram, and may not be fully presented even in writing.
    The developers will have a hard time figuring them out. In some cases they will
    make some assumptions about the intended behavior, and it is possible for them to
    make the wrong ones, resulting in incorrect functioning of the program.
    Analysts have their own closed meetings where many things are discussed about the
    domain, and there is a lot of knowledge sharing. They create a model which is supposed
    to contain all that information in a condensed form, and the developers have to
    assimilate all of it by reading the documents given to them. It would be much more
    productive if the developers could join the analyst meetings and have thus attain
    a clear and complete view of the domain and the model before they start designing
    the code.
    Connect model and code design</h2>
    A better approach is to closely relate domain modeling and design. The model should
    be constructed with an eye open to the software and design considerations. Developers
    should be included in the modeling process. The main idea is to choose a model which
    can be appropriately expressed in software, so that the design process is straightforward
    and based on the model. Tightly relating the code to an underlying model gives the
    code meaning and makes the model relevant.
    Getting the developers involved provides feedback. It makes sure that the model
    can be implemented in software. If something is wrong, it is identified at an early
    stage, and the problem can be easily corrected.
    Those who write the code should know the model very well, and should feel responsible
    for its integrity. They should realize that a change to the code implies a change
    to the model; otherwise they will refactor the code to the point where it no longer
    expresses the original model. If the analyst is separated from the implementation
    process, he will soon lose his concern about the limitations introduced by development.
    The result is a model which is not practical.
    Any technical person contributing to the model must spend some time touching the
    code, whatever primary role he or she plays on the project. Anyone responsible for
    changing code must learn to express a model through the code. Every developer must
    be involved in some level of discussion about the model and have contact with domain
    experts. Those who contribute in different ways must consciously engage those who
    touch the code in a dynamic exchange of model ideas through the Ubiquitous Language.</p>
    If the design, or some central part of it, does not map to the domain model, that
    model is of little value, and the correctness of the software is suspect. At the
    same time, complex mappings between models and design functions are difficult to
    understand and, in practice, impossible to maintain as the design changes. A deadly
    divide opens between analysis and design so that insight gained in each of those
    activities does not feed into the other.
    Design a portion of the software system to reflect the domain model in a very literal
    way, so that mapping is obvious. Revisit the model and modify it to be implemented
    more naturally software, even as you seek to make it reflect deeper insight in the
    domain. Demand a single model that serves both purpose well, in addition to supporting
    a fluent Ubiquitous Language.
    Draw from the model the terminology used in the design and the basic assignment
    of responsibilities. The code becomes an expression of the model, so a change to
    the code may be a change to the model. Its effect must ripple through the rest of
    the project’s activities accordingly.
    To tightly tie the implementation to a model usually requires software development
    tools and languages that support a modeling paradigm, such as object-oriented programming.
    The building blocks of a model driven design</h2>
    When we create a software application, a large part of the application is not directly
    related to the domain, but it is part of the infrastructure or serves the software
    itself. It is possible and ok for the domain part of an application to be quite
    small compared to the rest, since a typical application contains a lot of code related
    to database access, file or network access, user interfaces, etc.
    In an object-oriented program, UI, database, and other support code often gets written
    directly into the business objects. Additional business logic is embedded in the
    behavior of UI widgets and database scripts. This some times happens because it
    is the easiest way to make things work quickly.
    However, when domain-related code is mixed with the other layers, it becomes extremely
    difficult to see and think about. Superficial changes to the UI can actually change
    business logic. To change a business rule may require meticulous tracing of UI code,
    database code, or other program elements. Implementing coherent, model-driven objects
    becomes impractical. Automated testing is awkward. With all the technologies and
    logic involved in each activity, a program must be kept very simple or it becomes
    impossible to understand.
    Therefore, partition a complex program into LAYERS. Develop a design within each
    LAYER that is cohesive and that depends only on the layers below. Follow standard
    architectural patterns to provide loose coupling to the layers above. Concentrate
    all the code related to the domain model in one layer and isolate it from the user
    interface, application, and infrastructure code. The domain objects, free of the
    responsibility of displaying themselves, storing themselves, managing application
    tasks, and so forth, can be focused on expressing the domain model. This allows
    a model to evolve to be rich enough and clear enough to capture essential business
    knowledge and put it to work.
            User Interface (Presentation Layer)</p>
            Responsible for presenting information to the user and interpreting user commands.
            Application Layer
            This is a thin layer which coordinates the application activity. It does not contain
            business logic. It does not hold the state of the business objects, but it can hold
            the state of an application task progress.
            Domain Layer
            This layer contains information about the domain. This is the heart of the business
            software. The state of business objects is held here. Persistence of the business
            objects and possibly their state is delegated to the infrastructure layer.
            Infrastructure Layer
            This layer acts as a supporting library for all the other layers. It provides communication
            between layers, implements persistence for business objects, contains supporting
            libraries for the user interface layer, etc.
    It is important to divide an application in separate layers, and establish rules
    of interactions between the layers. If the code is not clearly separated into layers,
    it will soon become so entangled that it becomes very difficult to manage changes.
    One simple change in one section of the code may have unexpected and undesirable
    results in other sections. The domain layer should be focused on core domain issues.
    It should not be involved in infrastructure activities. The UI should neither be
    tightly connected to the business logic, nor to the tasks which normally belong
    to the infrastructure layer. An application layer is necessary in many cases. There
    has to be a manager over the business logic which supervises and coordinates the
    overall activity of the application.
    There is a category of objects which seem to have an identity, which remains the
    same throughout the states of the software. For these objects it is not the attributes
    which matter, but a thread of continuity and identity, which spans the life of a
    system and can extend beyond it. Such objects are called Entities</p>
    Therefore, implementing entities in software means creating identity. For a person
    it can be a combination of attributes: name, date of birth, place of birth, name
    of parents, current address. The Social Security number is also used in US to create
    identity. For a bank account the account number seems to be enough for its identity.
    Usually the identity is either an attribute of the object, a combination of attributes,
    an attribute specially created to preserve and express identity, or even a behavior.
    It is important for two objects with different identities to be to be easily distinguished
    by the system, and two objects with the same identity to be considered the same
    by the system. If that condition is not met, then the entire system can become corrupted.
    Value Objects
    We may be tempted to make all objects entities. Entities can be tracked. But tracking
    and creating identity comes with a cost. We need to make sure that each instance
    has its unique identity, and tracking identity is not very simple</p>
    If we don't need to keep track of an object, then it is value objects.</p>
    A value object can be immutable or mutable. But it is highly recommended that value
    objects be immutable. They are created with a constructor, and never modified during
    their life time.When you want a different value for the object, you simply create
    another one. This has important consequences for the design. Being immutable, and
    having no identity, Value Objects can be shared. That can be imperative for some
    designs. Immutable objects are sharable with important performance implications.
    They also manifest integrity, i.e. data integrity. Imagine what it would mean to
    share an object which is not immutable. An air travel booking system could create
    objects for each flight. One of the attributes could be the flight code. One client
    books a flight for a certain destination. Another client wants to book the same
    flight. The system chooses to reuse the object which holds the flight code, because
    it is about the same flight. In the meantime, the client changes his mind, and chooses
    to take a different flight. The system changes the flight code because this is not
    immutable. The result is that the flight code of the first client changes too.
    One golden rule is: if Value Objects are shareable, they should be immutable. Value
    Objects should be kept thin and simple. When a Value Object is needed by another
    party, it can be simply passed by value, or a copy of it can be created and given.
    Making a copy of a Value Object is simple, and usually without any consequences.
    If there is no identity, you can make as many copies as you wish, and destroy all
    of them when necessary.
    A Service should not replace the operation which normally belongs on domain objects.
    We should not create a Service for every operation needed. But when such an operation
    stands out as an important concept in the domain, a Service should be created for
    it. There are three characteristics of a Service:
    <li>The operation performed by the Service refers to a domain concept which does not
        naturally belong to an Entity or Value Object. </li>
    <li>The operation performed refers to other objects in the domain. </li>
    <li>The operation is stateless. </li>
    When a significant process or transformation in the domain is not a natural responsibility
    of an Entity or Value Object, add an operation to the model as a standalone interface
    declared as a Service. Define the interface in terms of the language of the model
    and make sure the operation name is part of the Ubiquitous Language. Make the Service
    While using Services, is important to keep the domain layer isolated. It is easy
    to get confused between services which belong to the domain layer, and those belonging
    to the infrastructure. There can also be services in the application layer which
    adds a supplementary level of complexity. Those services are even more difficult
    to separate from their counterparts residing in the domain layer. While working
    on the model and during the design phase, we need to make sure that the domain level
    remains isolated from the other levels.
    Both application and domain Services are usually built on top of domain Entities
    and Values providing required functionality directly related to those objects. Deciding
    the layer a Service belongs to is difficult. If the operation performed conceptually
    belongs to the application layer, then the Service should be placed there. If the
    operation is about domain objects, and is strictly related to the domain, serving
    a domain need, then it should belong to the domain layer.