Flatten your architecture: Simplicity as a core value

time to read 3 min | 588 words

Originally posted at 2/17/2011

In a recent codebase, I had to go through the following steps to understand how a piece of data in the database got to the screen:

  • Visit Presenter needs to show the most recent visit
    • It calls VisitationService
      • It calls PatientsService
        • It called PatientDataProvider
          • It calls Repository<Patient>
            • It uses NHibernate
      • It called VisitDataProvider
        • It calls Repository<Visit>
          • It uses NHibernate

All of that in order to just grab some data, but you won’t really get the grasp of why this is bad until you realize that you need to change something in the way you load stuff from the database.

A common example (where I usually comes in) is when you have a performance problem and need to optimize the way you access the database.

The problem with this type of architecture is that it looks good. You have good separation, and there are usually tests for it, and it matches every rule in the SOLID rule book. Except, that it is horrible to actually try to make changes in such a system. Oh, you can easily try to replace the way you handle patients, for example, because that has an interface and you can switch that.

But the problem that I usually run into in those projects it that the things that I want to change aren’t along the axis of expected change, and the architecture is usually working directly against my ability to make a meaningful modification.

Guys, we aren’t talking about rocket science here, we are talking about loading some crap from the database. And for the most part, the way I like to see is:

  • Visit Presenter needs to show the most recent visit
    • It uses NHibernate

Basically, we want to make it so that reading from the database has as few frills as possible, because it is taking too much effort otherwise.

Writing is usually when we have to apply things like validation, business logic, rules and behaviors. Put that in a service and run with that, but for reads? Reads should be simple, and close to where they are needed, otherwise you are opening yourself to a world of trouble.

Oh, I just realized that I am describing something quite similar to the CQRS model, although I think that I got to it from a different angle.