Podcast: Play in new window | Download
Subscribe: Apple Podcasts | Spotify | TuneIn | RSS
Stitcher is back and so are we as Michael proves he doesn’t have a career as a rapper, Allen can’t type on his phone, and Joe tweets with famous authors as we continue our dive into Domain Driven Design talking about aggregate roots, factories, and repositories.
Having a difficult time reading these show notes via your podcast player? Stop by https://www.codingblocks.net/episode61 to read the full show notes.
Sponsors
- FreshBooks.com/Coding – Use code “CODING BLOCKS” in the “How Did You Hear About Us?” section
- GetAirbrake.com/cb
- Linode – Use code “CODINGBLOCKS17” for $20 towards hosting (that’s up to four months free!)
How about you join our Slack Community Already?
Join us and the incredible Coding Blocks community by going to https://www.codingblocks.net/slack to become a part of the community.
Survey
In this episode, we talk about the term “invariant” as it relates to all things programming, and we ask: Did you know what invariant meant?
News
- We love the reviews and appreciate you taking the time to write them! Big thanks to these awesome people.
- iTunes reviews: Colter Cotten, Conservative Programmer, RWCheese, Shahn H, CCKessler, MarvTheRobot, Alex111132
- Stitcher reviews: Rippe, AdamWhitehurst, AllenIsClearlyTheBest, OnlyBavarianBeerIsBeer, clegg89, denifia, GodsShortbus, dubstylee, The Eye of Brows, Edgar da Bunny
- Azeteg submitted the coolest app to Apple’s App Store: Turbine Dr – Check the operating condition of air-driven turbine-style dental hand tools using _just_ your iPhone’s microphone.
- Joe tweets Eric Evans. Eric Evans tweeted back.
I think open source projects usually focus more narrowly
— Eric Evans (@ericevans0) May 26, 2017
- Allen is able to type on his phone again thanks to Gboard! (available on Google Play and Apple App Store)
- Joe tweets Stephen King. Suddenly, rabid dogs and clowns are circling his house.
.@StephenKing New book/movie idea for the modern era. Cursed #iphone that subtlety manipulates the text messages for #evil!
— CodingBlocks.net (@CodingBlocks) June 10, 2017
- Allen hints at an update to his laptop reviews.
- They’re totally capable of playing a great game of Who’s Your Daddy (Steam)
- Samsung’s new monitor makes your puny monitor look insignificant. (The Verge, Business Insider, Samsung) Available at Amazon.
Coding Blocks Stuff
Want some Coding Blocks stuff? Learn more at https://www.codingblocks.net/swag.
Lifecycle of Complex Relationships in Domain Driven Design
Invariants
- All constants are invariant, but not all invariants are constant
- Will always be true at the beginning or end of an iteration
- Binary tree left node always be greater than any child – Stack Overflow answer.
- As listed in Domain Driven Design – Chapter 6. pg 128, 1st paragraph “Invariants are consistency rules that must be maintained whenever data changes”
Aggregates and Aggregate Roots
Aggregate Root – the entry point of an aggregate – where the work should be done – that ensures the integrity of the object graph
Aggregate – Cluster of associated objects that we treat as a unit for the purpose of data changes – the graph of objects
- Objects within an aggregate boundary can reference each other, but not outside the boundary
- Aggregate roots can reference each other, but not objects not within their boundaries
- Entities within the aggregate are not accessible outside the boundaries of that aggregate
- Example of Car as an Aggregate Root…it has tires, a wheel, etc.
- Car has an identity – think of the VIN – but the tires probably only need to be identified as their position on the car – no external identifier
- Engines also have unique identifiers, and MIGHT be needed as an aggregate root in some domains, but probably just a part of the car boundary in others
- Aggregate Root (Entity Root) – global identity and responsible for checking invariants
- Entities inside the root boundary have only local identities and can only be referenced within the aggregate.
- The root can pass along a reference from an external entity and hand it down to it’s own entities to be used, but only transiently – they cannot maintain a handle to that external entity
- Only aggregate roots can be obtained directly with database queries
- Objects within an aggregate MAY contain references to other aggregate roots
- Deleting within an aggregate should remove all data at once
- When data inside the aggregate boundary changes – all invariants on the aggregate must be satisfied
- Strive to cluster the entities and value objects into aggregates and define the boundaries for each.
- After you’ve done this, choose one of the aggregates to be your Aggregate Root
- Purchase orders problem…
- Many people working on the same PO or many people working on many PO’s referencing items being sold
- What if part information such as prices change? Lock the parts? Deadlocks
- What if more than one person is working on a PO at a time? Do you lock it?
- Many people working on the same PO or many people working on many PO’s referencing items being sold
The Business Approach
- Parts are used in many PO’s (high contention)
- There are fewer changes to parts than there are to POs
- Changes to part prices do not necessarily update the POs…depends on when the price changed in relation to the status of the PO
- The PO becomes your aggregate root, your line items are entities within the boundary, and the Items themselves are an external aggregate root.
- Now the PO is responsible for ensuring the invariants / consistency of the data, and locks can be controlled at the PO level
- Factories and Repositories encapsulate the complexity of some of those life cycle state changes
Factories
- When creating objects or aggregates becomes complicated or revealing – Factory time!
- “Much of the power of objects rests in the intricate configuration of their internals and their associations. An object should be distilled until nothing remains that does not relate to it’s meaning or support its role in interactions. This mid-life cycle responsibility is plenty.
- Overlap w/ SOLID and Design Principles
- In order to create complex objects/aggregates, factories have to know some of the rules about invariants and the business logic…ew
- Keep that knowledge together in one place, in factories – which have no real meaning to the domain model, but are still part of our design
- 2 criteria for good factory (including factory methods, like on classes)
- ALWAYS return an object in a consistent state (atomic and enforce all invariants)
- Abstract to the TYPE desired, not the class
- But..where do we put our factory?
- Factory method on the aggregate root?
- Factory method on a similar spawner? (Example of creating a Trade Account over a Brokerage Account)
- Factory class / Depdency Injection (interesting this is the 3rd)
- Constructor….? But #2…Things you should consider
- Maybe the class is the type, polymorphism / hierarchy doesn’t matter
- Maybe the client cares (because that’s who is doing it) cares (like strategy pattern)
- Are any attrbutes hidden from the client?
- Is construction simple?
- Can we assure all invariants are safe?
- Designing factories
- Each operation must be atomic – pass everything up front!
- The factory will be coupled to it’s arguments – so be careful w/ complexity! Stick to abstract/lower levels
- But what about invariants? Duplicate the logic? Move the logic into the factory? Have the factory delegate it to the product!
- What about reconstituting stored objects? (deserialization)
- Do NOT assign a new tracking ID
- What do you do about invariant failures? Repair it..maybe?
- What about reconstituting stored objects? (deserialization)
Repositories
- Represents all objects of a certain type as a conceptual set, that acts like a collection, except with more elaborate querying capability
- Repositories focus on persistence
- Keep the client focused on the model
- Retrieves the requested object, encapsulating the machinery to query and map the data
- Implements a common interface, i.e. the basic CRUD operations
- Multiple repositories for each type but not necessary each class
- Using an abstract or base class for example.
- Repositories may offer many ways to query for a type
- Use of a Specification-based query improves the flexibility
Benefits
- Allows the client to “talk in intention-revealing” language (Clean Code?) promoting design decisions
- Promotes Separation of Concerns
- Enables testability – i.e. repositories could return dummy objects
Repositories vs Factories
- Factories create new objects
- Repositories find/object objects
- Repositories can use factories to create objects
- Factories do not deal with persistence
- Repositories do deal with persistence
Resources We Like
- Domain-Driven Design Fundamentals by Julie Lerman and Steve Smith (available at Pluralsight)
- Modern Software Architecture: Domain Models, CQRS, and Event Sourcing by Dino Esposito (available at Pluralsight)
- Domain Driven Design – Tackling Complexity in the Heart of Software by Eric Evans (available at Amazon)
- http://DDDCommunity.org
- http://DomainLanguage.com
Tip of the Week
- SonarQube – an open-source static analysis tool that is easy to plug into your pipeline for continuous code quality.
- Chrome’s DevTools now provide multiple breakpoints for the same line. See this Stack Overflow answer for an example.
- LinuxKit – A toolkit for building secure, portable, and lean operating systems for containers Code available on GitHub, read the writeup at Docker.
- Use the –depth switch to get a shallow clone of a Git repository (docs)
- git clone –depth 1 …
Sharing is Caring
Want to help Coding Blocks? Share. Just tell a friend about the show. That’s all we ask.
Well, that and a review. /8) Go to https://www.codingblocks.net/review to leave us a review that puts a smile on our faces.