[This is the second episode in my CQRS Overview Series - Series Contents]
First, some full disclosure. I started my career developing applications using Microsoft Access and VBA with SQL Server backend databases (yes, I know! but please keep reading, we all had to start somewhere...). Such a stack (if this can even be called a "stack") naturally led to a completely data-centric approach to writing applications. Object orientation wasn't even a distant thought in the mind of this business school graduate. My world consisted of presenting data entry screens to users, possibly validating or manipulating the data, shoving the data into a table, and then reporting on the data. Views and Stored Procedures were great ways to aggregate, filter, and slice and dice data. Data, data, data. You get the idea. (Side note - I had clients who loved the fact that they could just directly manipulate data in tables, bypassing all constraints, logic, validation, etc. Just imagine how hard it is to extend and maintain, let alone troubleshoot and debug such a system!).
"Neo, the matrix has you!"
Since I had never learned object oriented design principles, I was unaware of other approaches. But like Neo in the Matrix, at some point I sensed a splinter in my mind, driving me mad. One of my first interesting realizations came about when I noticed that many rules and processes of the business did not exist anywhere in the data-centric software. Instead, someone just had to know the process, or a document was created describing the process. Rather than building such logic into the application, a data centric application seemed to lend itself to leaving gaping holes, left to be patched by super human feats of memory ("remind me, how do I do this again?"), copious amounts of ever-stale documentation ("is this standard operating procedure up to date?"), or just plain dumb luck. Or things would just break and programmers could blame the users and call it a "data" problem ("the software isn't bad, it's a data entry problem. Bad user!").
When the .NET framework was released in 2002, I jumped on that bandwagon and also began learning object oriented practices. However, it proved hard to break the data-centric habit and it continued in force for a time. This was due to many factors, not the least of which being Microsoft's propensity to use this approach in many of their code samples and help documentation. For those who didn't know any better, the assumption was that the Microsoft way must be the "right" way. After all, they created the framework and the tools, so their code samples must represent the correct way to do things, right?
Wrong. In so many ways, wrong. Rather than talking about all the ways this is wrong, I want to delve into one particular area. Get ready to make a mental shift. You see, it's not about data. This was a stunning realization for me, and many still struggle to accept this as true. Even many who realize that data should not be the focus continue to design systems, tools and frameworks that keep data at the core. Even frameworks that focus on creating things like "business entities" with "business logic" continue to put data in the center of the universe. Developers add a few "methods" to some "entities" and call it object oriented. But, the Copernican revolution has already occurred. Data is not the center of the universe. Software development should not revolve around data. It should instead focus on messages and behavior.
"Hang on now, Jeff. Businesses really do care about data. And a good software developer wants to make the business happy. So you're just dead wrong. It really is all about the data."
I'm not saying that data doesn't matter. I am saying that data shouldn't be the center of our focus. Things like Invoices and Purchase Orders and Ledgers certainly have characteristics which must be represented as data. But there are far more interesting things going on in the business than just dates, currencies, strings and integers. Think of all the things a business might do with something as simple as an invoice. The business will create invoices. They might submit them. They might approve them or reject them. On occasion they might, perchance, adjust them or cancel them or combine them.
Let's step back to the data-centric systems approach I started with. In those days, I would have created an "Invoice" screen and a few supporting tables, queries, and reports. If the client wanted to be able to cancel an invoice, I probably would have just added a check box to the screen. If there was logic around whether or not an invoice could be cancelled, I would have to find a way to enforce that logic before the data got saved to a database (most likely in a procedural fashion). If the client wanted to adjust an invoice, they would just open the screen and do so, but no one would know specifically what was adjusted or why the adjustment was made. Many, many business processes remained "offline" from the perspective of the software system. It just provided a conduit for shoving data, with some forms of validation, and then regurgitating it later in some aggregated form like a report or query.
"It's Imperative! Do This!"
Instead, imagine telling the software application what to do. "Computer, create an invoice" or "computer, cancel this invoice" or "computer, approve this invoice" (no, I'm not a Trekkie, but I know a few). Certain data points will of course be captured along the way, but the user's intent becomes quite clear now as he or she interacts with the application. Instead of asking the system for a pile of data and then manipulating it accordingly, the user takes more discreet, fine-grained steps that model the reality of the business. The system becomes task oriented, message based and coherently descriptive of real business processes. Users submit commands to the software system, rather than plain data.
Consider just a few of the major improvements with such an approach. I've already mentioned one - the software begins to represent the reality of the business. Another benefit comes in the fact that developers begin to speak the same language as the software users. Instead of just gathering a bunch of data types with names like "InvoiceDate" or "Amount," developers learn the operational verbs used by the business. This can provide a healthy improvement to communication. So often developers want business people to speak their language, but high value systems can be built when developers learn to speak the language of the business instead.
While there are many other improvements due to this imperative approach, a final one worth mentioning comes from the fact that we are now sending meaningful messages between layers or components of our application and architecture, rather than piles of data. I will tease out multiple benefits of such a message based approach as this series continues. For now, just remember that it's not about the data. It's about the command. And the command is imperative.
See you next time when I'll tell you why you need to give your Domain a Break!