The DomainModel system exists to help support and encourage domain model and behaviour driven design and development in Python.
A very useful series of distinctions has emerged from the mass of experiences developing software to support working processes, and we have (albeit retrospectively) taken them as the stated purpose of DomainModel.
The implementation of DomainModel follows Martin Fowler's magnificent Patterns of Enterprise Application Architecture. It was created entirely by refactoring from real Python applications.
Purpose of the Product
The desire within domain driven design is that when we develop software to support a working process, at the heart of the development activity we want to code directly for the objects and the logic of the supported process.
Following the 'ubiquitous language' for domain modeling set out by Eric Evans in his marvelous Domain Driven Design, we are able to identify the following core stories (expanded below).
- Isolate a domain layer
- Express domain model in software
- Establish life cycle of domain object
- Partition domain into bounded contexts
- Determine co-operation between contexts
- Make each bounded context approachable
- Intensify and refine the model
- extract generic sub-domains
- extract cohesive mechanisms
- Introduce elements of larger scale structure
The resulting generic sub-domains (such as role based access control) and the extracted cohesive mechanisms (such as domain data migration, object access controller, model plugin extension) demonstrate the value of an isolated domain model layer.
Isolate a Domain Layer
We want our domain model to inhabit a layered architecture, with user interfaces and other clients above, and with a persistence layer below.
We want to isolate the model.
Object Relational Mapper Independence
We want to code directly for the objects and the logic of the supported process in the language of the supported domain, rather than perhaps in the language of mapping software objects to relational database tables.
Ultimately, of course, it's turtles all the way down. :-) At least from the standpoint of the model of a domain, it shouldn't make much difference what the expression of that model rests upon (we use third party ORMs).
Presentation Interface Independence
An interface provides access to the resource it presents. The resource is shared by all the interfaces which present it.
Therefore, we want to code directly for the objects and the logic of the supported process, and separate these concerns from any interface. In other words, we want to separate support for the working process from support for interacting with such support.
Dependence on Development Process
There's always a process, however it's constituted.
And there are ways of developing support for working processes other than by carefully following the supported domain. But the agile and domain driven approaches appear to be the most common, in that their names seem to circulate most.
Therefore, we want to code for the logic and in the language of the supported domain, and we want to layer this over the common language of agile and domain driven development.
Express Domain Model in Software
Modules, entities, value objects, services.
Establish Life Cycle of Domain Object
Aggregates, factories, repositories.
Partition Domain into Bounded Contexts
Bounded context, continuous integration, context map.
Determine Co-operation Between Contexts
Shared kernel, customer/supplier development, conformist, anti-corruption layer, separate ways.
Make Each Bounded Context Approachable
Open service, published language.
Intensify and Refine the Model
Core domain, domain vision statement, highlighted core, cohesive mechanisms, declarative style, segregated core, abstract core, generic sub-domains.
Introduce Elements of Larger Scale Structure
Responsibility layers, knowledge level, pluggable component framework.
Note on Migration of Domain Data
There are different ways of migrating domain data when upgrading application services, but it seems that unless the new version of the application is installed afresh with domain data migrated on the level of the domain model, changes in the database schema will be impossible to code for across the variations of persistence mode.
Also, frequently we want to migrate production data to an acceptance testing service without ever disturbing the production service. And we want to prepare and check the new production service without taking down the old.
Therefore, we wanted in some manner to stream the application domain model from service to service, and to initialize newly deployed services with migrated domain data whilst leaving existing services untouched.
This seems to be the best defense against accumulating errors from an indefinite series of raw database update scripts operating on the same production database, regardless of whether or not they have been backed up first.
Scope of the Work
The work of developing a domain model includes the following stories.
- Name a domain
- Name a domain context
- Name a shared kernel
- Name a domain entity
- Name a domain entity attribute
- Name a value object
- Name a domain service
- Identify an aggregation
- Site a factory
- Name a repository
- Name a service
- Publish language
- Record value propositions
- Extract core model
- Highlight core model
- Extract cohesive mechanism
- Extract abstract core
- Extract generic sub-domain
- Express model in declarative style
- Introduce responsibility layer
- Introduce knowledge level
- Introduce pluggable component framework
Scope of the System
The DomainModel system currently provides features which satisfy the following requirements.
- The system shall have a layer base class for all domain objects.
- The system shall have a base class for domain entity objects.
- The system shall have a base class for domain value objects.
- The system shall have a set of classes for expressing domain value object attributes.
- The system shall have a class for expressing value object attributes of a domain object.
- The system shall have a class for expressing domain entity association attributes of a domain object.
- The system shall have a set of classes for expressing aggregation of domain objects.
- The system shall provide a cohesive mechanism for creating running software objects from domain object model declarations.
- The system shall provide a cohesive mechanism for plugging in domain object model extensions.
- The system shall provide a cohesive mechanism for meta mapping domain objects into a persistence layer.
- The system shall provide a dictionary-like interface for direct domain entity object access.
- The system shall provide a generic access control sub-domain model.
- The system shall provide a generic user session sub-domain model
- The system shall provide a generic person sub-domain model.
- The system shall provide a cohesive mechanism for meta mapping domain objects into a presentation layer.
- The system shall provide a cohesive mechanism for command line interface presentation.
- The system shall provide a cohesive mechanism for Web interface presentation.
- The system shall provide a cohesive mechanism for domain data migration (loading, dumping, transforming).