In the previous chapter, we’ve seen the benefits of finding mutual exclusivity between Sources and within Causes. Not only does it lead us to a correct design in terms of cohesion and decoupling, it leads to slowing down the erosive evolutionary processes. Specifically, towards a Monolith and a Refactor. Which makes it an eventually beneficial design.
We’ve shown the reason behind that success. It is a design that better matches the Change Stream and is agnostic to its unsteadiness. Problem is, applications are far more complicated than just being dependent on a third party package. They have a goal to serve customers, and fortunately the Product Manager is here to make sure of that. In this chapter, we’ll explore the problem Product Changes entails through the Change Stream.
Cutting Through Layers
Realistically speaking, we do all know that Changes to Stripe do not adhere to its Direction of Change. Some Changes to any 3rd party dependencies, Stripe or our database, do affect our product and thus has the potential to affect our entire application.
Let’s imagine a simple Change in Stripe of a new flag/boolean had been added to one endpoint. For Product A it entails a user to select from a drop-down menu, with some default value. For Product B it entails a user to tick a box, ticked off by default. As it says so in the Ticket the Product Manager created, a Cause with Intention has been created. Our application currently has only one Direction for us to follow, so we have no choice but to cross over the integration to the other Modules and Change them all together at once. Or we can follow in another Direction.
Imagine a single application perfectly designed to layers. Each layer is decoupled from the other, and internally cohesive. Up until today, the application was simple enough that it did not require a database. All the data was stored in memory.
Due to a technical Cause ,the application today requires a new database. As we design with eventualism, we knew this day would come so we put in the Data Access Layer (DAL) in advance. Good thinking. Now that we need to Change the Data layer, there would be no Change to any Product related layers. Sounds exactly like a Direction.
A few weeks after the data was moved to Redis, a new feature request had come in from the Product Manager. A Cause with Intention to Change Product A alone. Getting it done requires at least one Change to each and every layer. Luckily, our organization has a dedicated team for each layer. Each one really does require a different kind of technology, expertise or experience. Let’s model these Directions.
Something is wrong here. A Change to each layer has the potential to unintentionally affect both products, although our people’s Intentions are to Change Product A alone. We also know that there is one Cause (the new feature) and one Source (The Product Manager). Instead we can see three Causes and three Directions. There is a mismatch between our application and our organization and the Change Stream.
This mismatch results in organizational friction. As each team has its own schedule, there would be delays in deliveries. It also requires a lot of collaboration and a lot of back and forth communication between teams, mostly unnecessary ones. The mismatch creates Inefficiencies and preventing those is under the responsibility of The Architect.
The Engineer is about to do what he should do, which is to refactor the application to make it more suitable for the product Changes. He would call in The Architect who understands the Source, and they both invert the design. They both realize that cutting through all these layers all the time is inefficient and quite hard. Unfortunately, refactors always have the potential to create Instabilities and fail. Uncoincidentally we hired the best people so they know how to refactor it slowly and safely. Unawarely, they have aligned the application with the Change Stream.
We can assume that The Architect, with his understanding of the Source, has also realized that they work for a Product-oriented company. He went ahead and saw that Product-oriented Changes are more frequent than Technical-oriented ones, properties of the Change Stream . He knows the company is not a platform provider but only has a mobile application.
What they haven’t done, is overcoming the unsteadiness of the Change Stream. A year later the company has raised some serious capital and has entered its growth stage. The entire next year would be all about platformization, exposing everything we have as APIs. The company is now no longer Product-oriented, it is Technical-oriented. The Change Stream has Changed. The application would need to be inverted and refactored again.
Although they refactored the application correctly, the organization had remained the same. The split to three Causes still exists because we still have three dedicated teams with their required expertise. The Architect has raised a flag and Caused a refactor to the organization, what is better known as a reorganization.
Obviously he only Caused it. Trust me, you don’t want to be the one to Change an organization’s structure. It is something way beyond what is required of a Software Engineer. He only needs to Change his application accordingly, and leave the organization to its leadership which The Architect is only a part of.
The leadership went ahead and Changed the structure. Instead of a dedicated team per layer, the company now consists of dedicated teams per product. Each one with its own Product Manager. As a consequence it is now also aligned with the Change Stream. And a year later there might be another reorganization because the Change Stream is unsteady, and the company has entered its maturity stage. And that entailed yet another refactor to our application.
We need to recall that our application has no mind of its own. An application should not be aware and can not be aware whether a person is now titled “Product Manager” or a “Technical Product Manager”, or of this entity called “Organization” or “Company”. It’s not an application “fault” that the company had been successful and grew.
But we’ve been through this before, we already know how to overcome this. We’ve seen that if we can find mutually exclusive Causes and Directions, our application would align accordingly. And it seems we have some kind of split between Product-oriented and Technical-oriented Changes.
There is something to it, but this tuple is not mutually exclusive and Products are a whole different thing from a Database. We’re going to see why in the next chapter.