Factory and Repository in the Domain

I’m a big fan of the book Domain Driven Design, and for some time I’ve been pushing the principles and patterns in my workplace. I’ve never managed to get ‘into’ the more theoretical parts of the book, and I chuckle each time one of my colleagues refers to the “contours of the domain”, however it’s up there with books that have caused a substantial shift in my thinking.

When I’m evangelising the use of Entities, Aggregates, Value Objects, and Repositories, one question that comes up regularly is “what’s the difference between a Repository and a plain old DAO?”. It’s a very good question with the right level of skepticism.

I really enjoyed reading Christian Bauer’s post “Repository Pattern vs. Transparent Persistence” – particularly the title which implies that there is a choice to be made between two approaches. In actual fact transparent persistence as implemented in Hibernate makes DDD and the use of Repositories extremely powerful. I’ll backtrack a little…

A lot of web application code that I find these days that was written with ‘best practice’ of just a few years ago follows a rough outline like this. DAO objects (or Data Mappers) provide find/save/update/delete operations methods for each object in your domain. The DAO is a basic abstraction around database persistence, often JDBC.

Business logic is usually either written directly within Transaction Scripts (recently I’ve become used to inheriting hundreds of lines of code in Struts actions… *sigh*) or within a basic Service Layer. The script or service is the only thing that can hold references to the DAOs, so of course you HAVE to put the business logic there – in most web apps there is a lot of creation and persistence of objects. No problem, we’ll just divide and conquer – from our scripts we’ll extract services, then we’ll divide our services into more services and delegate between them.

Because the application does a lot of operations requiring persistence, there’s a natural force preventing any business logic being moved to anywhere but scripts or service layers. So what are our domain object? Nothing but structures carrying data, with maybe some rudimentary logic that only affect local state. The client code asks the domain to provide it with data, and then the client code makes decisions based on that data.

The transaction script and service layer approach is simple to begin with, but as the application becomes more complex it leads to a bunch of problems, especially as developers try to avoid duplication (cut and paste is bad kiddies). Ever picked up a hierarchy of Struts actions seven layers deep with multiple Template Methods to allow overrides for different sub-classes? Bloody nightmare.

What I’ve achieved by applying the DDD patterns is the elimination of those transaction scripts and (most) services. The transaction script (e.g. struts action in a web application if you’re so inclined) is simply responsible for finding an appropriate entry-point into the domain, then telling that domain class to do some work.

The consequence is that business logic can be expressed more deeply in your domain, you are free to find the right abstractions that will allow you to make your code understandable, and to create small classes with single responsibilities.  This also means that the creation and persistence of objects will be deep in the bowels of the domain, and even better – without the calling client code or script HAVING to be aware of the object creation.  How can this be?  Domain classes aren’t allowed to hold references to DAOs – that would break our traditional view of layering.

But… when I apply DDD, Repository and Factory interfaces are part of the domain.  This is a fundamental change – that a domain object deep in an aggregate can be constructed with a reference to a Repository in order to look up persistent data.  That a domain object can also use a Factory to construct objects, hiding the detail of construction (and dependency injection).  None of this work has to be done in a transaction script or script – move that responsibility into a place in your domain where it makes sense.

Repositories can be used to perform lazy instantiation of relationships in a persistent graph of domain objects.  E.g. retrieve a PurchaseOrder from the PurchaseOrderRepository, when the PurchaseOrder requires it’s line items it asks the LineItemRepository for matching line items.  A consequence is that this will lead to a bunch of Repositories being created in a complex model.  It’s simpler (less code) if you can use a tool like Hibernate to manage persistence of the entire graph, and configure it to automatically instantiate collection relationships lazily.  Nothing about Repository prevents you from doing that – you would just eliminate the use of Repository at that point and use the collection directly.   Hibernate is no solution to fit all problems however, and we commonly find places where explicit use of a Repository is cleaner.

I also deal with a lot of ‘legacy’ code that needs to be renovated into submission – often a safe path with JDBC code is to refactor towards the use of Repositories and moving the use of those Repositories into the domain to make it more understandable.  Often the JDBC code inside the Repository implementation does not have to change much.  When it does later on, you have the opportunity to make a shift towards a technology like Hibernate.

Transparent persistence and the Hibernate Session is a really important tool for implementing a rich domain model – if we make our client code (transaction script, service) as thin as possible, it is no longer responsible for remembering which objects have been updated and saving them back to the database.  Instead we use the Hibernate Session as a Unit of Work – our client code tells the domain to go and do something and the domain can go ahead and perform calculations, validate data, and update fields as need be.  When the work is complete we tell the Session to commit and it works out what needs to be updated in the database.  Brilliant – now if we add more complexity to the domain we don’t have to add matching complexity to our client code, and not in multiple places.

Christian is very concerned with adding additional layers into our code – a Repository wrapping a DAO.  I personally do away with the DAO idea altogether – the Repository implementation is performing the same thing.  The important thing is that the Repository interface (e.g. PurchaseOrderRepository) lives in the domain, and the implementation (e.g. JdbcPurchaseOrderRepository or HibernatePurchaseOrderRepository) lives outside the domain in infrastructure.

Conclusion (otherwise I’ll go on all day):  let go of the idea that domain classes must not interact with a database (or a message queue or a file system) – free them to do their responsibility, just make sure they do so through an appropriate domain abstraction – Repository and Factory are good examples.

Oh – and stop using Struts (1.x anyway).

Mike wants a new job

Mike has posted his job requirements, as specified in a letter to recruiters. Nice idea.

If you are reading this post you probably work for a consulting company or a bank, so don’t bother offering Mike a job. If by any chance you work for a product company with an opening in your amazing team of talented and committed developers, then Mike is a seriously smart dude. Seriously.

If I didn’t work for a consulting company (geez) I’d be trying to hire him.

Australian Architecture Forum Done.

Last week I presented with some ThoughtWorks colleagues at the Australian Architecture Forum in Sydney and Melbourne. My topic was titled “No Nukes – don’t detonate your legacy software” covering approaches to incrementally replacing a legacy application. I was a bit shakey in Sydney – I’m not very comfortable with public speaking – but I felt much better about my delivery in Melbourne. All round a really great experience and I hope to do more of this kind of thing in the future. The topic definitely sparked some interesting conversations – maintaining and renovating legacy applications (sometimes not more than 18 months old…) is such a big part of what we do as an industry.

The forum itself was mostly interesting – I don’t really identify well with the title “Architect” although that is a large part of the work that I do. I find that most software architects seem to struggle to remain relevant as they get further divorced from project delivery. For this reason I found my colleague Gianny Damour’s discussion group on “The role of the architect on agile projects” most entertaining as he described architectural practices found to be questionable including “pretentious modelling”, “over technical design” and “ivory tower mentality”. It definitely sparked a healthy debate, especially the assertion that architects should code.

Much less amusing was a discussion group by the local chapter of the International Association of Software Architects that was preaching _certification_ as the answer to peer recognition of your mad architecting skillz. That and several hundred pages of an “IT architect skills library”. I think the secret architect handshake is detailed in UML 2.0 on page 259. Forgive my skepticism.

Overall though a successful forum – congratulations to the organisers!

Careful of ‘technical stories’

Just came across an old article by Jeremy Miller titled ‘Balancing Technical Improvements vs New Business Features‘ which hits on a topic close to my heart. I’ve been doing a lot of work in the last couple of years on legacy software, and there’s often a large amount of technical debt already in place when we come along. It sometimes feels like there’s too much to do – and the temptation would be to stop working on new features until we get our ‘house in order’.

I strongly believe this is the wrong thing to do – how can I tell a customer that we are deferring work that provides critical (and sometimes way overdue) business value? Smells like gold-plating to me. I’d rather have the conversation that shows we are working on business priorities, and we are taking the right amount of care and just enough technical improvement to make sure we can deliver more quickly in the future. I never want to see ‘refactoring stories’ – the team needs to agree on a technical vision and ensure each story being played takes the software a step in the right direction. It might take multiple releases to acheive a refactoring or renovation goal in it’s entirety, but that’s a worthwhile cost for staying on priority.

It’s more challenging of course. You need to maintain that vision across multiple releases, and you are carrying for a long time the baggage of the old and new ways of doing things. You’d better be sure you’ve got enough time to reach the destination, or you may have left the code in a worse state than it was before. Sometimes when the changes are in java code we can use deprecation to document areas that are ‘old’ and need to be cleaned up next time a business story takes a developer into that area.

There’s also some changes which fall into the ‘stop the line’ category. Some things slow the team down so badly that you are forced to play some technical stories. Usually these are related to automated build, automated test, or building or remediating servers and environments. These are things that are often ‘all or none’ in nature, and are very difficult to change incrementally while working on business priorities.

Our teams use a ‘story wall’ to track user stories (on filing cards) being worked on in the current iteration. We colour code the stories which have business value (blue and white on this project) and those which are just technical stories (yellow). Sometimes I look at the wall from a distance and see that there is just too much yellow, and we need to have a conversation about priorities again.

Canary Tests

Neal Ford writes about Coalmine Canary Tests. Canaries were carried by miners in the ‘olden days’ as an early warning system for a buildup of gas, giving them time to exit the mine before imminent death. Neal describes using a set of simple tests that verify basic execution of parts of your application. When changes are made the canary tests can be run first and give earlier feedback when something has gone horribly wrong.

Recently I started using the same name ‘canary tests’ for a slightly different type of test. The team I’ve been working with has inherited a large web application which is suffering badly from a couple of environmental dependencies. It has to be started up just right, with components started in the right order, and the timing just right. We’ve been doing archaeology on the system, learning it’s tricks and failure modes – however we’ve been limited in the amount of resource we can spend on finding root causes. Most of the time when the application has been deployed or started in a bad state we can find some corresponding symptom. One by one the team has collected these symptoms and built a set of ‘canary tests’ that are run prior to handing the deployed environment over to be tested. If one of those tests fails, we need to work out what had changed in the environment, and probably at least restart and check again before continuing.

The canary tests are not a solution, they just help us make sure we don’t continue working with the environment while it’s in a bad state. We are separately investigating each problem to find it’s root cause and put in place a permanent solution if possible. Some of these may take a long time to put in place, but at least the impact can be managed.

Build Hat

I like the build patterns that TWer Sam Newman has been blogging about. A recent favorite was a post titled “build fix flag” where Sam describes using a paper flag to show visually who is fixing the build. The rules according to Sam:

1. If you saw a CI build breakage, you looked for the flag
2. If someone had the flag, you left them alone
3. If you couldn’t see the flag, you tried to identify the person who made the last check in
4. If you couldn’t find a likely culprit, you raised the flag and fixed it yourself

We use a couple of TW branded USB build lights on our project to give visibility to the current build status across the floor, but with a large team there is a bit of time wasted asking ‘who broke the build? are you fixing it? who’s fixing it?’. We talked about the idea of an indicator, and this morning there appeared an large furry multi-colored wizard’s hat. Replace ‘flag‘ in the rules above with ‘funny hat‘.

I think it’s brilliant – I’m going to jump in and fix the build next time I notice it broken, just so I can wear the bloody hat!

Scared little boy. Australian Architecture Forum 2007

So I’m presenting at the AAF in Sydney June 27th, and Melbourne June 29th. The topic is about dealing with legacy software, peppered with learnings from a couple of client projects. It’s a topic I feel strongly about and an area that we’ve done some great work, so you’d think I’d be excited about being able to share my views in a breakout session at the conference.

Well I’m scared witless. I’m a software tech lead, application architect, very comfortable standing in front of a whiteboard addressing a team of familiar peers. I can be opinionated and loud, sometimes argumentative, most of the time quite comfortable. In front of a large group of strangers I’ll be quivering like a lost little boy. *sigh*

Why would I subject myself to this pain and humiliation? I want to learn how. I want to know that I gave it a go. Wish me luck…

// TODO: think of a witty and intelligent tagline