Showing posts with label ddd. Show all posts
Showing posts with label ddd. Show all posts

Wednesday, 21 August 2013

There's still a need for SQL databases

Document Databases are an important part of the NoSql movement taking place. They are appealing to developers because of their intuitive Apis and also to stakeholders as they lower the boundaries to feature development that would have once been hugely difficult a Sql-only environment. Some key benefits of document databases include:

- They permit fast development of complex objects graphs, making it easy to employ DDD. Though hand-scripting stored procedures are now largely a thing of the past thanks to modern ORMs, they are difficult to retro-fit to a legacy system and can introduce new bugs of their own. I would argue that there is more confidence in storing and accessing aggregates roots in a document database as their is 'truer' representation of the model being stored on disk, while with an ORM there will always be a layer of translation.


- Are schema-less and therefore 'backwards compatible', meaning no application downtime while the database is administered. Again, ORMs have advanced enough to support deployment tasks, see Microsoft Web Deploy and RoundhousE of the Chuck Norris Dev Ops suite, but the risk still exists of losing or corrupting data with a tool or not.


- When you need to scale, document databases have been designed from the ground up to be able to distribute the data across large numbers of machines with aim of spreading system load, increasing availability and preventing failures. There is a physical limit that Sql will reach when scaling simply by throwing more resources at it (vertical scaling). Document databases deal with sharding more effectively as they don't have relationships to maintain as in a relational SQL database. There are ways in which you can scale a sql database that are not so simple.


- When you need to perform calculations over a large dataset very quickly. Document databases lend themselves to map-reduce type queries especially well because of their distributed nature. Map reduce queries are designed to be performed in parallel, which is a great fit for a shared document database. Queries are also optimized for 'eventual consistency', meaning that result accuracy is traded for low response times.


- When you need access from JavaScript. Many document databases store their data as JSON objects, so using a JavaScript client is a great way of consuming a document database service. The increase of Single Page Applications written in JavaScript and also Node Js in the back-end has encouraged the growth of JS clients. Take the Mongoose npm package for example.


In modern applications, its hard to argue that any of these requirements can be overlooked. But if you don't have a bursty traffic model and do not need a globally accessible service then you are not yet excluded from using a Sql database...


Sql databases still have a very good use. Leaving aside the fact that they remain largely a more stable platform due to there maturity compared with the relative youthful NoSql technologies, Sql databases make a great tool for data-mining. That is, to make use of the Sql JOIN operator across multiple tables to 'slice' the data. If you are working with a normalized schema, Sql queries provide the ability to draw conclusions from a body of data with more freedom than a document database. Document databases demand that you specify the kind of report you will want up front at design-time. With a Sql database, or at least a tool that provides a Sql type language interface, you can build up reports based on the relationships built into the tables.


By reporting in this context, I primarily mean the types of back end office reports that might be needed on a daily, weekly or monthly basis. These type of reports are largely back office type reports, that tend to grow as the business rules change. The type of reports I mean reveal insight and are built up further on top of existing tables and views. This type of gradual evolution is brought about by in-house report writers, who know the schema well. These reports take time to write, as well as time to run. But that time is acceptable because of the advantages that they lend the business.

In contrast, when lots of users need to see top level summaries of data quickly, a document database would be a much better tool for the job. Dashboards headline figures can be useful debugging as well as marketing tools, but they are not the type of reports that are suited to a Sql database. When website response time is important, do not put a report generated from a Sql database on the home page (hopefully we all learned this by now, right?!)

It is easy to get caught up in the momentum and success of the NoSql movement. But it can be difficult to tell what benefits it will bring to your application, and at what cost. Hopefully this article offers you a balanced view. Its fun to be an early adopter, but I would exercise caution before binning the old Sql reporting database in favour of the latest and greatest.


Sunday, 31 March 2013

Accelerating Agile

I was at QCON earlier this month. I attended plenty of excellent talks. The talk I found myself nodding in agreement most often was Dan North's Accelerating Agile. In it, he describes his experience with a firm who were capable of producing valuable software in a much shorter time frame than he had previously though possible. The overall message was that the strict Agile Methodologies he was used to practising had been replaced with bare bones Agile Manifesto reasoning and very low ceremony processes. He distilled the processes the firm exhibited down to 12 steps. I pretty much agree with each one, below I have added why I do so based on experience. Presentation slides here.


Step 1: Learn the domain
Ironically, it is the first point that I have the biggest problem with! But first, I must agree it is hugely valuable to have developers become experts in the domain that they working in. However, I think the point is largely lifted from Eric Evan's Domain Driven Design Book; specifically the Crunching Knowledge chapter. Evans, too, speaks of immersion in this sense. It is the basis for building an accurate domain model and enables the tech team to speak the same ubiquitous language as the business experts. My issue with this point is that developer time spent learning the domain should be considered 'on-the-clock'. A developer who is sat at the desk of a business expert, engaged in learning the trade is obviously not designing or coding at this moment - but they have begun the project. The clock has started. And if the point of this talk is that these steps help you produce faster, then this time spent learning (1 or 2 weeks) must be factored into that.


My second issue is that this step is not always possible on every project. Learning the trade of your domain is not also as simple as taking a short course or shadowing a colleague. I have worked on a lot of e-commerce projects in which the end user is the customer - who could be anywhere in the world. This is obviously a hurdle to getting inside the mind of those using your software! Any project in which the end user is not on in the same building will have trouble with this first step and I don't think Dan did enough to address this point.

Step 2: Prioritise risky over valuable
Dan's memorable phrasing on this step was to 'Slay the Dragon's First'. And it makes absolute sense. The traditional Agile (note the capitalisation) approach is to prioritise business value and try to deliver the simplest, and most desired functionality first. However logical this sounds, its possible to run into trouble further down the line if you do not deal with the danger zones. Making sure that you have cracked the parts of the domain which you know could jeopardise the project later is a very wise decision. This point is mirrored in George Fairbanks' book Just Enough Software Architecture; A Risk-Driven Approach. In it, he stresses the importance of evaluating Risk to inform the complexity of individual components. He argues that this should prevent an over-engineered solution, whilst Dan's point is that trying to eliminate Risk enables you to fail faster (which is good!).

Step 3: Plan as far as you need
I really like this step. As much as it appeals to my lazy side, it also supports the way we have been organising ourselves at work recently. Dan backs the idea of having only a small Kanban board and planning no more that a week ahead. This immediately gives you back all the hours spent sprint planning and storyboarding. The prescription is to plan no more than a week in advance, but crucially to review the board often. 'Often' in this context is supposed to be imprecise. Just keep the board up to date and build tacit knowledge to be able to plan smarter. From experience I absolutely agree that a small board works well because it physically won't let you plan too far ahead, nor let you get distracted. It is most effective when used as a communication tool, to serve as a snap shot of what is going on at this moment. A key piece of practical advice was that if a story/piece of work has been on the board for too long is to analyse it a break it down to smaller stories, possibly to be worked on in parallel.

Step 4: Try something different
I cannot claim to be a polyglot programmer, but I agree with the sentiment here. Having more tools at your disposal enables you to solve more problems. Dan spoke explicitly about the languages and styles that you could try out for the sake of expanding your ability to solve problems. Also at QCON, Damian Conway gave an excellent keynote: Fun with Dead Languages. The moral of the story is that learning alternative languages helps us to become better problem solvers. He makes the point that a programming language is not just a tool for repeating operations, or even just communicating ideas between developers. Conway believes that a programming language's primary purpose is to provide a way to think about a problem. If we have more ways to think we have a better chance of solving a particular problem in the best way possible. I realise that not every problem is best solved with C#. But as the .net developer I am I have difficulty slicing the problem any other way. And as such I am currently learning F#!

Step 5: Fire, Aim, Ready
This isn't especially ground breaking, its an opinion that's been around for a while in fact. But nevertheless a brilliant title that communicates the message well. Don't wait to prettify, don't hesitate to show off, don't let uncertainty stop you from demonstrating. Negative possibilities are exactly what you should seek to confirm or disprove as early as you can by getting the product out there. Dan makes the case that this all about feedback from the right people. I believe it also helps maintain the right level of communication with your stakeholders and helps bake in a success story to your project. Sharing the experience of having ideas shot down or realisations occur in cross department meetings reinforces team mentality and keeps everyone's expectations aligned.

Step 6: Build small, separate pieces
This is good practical advice mostly in the name of maintainability. The benefit of having small separate pieces is that they can be replaced easily. Mapping out the geography of your project allows you to also think more clearly about the architecture. I think we generally have to think harder about how not to build monolithic objects/solutions. Its the old argument of easy versus simple. Dan points out that the DRY principle is the enemy of Decoupled. I was uncomfortable with this idea at first but Dan went on to give clear guidelines about when to think this way: by referencing Evans' DDD he used the concept of a Bounded Context. "Let this be the limit to which you should attempt to be DRY".

Step 7: Deploy small, separate pieces
This step is largely dependent on the previous step. In my experience smaller components permit smaller, lower risk, more frequent, quicker deploys. Hopefully resulting in less down time. Dan provides lots of practical DevOps advice here. He suggests never rolling backward... If you are deploying frequently then you are only ever deploying small changes. If you are only every incrementing in small steps then you can never break something so severely that you have to roll back, just fix the code and deploy again! This requires discipline that the whole team must achieve. Dan argues the case for consistent environments and consistent deployment plans that make it easy for new starters to get to grips with and less to remember when problems in deployment arise. To help with this I have recently looked at introducing Vagrant into our development work-flow.

Step 8: Prefer simple over easy
Dan offers some specific examples in this point but the main message is clear: Simple requires thought, but in the end the result is easy to communicate. A simple idea is one that you can hold in your head. 

Step 9: Make the trade-offs
Starting off with a framework might help you get some quick wins but it might be a burden in the long run. My feeling is to always rely on third party libraries to help you get started, but to revise the position on each component where necessary.

Step 10: Share the love
This is all about communication between team members. Make it common practice to pair program and to exploit those 'Aha!' moments for the team's benefit. Dan ventures that code reviews are valuable tools. My opinion is that that they can be replaced by continuous pair programming and pull-requests, but each team is different. 'On-boarding' was a process he described to initiate new starters into the process (if any!) and technologies in play. All the steps described so far I think contribute to making this journey for a beginner as easy as possible.

Step 11: Be ok with “failure”
As I mentioned earlier Failing Fast is a Good Thing! In my experience knowing what won't work can be just as valuable as knowing what will. Dan believes we should be more concerned with Product Delivery not Project Delivery. Progress, he believes, can also be defined as a series of experiments.

Step 12: There are always 12 steps
"Delivering this fast can be addictive." My final thought is that even though it is easy to jump on the SCRUM hate wagon right now, that this is could be the opposite end of the spectrum. Let's just remember that each team and each organisation is different. And as Ward Cunningham mentioned to me after the talk: "You're an engineer aren't you? Engineer your own process!" Wise words.

Sunday, 27 January 2013

MVC projects encourage poorly organised domain namespaces

The asp.net MVC framework has been a huge breath of fresh air having usurped Webforms as the standard framework for web applications. Everyone knows the MVC pattern wasn't created by Microsoft, and the current implementation of asp.net MVC has some fundamental differences to that of the original pattern found in SmallTalk. But, it has still provided a more lightweight, transparent, extendible and testable platform to build on then Webforms ever was. And its feels so much better suited to the Web. So, regardless of how much it was influenced by Ruby on Rails, I'm grateful that Microsoft were able to bring MVC under the asp.net umbrella.

With that said, I have a small gripe with with MVC. It's a very small gripe and one that can really only be loosely attributed with it, but its the most obvious place to point the finger for this sake of this article: I think the asp.net framework encourages developers to organise domain namespaces poorly.

First, let me explain what I think a good domain namespace organisation should look like - largely learned from Domain-Driven-Design. Domain namespaces (essentially, folders in the domain project) should expose the purpose of the system. The names should closely and honestly reflect the primary concepts of the domain model. The language of the domain model should be reflected in code - this includes the namespaces the code resides in. If we are designing an application based on a domain model described by the Ubiquitous Language we have unearthed in communication between developers and business experts, then our design must share this language. A well organised namespace should allow the Business experts working on the project to look at the root of the domain and should be able to recognise the key concepts in the names of the root level folders.

In any domain, you will always need some classes as part of your design that do not come directly from the model. These classes commonly come as part of a design pattern being implemented. Their presence makes the communication of the pattern clearer, usually by encapsulating away the details, such as in the Façade Pattern. Such classes usually come with a suffix to describe their purpose, such as: Provider, Factory, Repository, Builder or Manager. It is when domain namespaces become oriented around these classes that are external to the model that organisation has failed. A domain namespace should not describe the purpose of the classes it contains. We should never end up with folders in our domain project called Providers, Factories, Repositories, Builders, or Managers because this is never what our domain is about. Yet this is exactly what MVC encourages.

Because MVC is a Framework (and not a library) it gives us handles to work it. Asp.net MVC is useful largely because it gives us answers to questions like "where do I put a new Controller?" or "where do my Scripts go?". With MVC, you know where to add new Models because there is a folder called Models. It doesn't matter that those (view) models may relate to completely distinct concepts, they can still exist in the same folder - and they're only view models anyway, right? They don't tie directly to the domain model, they're just there to make the presentation layer work.

Right. However, the problem is that I see developers make the mistake of following this convention in the domain project. The model is ignored and folders are created to categorise a sub collection of classes that all happen to be "Factories" or other such classes external to the model. The domain project then fails to be decipherable to a business expert and no longer describes itself with the Ubiquitous Language.

Presumably developers do this because Microsoft gave us the template MVC project as is and because its just easier to put that new Factory in the Factory folder with the others. It'll be easy to find later. But there-in lies the danger: If we are not forced to think hard about how to arrange the namespace then we risk designing something that is not true to the model. If we have to think before we add a class, it makes the choice to add a new class tougher. We will only then be able to authorise the creation of classes that have an appropriate place in the namespace of our domain - keeping the design as close to the model as possible. If we unearth a purpose for a class that doesn't appear in the model (and also isn't an artefact of a design pattern) then we must revisit our model and communicate the idea with our business experts and incorporate the idea in the Ubiquitous Language.

In defence of MVC, it couldn't really work any other way. MVC is a presentation framework - its not supposed to be a domain framework (if there is such a thing?). It has license to organise the way that suits this purpose. It is the developer's responsibility to organise that the domain suits its purpose (according to the model). Just because MVC has a layout that groups together its classes by their purpose, does not mean any other project should. The real issue is to make sure that developers are in tune with the domain and to ensure that it is exposed in the design, and not use the MVC framework as a guiding tool for how to do that.

Even inside the domain, perhaps a layer or two in from the root, there is a place for arranging classes that are external to the model together. If the development team is comfortable that nested inside folders (named according to the model) that it is appropriate to name a folder 'Factories' - then so be it. But I would expect to find such folders a rarity. (Just how many Factories would really be needed in one corner of the domain?).

But maybe there is something to learn from MVC in how we organise the domain? With MVC3 came the concept of Areas. The goal of an area is to provide logical Url Routing and help organise the presentation layer classes and assets according to the routing rules. If you have a number of Areas in your MVC3 project, then the Areas folder starts to look like a well organised domain. All the root folders will speak in terms of the domain model, while sub folders will house Models, Views & Controllers and be named as such. So, if there is anything MVC can do to encourage better domain namespace organisation, it is to include Areas in all template MVC projects.

Thursday, 8 November 2012

DDD Notes Part III

Part III Refactoring Toward Deeper Insight

8 - Breakthrough

- Breakthroughs cannot be forced, the usually occur after many modest refactorings.
- Concentrate on knowledge crunching and cultivating robust Ubiquitous Language.
- Watch for opportunities to gain deeper insight and do not hesitate to make even minor improvements.
- Breakthroughs can lead to a cascade of more breakthroughs.


9 - Making Implicit Concepts Explicit

- Developers need to sensitize to the hints revealing implicit concepts and sometimes search them out.
- Listen to the language the domain experts use. It is a warning when the experts use vocabulary that is not present in the design.
- Watch for puzzled expressions on domain experts faces when you mention particular phrases.
- When the missing concept is not on the surface of conversations with domain experts, try digging around the most awkward part of the design - i.e. the place that is hardest to explain.
- Actively engage domain experts in the search, play with ideas or use them for validation.
- Usually contradictions from opposing domain experts can reveal deeper insight to the domain.
- Business books on the domain are a great source of information when the domain expert is not available.
- Explicit Constraints, such as invariants, should be extracted in the design so that their intention is more obvious by using descriptive method names within the object.
- Constraints do not belong in the object if they require data that doesn't fit in the object's definition. Or if requirements conversation revolves around the constraint but they are hidden in procedural code within the object.
- The Specification Pattern provides a way of expressing conditional rules explicitly in the model (predicates) whilst keeping the logic in the domain layer.
- Specifications determine if an object satisfies a condition, the logic having probably been extracted from an attribute of the property.
- Specifications work well with repositories by specifying criteria to select against, esp with ORMs.
- Specs defined in terms of interfaces decouple designs and help clear logjams by using prototypes.


10 - Supple Design

- Relieve the client from having to know about the implementation by using Intention Revealing Interfaces.
- Describe purpose and effect but not how it is achieved and always with Ubiquitous language.
- Functions do not affect the state of an object and are therefore 'side-effect-free'.
- Function should be able to be called repeatedly and deeply nested. Functions are predictable and safe.
- Commands cause change of state and should be kept separate from queries (CQRS). Commands should not return domain data - leave that to functions.
- Where possible, return Value Objects from functions so you don't have to maintain its life-cycle. Furthermore, all Value Object operations should be functions as they are immutable and have no state.
- Move complex queries into Value Objects to reduce side effects.
- Make invariant conditions explicit by unit testing and making assertions.
- Search for meaningful units of functionality to make designs flexible and easier to understand.
- Use your intuition about the domain to decompose design elements (classes/aggregates) into cohesive units.
- Changes are more easily applied to Conceptual Contours and they are easier to combine and reuse.
- Standalone classes with zero dependencies other than primitives are easier to understand and reduces mental overload by having extremely low coupling.
- Every dependency is suspect until proven to be fundamental to the concept of the object.
- Prioritise the most complex computations into standalone classes (value objects?) and allow other classes to depend on them.
- Operations who's argument and return value are of the same type are said to be closed under the set of instances of that type. Closed operations do not introduce further dependencies.
- Closed Operations can operate under abstract types.
- Declarative design can be burdened by frameworks and DSLs. Use only lightweight plugins that solve a particular mundane problem well and that leave you to design more accurately.
- The specification pattern can be very useful for declarative design because individual specifications can be combined and chained to produce meaningful sentences using Ubiquitous Language.
- When trying to achieve Supple Design start with identifiable subdomains (conceptual contours?) and tackle problems step by step. It is better to make a big impact on one area, making some part of the design supple, rather than to spread efforts thinly.
- Draw on established formalisms of the domain when you can.


11 - Applying Analysis Patterns

- Analysis Patterns are not technical solutions but guides to help you work out the model.
- Analysis patterns can carry tried and tested experience of implementation and maintenance from a mature project and bring model insights, direction & discussion.
- Analysis Patterns provide cleanly abstracted vocabulary.
- Development can be stimulated by using analysis patterns and results often resemble adapted the form adapted to the circumstances, but sometimes can inspire the development in other directions.
- It is wise not to adjust the basic concept of an analysis pattern so as to keep the well understand terms and phrases consistent in your project. If model definitions change then keep class/method names up to date.
- Analysis patterns focus on the most critical decisions and offer choices. They anticipate downstream consequences that are expensive to discover yourself.


12 - Relating Design Patterns to the Model

- Design patterns present design elements that have solved problems before in purely technical terms. They can be applied to the model because they correspond to general objects that emerge in domains.
- The conventional focus of the strategy pattern focuses on substituting different algorithms. However, its use as a domain pattern focuses on its ability to express a process or policy rule as a concept.
- When a technical design pattern is used in the model we need another motivational layer of meaning to correlate actual business strategy to make the pattern more than just a useful implementation technique.
- A consequence of the strategy pattern is that it can increase the number of objects in the design and requires clients to be aware of the different strategies. This can be mitigated by implementing strategies as stateless objects that are contexts can share.
- The Composite pattern offers the same behaviour at every structural level of an inheritance hierarchy.
- The Flyweight pattern has no correspondence to the domain model, its only value is at the design level when implementing value objects. The Composite pattern differs as it is for conceptual objects composed of conceptual objects of the same type.
- This is what makes Composite pattern a domain, as the pattern applies to both model and implementation.


13 - Refactoring Toward Deeper Insight

- Is a multifaceted process: Live in the Domain > Keep looking at things differently > Maintain an unbroken dialogue with Domain experts.
- Seeking insight into the domain creates a broader context for the process of refactoring.
- Refactoring can begin in many ways - usually as a result of some awkward realisation or difficulty implementing a reasonable requirement, divergence of language, or any source of dissatisfaction.
- Exploration teams can be tasked with thinking about how to improve the model. These teams need to be self organised and small in members meeting for short frequent periods. The meetings should be spaced out over a few days to allow time to digest the new model. Brainstorming sessions should always exercise the Ubiquitous language. The end result is a refinement of the language to be formalised in code.
- Knowledge should be sought from other sources in the domain to gain insight. It is always possible that the domain has already got well defined concepts and useful abstractions.
- Refactoring toward deeper insight both leads to and benefits from a supple design. A supple design communicates it intent and limit mental overload by reducing dependencies and side effects and being fine grained only where it is most critical to users.
- Continuous refactoring has to be considered a best practice and part of the ongoing exploration of subject matter, education of developers and meeting of minds of developers and domain experts. Take any opportunity to refactor that benefits the integrity of the design and consolidates the teams's understanding. 
- Development suddenly comes to the brink of a breakthrough and plunges through to a deep model-then again begins a phase of steady refinement.


Tuesday, 2 October 2012

DDD Notes Part I & Part II

Part I - Putting the Domain Model to Work


1 - Crunching Knowledge

- Communication with Domain Experts is mandatory to accumulate domain knowledge.
- Initial conversations should revolve around an emerging language based on the model.
- Experimenting with different ideas about the model is important.
- Layers of feedback erode the details of the model, only business people and developers needed.
- Learning has to be continuous as the business changes and domain evolves.


2 - Communication and the Use of Language

- Domain experts and developers need to speak the same language.
- The language of the model should be reflected in the code.
- Using the language will force model weaknesses into the open and reveal gaps to be - plugged.
- Model should be the backbone of the ubiquitous language, change in change means change in model.
- If experts don't understand the model there is something wrong with the model.
- Diagrams are useful but should be temporary and serve only communicate the present.
- Documents are useful if they add to the model.


3 - Binding Model and Implementation

- Model driven design removes the separation of analysis models and design models by having a single model that fits both purposes and makes for a very relevant model.
- If a model does not faithfully express key domain concepts, a new model is needed.
- The model must support the ubiquitous language and start with the domain reflected in code in a very literal way that can be improved as deeper insight is gained. This way the code becomes an expression of the model.
- OOP is a great paradigm for expressing models as it inherently supports objects as opposed to procedural languages.
- It is usually a good idea not to try to hide the inner workings of the system from the user as it prevents the user understanding the model, which is usual of benefit to the user as they can reason about it and make predictions.
- The people involved in modelling need also to be taking part in crafting the code. There are subtle relationships in code carry important information about the model that are difficult to communicate verbally.


Part II - The Building Blocks of a Model-Driven Design


4 - Isolating the Domain

- A layered architecture is the most appropriate when trying to employ DDD.
- The Domain layer is where the model lives.
- A separate domain layer allows a model to evolve to be rich and clear enough to capture business knowledge.
- Keeping it separate from infrastructure or UI concerns is imperative.
- Smart UI designs can be practical but are not sustainable long-term.


5 - A Model Expressed in Software

- Entities require an identity so they can be uniquely referenced throughout their lifetime.
- Entity class definitions should be should be kept focussed on the lifestyle continuity and identity i.e. properties that make the class findable with intrinsic characteristics.
- Add behaviour to entities that is essential to the concept, move non essential attributes into other objects associated with the core entity.
- Value objects have no identity as it is not important to tell them apart.
- Objects without identities are more transient and can allow for better system performance without the burden of being identifiable. Applying identities where not needed also confuses the design.
- In value objects we only care about the attributes of the class and they should always be immutable - the value object should be replaced rather than manipulated, e.g. address.
- Value objects can be shared where it is acceptable in the model and of benefit to system resources but is difficult in distributed systems. Shared value objects must never be mutable.
- Services represent valid ways of capturing behaviour that do not belong to an object.
- It is easy to create a service and not apply to an object when it should be in an object but forcing behaviour into an object in which it doesn't belong can distort the model.
- Service operations should be part of the ubiquitous language.
- Services are stateless and have interfaces defined in terms of other domain elements e.g. a bank transfer service deals with other domain elements - money (value) & accounts (entities).
- Modules should be treated as fully fledged parts of the domain and organise objects.
- Code divided into modules means being divided into logical domain concepts. This helps coherent thinking about few topics at once and helps to reason about the system as a whole in terms of its modules.
- Modules should act as a communication mechanism and support the ubiquitous language by reflecting insight into the domain.
- Mixing paradigms should only be considered when all other options for using the primary paradigm for the module in question have been exhausted.
- One way to ease the friction on heterogeneous models is to use the same language in all paradigms.
- Paradigms that do not allow expressive representation of the domain with ubiquitous language should not be used.
Slowly learning that the struggle should always be to use the tools in the best possible way to fit the model, not to adjust model problems so that they are easily solved with our tools.
What happens when domain experts do not know the model well enough to answer deeper questions of things the business hasn't decided yet? 

6 - The Life Cycle of a Domain Object

- Invariants are ways to maintain business rules within an Aggregate
- An aggregate is a cluster of associated objects that we treat as a unit for the purposes of data changes.
- An aggregate route is the one entity (of possibly many) in the aggregate that other entities outside the aggregate can hold reference to. 
- That means the other entities inside the aggregate only need identifiers distinguishable inside the aggregate, as nothing outside can access them.
- Aggregates are the only thing in the aggregate that can be accessed directly from the database. A delete operation must remove everything within the boundary.
- Invariants (consistency rules) involve relationships between members of the aggregate and must be enforced by persisting the aggregate as a whole.
- Decouple elements to keep clean distinctions between things inside and outside the aggregate boundary.
- Factories remove the need for object clients to know the inner workings of the client.
- They are not intrinsically part of the model but they are a reasoned necessity of the design.
- A factory should be an atomic operation that creates a valid entire aggregate for an entity with all invariants satisfied.
- Factories can over complicate a simple design but the threshold for choosing a factory method is short.
- Factory parameters should be from a lower design layer or basic objects and abstract types.
- Objects don't need to carry around logic that will never be applied in its active lifetime - so the factory can be a good place host the responsibility of enforcing invariants (especially if they are immutable).
- Factories are also suitable for reconstituting inactive objects, ie loading from the db.
- Infrastructure makes it easy to traverse dbs but developers have to try to keep the model in tact.
- Use a repositories to provide access to aggregates routes. Only ever traverse via the route to access objects internal to the aggregate.
- Repositories help maintain focus on the model by emulating an in-memory collection of all entities of a type.
- Repositories decouple domain design from persistence technology (facade) and allow for easy substitution.
- The specification pattern helps complex querying whilst maintaining the model.
- Keep mappings between objects and tables simple when designing relational dbs by compromising normalisation in favour of tight coupling between model and implementation.


7 - Using the Language: An Extended Example

- An Anti Corruption layer can protect external systems that are not based on the same domain model from bleeding into your design.
- Enterprise Segments can be useful value objects for the design to allow communication between modules and preserve the ubiquitous language.
- The application layer should orchestrate the different elements of the domain but should not contain any business logic.
Should repositories be placed in a data access layer or do they belong inside the conceptual modules along with the entities they are for? 
Could (or perhaps, should) there be an object oriented language or framework with these concepts of entities, values, aggregates, factories, repositories, anti-corruption layers as first class elements? We would lose precision but we would have a platform that is built for DDD?