Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

 

Table of Contents
maxLevel2

...

Chapter 3 Binding Model and Implementation and Chapter 4 Isolating the Domain

Quotes

“Software development is all design. All teams have specialized roles for members, but over separation of responsibility for analysis, modeling, design, and programming interferes with MODEL-DRIVEN DESIGN.”

Example: “A user of Internet Explorer thinks of 'Favorites' as a list of names of Web sites that persist from session to session. But the implementation treats a Favorite as a file containing a URL, and whose filename is put in the Favorites list.”

“If the people who write the code do not feel responsible for the model, or don’t understand how to make the model work for an application, then the model has nothing to do with the software.”

“Every developer must be involved in some level of discussion about the model and have contact with domain experts.”

Discussion

Expand
  • How would this apply to a functional programming language (author examines procedural and logical paradigms, but not FP)?
    • Artifact of when it was written?
    • Would probably work fine.
    • Not as layered.
    • Examples in JS of functional composition (e.g. React).
    • Django's MVC setup actually makes it harder.
      • Not a place for a lot of domain logic (e.g. utils.py)
      • One strategy: Separate layer to proxy lower level models.
      • Another strategy: Service pattern, service encapsulates business logic.
      • Example of what's talked in the book about frameworks dictating a lot of the design.
      • Grades app does have classes to encapsulate domain, but have to go without using niceties like DRF serializers.
      • Question: Are some of the tools that make it easy to write code making it harder to separate out domain logic?
        • Do we need a layer of our own/special tooling to enable this?
  • Analogs between the Smart UI pattern and Django's "Smart Model" and its conveniences.
    • Django optimizing for building it fast? Easy to leak implementation.
    • Useful middle ground?
    • Enterprise API – package that's installed, but API calls are via REST API as if it were a separate system.
      • Business logic encapsulated in models.
    • How to handle internal Python APIs?
      • Best practice to not pass back models?
      • api.py is the public interface between Django apps (though we're not sure if we want to continue using it)
      • Pass back the model but only allow certain methods to be called?
      • Write business logic as functional modules and use the model methods just as a proxy to that?
    • What is the problem we're solving?
      • Enrollment example
      • Separating domain logic from underlying details
      • Simplifying testing
  • Question: Difference between Application Layer and Domain Layer?
    • Application layer manages jobs and tasks and lifecycle of the application. Very thin.
    • Layer for orchestration.
    • No business logic, just knowing who to call.
    • Initialization of the application, setup, teardown.
    • Django "best practice" as view, but this is often not followed.
      • Need to have a clear location for business logic.
    • In async tasks (grades example), is the thing that kicks off task the app layer and the task itself the domain layer?
      • tasks.py is the Django interface
      • domain logic is in the classes: CourseGrade, CourseGradeFactory, SubsectionGrade, and SubsectionGradeFactory
    • Where does app end and domain begin?
      • Where the framework ends and you create domain layer concepts and return domain layer concepts.
  • Question: Are permissions domain logic or app?
    • The notion of "readable by superusers" (app) vs. domain concept of who should be a superuser?
    • Attached to the View in our code.
    • Mapping of of roles to permissions, permissions to views in Django.
    • Permission a Guard on the view, and therefore a separate Domain?
    • Are permissions for what can be done in a Domain a separate Domain?
    • Implementation of permission is app, where to attach it is Domain.
      • Combination, since there's a lot of permission checking in the domain itself.
    • Artifact of the fact that it's a web app, because the conceptual Domain wouldn't even allow certain methods to be invoked? Different objects for different kinds of people?
    • Purer form of this might be to just pass permissions down to the domain layer and let it make the decisions.
    • When will we know that we've outgrown Django?
      • Many of the things we run into are fundamental to the framework.
      • Gradually outgrow it by pieces (asset pipeline, templates, etc.)
    • Django not strictly object oriented, applying separation of concerns without adhering too strictly to DDD?
      • In the end, it's just Python, we can shape it as we need to.
        • Easy to do in a small team, harder to do at large.
          • Especially at open source.
    • Workflow as business logic, app layer just doing I/O, piping to the next thing.
  • Monolith and Folder Structure: Anyone interested in figuring this out, contact Nimisha Asthagiri (Deactivated)
    • First a template, then a script to generate that structure (manage.py – startapp at a specific URL already supported?)
  • Layers and directionality of layers
    • We should think about separation of communication and not just arrangement of app.
    • "You are talking to way too many places in the code."
      • Compositional components
    • Are we missing anything by having Django apps that cross all four layers?
      • Just a matter of discipline, would be confusing to separate out
      • Cross dependencies without directionality
      • Each Django app as its own Context
        • But part of a higher level tiering (different apps at different layers)
        • Middleware as an example of an app layer concern
          • But can be part of an app that spans all layers, e.g. language preference middleware that also has UI for users and model layer, etc.
            • How does this work for extraction, say pulling language related logic into a separate service?
            • App as glue, so app can get the language preference and pass it to the next thing that cares about language.
            • Common anti-pattern: Passing the request object instead of the things you need from it.
            • Service pattern, letting the Domain query from a service as it's needed.
            • Should we need to pass it down through the layers? Should things near the bottom need to know how to access services?
            • Pass in the service you need to use (for in-process services) to make testing easier
            • Don't like to pass the same parameters over and over again
            • Not opposed to passing the model (User instead of say six fields on the user)
              • If you're always sending the same parameters together, it's probably its own model
              • Difference between passing around simple structure vs. smart object that can make queries
              • Be transparent whether a call is a blocking call to an external service
        • Tracking and analytics are infrastructure layers

...

  • 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.
  • 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.
  • 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.
  • Like all powerful ideas, REFLECTION and KNOWLEDGE LEVELS can be intoxicating. This pattern should be used sparingly.

Pluggable Component Framework

...

Chapter 17. Bringing the Strategy Together

Quotes

...

  • ..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.

...

  • A large- scale structure can exist within one BOUNDED CONTEXT, or it can cut across many of them and organize the CONTEXT MAP.
  • When you are tackling strategic design on a project, you need to start from a clear assessment of the current situation.

    1. Draw a CONTEXT MAP. Can you draw a consistent one, or are there ambiguous situations?

    2. Attend to the use of language on the project. Is there a UBIQUI- TOUS LANGUAGE? Is it rich enough to help development?

    3. Understand what is important. Is the CORE DOMAIN identified? Is there a DOMAIN VISION STATEMENT? Can you write one?

    4. Does the technology of the project work for or against a MODEL- DRIVEN DESIGN?

    5. Do the developers on the team have the necessary technical skills?

    6. Are the developers knowledgeable about the domain? Are they interested in the domain?

  • An architecture team can act as a peer with various application teams, helping to coordinate and harmonize their large-scale structures as well as BOUNDED CONTEXT boundaries and other cross-team technical issues. To be useful in this, they must have a mind set that emphasizes application development.
  • Six essential for strategic decision making
    • Decisions must reach the entire team.
    • The decision process must absorb feedback.
    • The plan must allow for evolution.
    • Architecture/infrastructure teams must not siphon off all the best and brightest.
    • Strategic design requires minimalism and humility.
    • Objects are specialists; developers are generalists.
  • Technical frameworks can greatly accelerate application development, including the domain layer, by providing an infrastructure layer that frees the application from implementing basic services, and by helping to isolate the domain from other concerns. But there is a risk that an architecture can interfere with expressive implementations of the domain model and easy change. Evolution, minimalism, and involvement with the application development team can lead to a continuously refined set of services and rules that genuinely help application development without getting in the way.
  • Don’t write frameworks for dummies.

  • Advocate a set of principles for all community members to apply to every act of piecemeal growth, so that “organic order” emerges, well adapted to circumstances.

Discussion

Expand
  • This last diagram should have been presented in the beginning of the book.
    • from his perspective, he may have wanted the reader to first understand all the terminology beforehand.
  • The Assessment First section is good about how to get started
  • Architecture handed down doesn't usually work
  • Don't put all your senior engineers on the platform team
    • partly because of interests of people on the team
  • Don't have a top-down ivory-tower approach 
  • The books seems to taper off.
  • The epilogue has a bunch of war stories - with further perspective on the models he used from earlier in the book.
  • Would we ever get to the point of getting to the details (e.g., value objects versus entities, repositories, etc)?
  • We started with the django framework → overtime, we've migrated several things into our custom implementation (e.g., asset-handling, distributed config)
    • Vistaprint started in a framework, then replaced with a custom framework, then needed to replatform again to get back into the framework.
      • Probably need a hybrid - going either all framework or all custom is too extreme
  •  Don’t write frameworks for dummies.
    • Some DSLs do this.
    • Even xBlocks may be guilty of this.
  • Level of refactoring effort may depend on the maturity of the company.
    • Per the 20/80 rule, our focus on refactoring only needs to be within the segregated core part of the codebase
    • He also talks about how multiple refactorings lead to more suppleness in the code - so future refactorings would be easier.
    • But what about if the company pivots?  Then their core may change.

...