I’m in the process of rewriting a .NET application in Node.js. The .NET application has been implemented using Domain Driven Design (DDD), so there’s an AggregateRoot and a bunch of Commands and Handlers, which are referencing a common internal Domain package, which in turn references NEventStore. It’s kind of hard to tell what the effective outcome of hitting an Action on a Controller is, because whatever it is, it’s handled somewhere in the depths of all the abstraction and plug-ins. The thousands of lines of code in the current implementation just kind of indirectly cause this to happen in some vague, near-impenetrable way.
Now, I’m not an expert on DDD. I have never built a big, enterprisey application using this methodology. The idea of Bounded Contexts and a Ubiquitous Language certainly sound useful in that type of Software Development At Scale, with multiple teams working on various aspects of a single solution. I can certainly appreciate the value of an Event Store, and Command Query Responsibility Segregation is a sensible evolution of the Single Responsibility Principle (the S in SOLID). In an application with a high volume of constantly-changing data, having separate back-end processes and different storage engines for applying changes versus retrieving or reporting on data makes very good sense.
So why am I moaning about DDD on Twitter?
Because the application in question is a tiny, standalone part of an analytics service. It’s got one significant controller, with one significant action. All it does is insert records in a Mongo database, and add messages to a RabbitMQ queue. That’s it. It is not a complex system that is going to evolve in complex ways over time: I can tell this from the commit history in the GitHub repo, where the "last commit" times are displayed in years. It is write-only; there is no read functionality. There is no Ubiquitous Language. There are no Bounded Contexts. None of the libraries are shared with other applications across the enterprise.
The entire process flow is:
- Hit a URL.
- Record added to MongoDB collection.
- Message sent to RabbitMQ.
- 200 OK.
It is, in fact, a microservice. I like microservices. I’m refactoring quite a lot of code into microservices (by moving discrete chunks out of macroservices). There is a lot to be said for microservices. One of the things to be said for microservices is that, by breaking a huge, monolithic application up into lots of small, self-contained services, you avoid the need for most of the really complicated patterns and practices that are so helpful when huge, monolithic applications, like Bounded Contexts and Aggregate Roots and Commands and Handlers. A microservice is a Bounded Context and a Command and a Handler. So within that highly-focused, small codebase, you can abandon all the trappings and abstractions and Packaged Concrete Implementations of Abstract Concepts beloved of the Enterprise Monolith and get on with writing some Very Simple Code that Just Does One Thing (or maybe two).