[TSE] The Art of Domain Modeling
Now at the beginning of the afternoon it's Keith Donald's second talk about Domain Driven Design at The Spring Experience.
Effective modeling is about creating a knowledge rich model with everything relevant to the problem being solved. In order to achieve this one has to develop a common language so that everybody involved has a chance to stay on the same page. It's about brainstorming and experimenting using tools such as unit tests and the IDE. The idea is to write code very early, but for the time being leave questions of the infrastructure out.
Domain experts and developers need to work together. Only I believe that most domain experts don't have the time to follow that approach. So in the end it will be about showing a simplistic prototype to them. Something that appears to be working, although underneath there is no functionality that can really be put into production. I see a few questions here.
Once you understand enough of the domain problem, write some code. Focus on behavior, avoid all infrastructure. Then get some feedback from users. Again I see some questions here. The idea is certainly a good one, but will the users accept being shown something that is purely a simulation? Some non-technical people tend to expect real working software dealing with real data at an early stage. So here will be certainly some need to explain things to them.
[TSE] The Building Blocks of Domain Driven Design
Keith Donald's talk at The Spring Experience has started. Right now he's summarizing what Eric told us before.
A domain model does not capture every aspect of the real world. Instead it's a simplistic view of the world to serve a purpose. Discoveries during the implementation feed back into the model design.
Isolate the domain by using a layered architecture. Do not mix UI, database, external services and business objects all together. The very same isolation allows unit testing and Spring helps in the wiring of the units.
Keith shows a diagram with the user interface on top of the application and the application on top of the domain and everything on top of the infrastructure. The application layer delegates tasks to the domain layer for complex solutions.
The domain layer represents business rules and states.
The infrastructure layer interacts with the database, constructs UI widgets and deal with everything technical.
The domain layer is to isolate the domain objects from other functions in the system to avoid mixing technical and domain concepts. One should bind the model the implementation early. Implement the behavior of the application within the domain model classes without thinking about the technical infrastructure. The resulting artifact is a unit test.
In the beginning map domain entities literally to Java objects. Some of these mappings may be wrong in the end and you will need to refactor, but it's a start. Then start writing unit tests using those classes. Keith is now showing actual code of unit tests for his reward dining example.
Organize domain behaviors into coarse-grain, high-level user operations. Make user operations part of the application layer. Unit tests in the domain layer are a good place to look for application layer use-cases. The application layer encapsulates complex domain layer objects and rules and allows for freedom in the implementation. After defining the boundaries of the application layer focus on streamlining the domain model implementation.
Streamline associations between model objects. If you don't understand why an association is needed, avoid it. Association create coupling, which is generally to be avoided. Impose a traversal direction on associations.
Entities, value objects and services. Often entities are persisted to a database. Entities maintain their identity that never changes. Entities may be used by other applications and need to be tracked. They have a life cycle and the model needs to define what it means to be the same thing. String entity objects down to the most intrinsic characteristics and only add required behavior and attributes needed for that behavior. For everything else add associated objects.
Value objects are identified by their attributes and often they are interchangeable and transient. Value objects can be shared and are good candidates for immutability. They reduce bugs by avoiding invariants.
Services are activities or actions, not a thing. A service is something that makes it happen and is stateless. Services should be thin coordinators and one should resist the urge to develop fat services that attempt to solve the problem all on their own. Look for natural opportunities to encapsulate behavior in services that doesn't make sense within Entities or Value Objects. The main responsibility of a service is to orchestrate things, to coordinate. It delegates to entities to do the work.
The creation of Entities should be done using factories and repositories that restore an entity object from a persistent form. Services control and coordinate the life cycle of entities.
Someone asked whether a repository isn't a service. Keith answers is that a repository is a DAO service, but with a very simple job. It doesn't coordinate work and therefore it wouldn't be justified to call it a service.
Make sure that your factories and repositories return fully initialized objects to their callers.
[TSE] Domain Driven Design
I'm sitting in Eric Evans' talk "Introduction to Domain Driven Design" at The Spring Experience. The first question he is asking is whether your problem really is a technical problem. Technical people tend to see everything as a technical problem and seek technical solutions to solve it.
Understanding the problem domain better is key he is saying. I agree, but let's see how DDD can help with that.
Be careful not to mix your opinion or perception into the creation of your model. Be precise in your model. Avoid shortcuts and don't assume that details are already well-known.
Probably even very small projects will use multiple data models to help in the implementation of the solution. Objects created to deal with one model should not be taken out of context. This raises the need to convert information between the models.
Eric goes on saying that one should not try to come up with a big, every encompassing enterprise domain model, but instead a model for each part of the system. Frequently great object designs get modified so many times that in the end the original architecture will not be there anymore. It seems he proposes to isolate concerns, create the best model for a well defined part of the system and then find a way to interface those parts with each other.
Interesting: modeling does not drive an upfront design phase. In fact it would be wrong, because at the beginning of a project the team is ignorant about the problem domain. Trying to come up with a model at that stage will create the wrong thing.
Not tools like visual programming, UML diagrams and so on help to raise the needed level of abstraction. Instead proper use of language as the primary abstraction tool is important. Eric's favorite modeling tools are: whiteboard, IDE, unit tests to explore the model itself and, again, our mouths and ears.