At the moment I’m reading Eric Evans’s Book “Domain-Driven Design: Tackling Complexity in the Heart of Software [published by Addison-Wesley, ISBN: 0-321-12521-5]. Although the book was written in 2004, many of his observations and motivations for DDD still ring true - little having changed in the world of object-oriented design. The book is really the first place to look if you're interested in learning DDD.
What I like - DDD (done well) is an effective way to manage and communicate a complex set of business rules. Keep it simple, use objects the way the inventors intended!
What I don't like - DDD has quite a few guiding principles, increasing the learning curve. This is not in itself a great issue, however proponents of DDD can be very dogmatic (aka anal) about how to apply the principles wrt entities, value objects, service locator patterns and so on. This drives new programmers away in droves!
I'm lucky enough to have had first hand experience of domain driven design -- back in 2005 I worked on an ASP.NET insurance project for Toyota Financial Services (an online origination system used throughout Toyota's Australian dealerships). Because the dev leads were crossing over from the Java community, many of the techniques employed (.NET 2.0 in Beta, AJAX, nHibernate, Spring.NET) were 'bleeding edge' at the time - certainly a while before ALT.NET was dreamed up. However, the simplest piece of the puzzle was indeed the domain model. It's a very natural piece of an OO puzzle, and it proved to be key to the project's success.
.NET is an object-oriented language, or did you forget?
So why is DDD not more more widely used in .NET projects? The main reason seems to be that .NET programmers become very dependent upon visual tooling. Because of this, the more esoteric aspects of object-oriented design (like design patterns, dependency injection or ORMs) are quite alien to .NET programmers. Thankfully this is something Microsoft is trying hard to put right, but you will still find experienced .NET guys routinely coupling application logic directly to underlying infrastructure, whether that be a Windows form control or a stored procedure. This is a great approach for a small project - simple always gets the best results - but the outcome is defect hell in enterprise development.
Lessons from recent projects
A few years ago I joined a banking project mid way through -- it took us twelve weeks to move the application a few centimetres -- it was plain that the complexity was killing us, because the lead devs had put all their business logic in the UI! A developer fixing one bug would introduce another, and had no means to build any tests in isolation, because the logic was all in the UI. The team leads -- the guys who had designed the f***ed architecture in the first place -- blamed the devs! I'm glad I turned up late to that party.
Twelve months later, we're now in the process of re-running a similar project for wholesale share trading. Thus far we're about to go into production, in around half the time, with one third of the defects, with a smaller team. Why? Because we applied some up-front design, rather than diving in to ad hoc development. By applying some basic principles of service architecture (like data encasulation), employing a simple domain model (objects with inbuilt behaviour, not datasets with extrinsic (repeated) behaviour) as well as techniques such as code generation to handle database persistence, we've achieved one thing: we removed complex logic from the UI and stored procedures. In other words, by architecting the application in order to put business logic in the domain objects, we get a much better end result. In fact, the difference is night and day -- let's hope they realise why!!
Thats my rant on DDD over for today... below are a few snippets of Evans' book, with my throughts attached...
“We, in the enterprise development community, especially the web development community, have been tainted by years of hype that took us away from proper object oriented software development. In the Java community, good domain modeling was lost in the hype of EJB and the container/component models of 1999-2004.”
The same can be said of .NET software, which has been ruled by the obsession with Visual Studio designer-driven drag-and-drop integration with SQL Server. Just the same way as you would expect a strong HTML coder never to touch the designer in Visual Studio (it produces the worst HTML known to mankind), you wouldn't expect someone with a knowledge of OOP to write data access code using a designer and datasets.
Until recently, Microsoft had not rushed to develop an enterprise level ORM solution – with third party ORMs filling this space. Now we have Linq to SQL and (coming soon) the ADO.NET Entity Framework (so far universally hated by the ALT.NET crowd).
"…the community is lacking a clear vision for how to apply object orientation on an enterprise scale, which is why I think DDD is important”
This is still true today, and arugably especially so of Microsoft developers, who tend to prefer data-centric (dataset driven) architectures that come out of the box in Visual Studio. It seems that nHibernate scares them, despite the fact that Hibernate has been commonplace in Java enterprise projects for some years now...
Some of my projects were very successful; a few failed. A feature common to the success was a rich domain model that evolved through iterations of design and became part of the fabric of the project."
Yes, but is an extensive domain model necessary for all applications? In some ways it's an additional complexity that one should only attempt on a large project -- where you have resources to manage it properly? Often the business wants the simplest solution that will generate positive ROI -- not something that will become a core app for the next 20 years....
What is a domain model?
A domain model is business process knowledge, captured. It results in -
- a framework for making design decisions - the building blocks of a model-driven design are best practices and shared design patterns (e.g. layered architecture, Factories, Repositories)
- a common technical vocabulary – the fundamental goal of DDD is to use the domain model to drive communication and design
Approach to design is critical
"It is the approach to design that largely determines how complex software can become"
"The most significant complexity of many applications is not technical. It is the domain itself, the activity or business of the user… a successful design must systematically deal with this central aspect of the software."
I agree that the design must address the complexities of the business domain, however in incremental development the business requirement usually isn't fully understood at the outset. Business requirements usually get more complex as the project progresses, and without the appropriate management, the code usually gets in an unreal mess :) Most ad-hoc incremental development development tries to deliver by tweak-tweak tweaking, instead of revisting the design afresh - which of course just incurs a design debt. There comes a point where the code's 'logical infrastructure' isn't capable of being extended to support the complexities of the business logic required.
"XP works best for developers with a sharp design sense"
That suggests that DDD has a talent dimension -- accordingly it's not something you should attempt to use with a team of junior developers who've not worked on a domain model project previously. All we need is well structured code with enough tests to allow it to be safely refactored or completely redesigned when the time comes - full lifecycle testing. However, the issue with this is that you need a strong programmer
"… with typical design approaches, the code and documents don't express this hard-earned knowledge in a usable form, so when the oral tradition is interrupted for any reason, the knowledge is lost."
Projects with technological debt
"Developers were flying by the seat of their pants, but this didn't hinder them because simple software can be written with little attention to design. As a result of this initial success,expectations for future development were sky high!"
Technological debt results in
-
lack of a domain model
-
Lack of a consistent, common language
-
Unstructured design
-
Poor architecture - meaning refactoring / retrospectives are impossible to attempt
We’ve all worked on new projects whose codebase has to be treated like legacy code…
"... their first release had ossified prematurely into a high maintenance legacy."
lol! How true is that!
"Early in my career, I was fortunate to end up on a project that did emphasise domain design"
"This upward trajectory was directly attributable to an incisive domain model, repeatedly refined and expressed in code"
"As the team gained new insight into the domain, the model deepened. The quality of communication improved not only among developers, but also between developers and domain experts"
When domain model fails - communication disconnects such as this are commonplace in Enterprise development:
"a poorly chosen separation of developer roles disconnected modeling from implementation, so that design did not reflect the deep analysis that was going on"
I think architecture is the main culprit – if you’re obliged to apply dataset / DTO thinking across the board, this then prevents developers from achieving any awareness of object oriented design:
Developers often have "no awareness of the informal body of style and technique for creating model based objects that also function as practical, running software."
The conclusion is simple: medium to large projects require a well thought out up-front design approach, which is ideally lightweight, as in Agile projects. You need decent devs to lay the groundwork before you try to scale out quickly - some basic architectural guidance is a must, together with ongoing mentoring in object oriented design.