Showing posts with label Microservices. Show all posts
Showing posts with label Microservices. Show all posts

Sunday, November 25, 2018

The self-preservation of Corporate systems

Can we fundamentally change a company culture? If so, how can we approach it lest the self-preservation mechanisms snap the system back into its former status quo? Let us examine the joints and levers within a typical corporate system with a causal loop diagram - and what we would need to tackle to make a lasting change.



A stable corporate system

Before we take a look at the slightly scary diagram, let me explain the basic representation model:

Defining the model

Black rectangles represent organizational artifacts and/or structures.
The colors red and blue represent negatives and positives, so respectively:

  • A red circle represents a negative system variable of which you probably want to have as little as possible.
  • A blue circle represents a negative system variable of which you may want to have as much as possible.
  • red arrow represents a negative causation, which means by adding more of the source, you get more of the target.
  • blue arrow represents a positive causation, which means that adding more of the source means you'll end up with more of the target.

With this in mind, take look at the model:


Example 1: Titles and hierarchies

Why do organizations assign titles and positions? You may find numerous reasons,such as a way represent responsibility, denote boundaries, indicate paycheck size or soffer prestige as a non-monetary reward or incentive.




Regardless of the initial reason for creating a title, the title or position derives meaning from the privilege it provides. Any such privilege indicates that a hierarchy is formed.
For example, you can't have a Ministry of Silly Walks if there's nobody in charge of Silly Walks - so the organization gets divided into those responsible for Silly Walks and those not.

As long as the position and the title exist, the organizational boundary continues to exist, and as long as the organizational unit exists, it needs someone in charge and some executive function to take strategic responsibility.

As the years go by, it becomes impossible to discern whether the Ministry of Silly Walks exists because the company needs it, but since it has a function, it needs to continue to exist - and when someone from that unit leaves, another person is hired to fill the role: The position exists because the hierarchy has a place for it, and the hierarchy has a place for it because it exists.

As more organizational units are added, the hierarchy becomes stronger - and a strong hierarchy needs clear separation of responsibility to function: a positive reinforcement loop.


Example 2: The mindset of a hierarchical organization

As soon as a hierarchy has been defined, people start to think in terms of that hierarchy. "We need a Silly Walker for the Ministry of Silly Walks".

It doesn't stop at needing someone who meets the requirement of Silly Walking: we wouldn't want to hire just anyone for Silly Walks - we need someone who is good at Silly Walks, who has experience and who is the perfect fit for the position. Rather than consider the myriad of ways in which a person can add value to the organization, the position of Silly Walking would be given to a person with proven track record of Silly Walks, a person with a history in Sales and Marketing wouldn't even be considered.
Likewise, a person who worked in Silly Walks for years is "obviously" best suited for Silly Walks. It becomes ludicrous to entertain the idea to place such a person in IT or customer care. The pervasive mindset becomes that people can only be good at the things they did before - a "fixed mindset":




As titles become more important, people themselves stop entertaining the idea of changing roles - why would a VP of Silly Walks want to take the role of "Developer" or "Scrum Master"? So instead of moving towards a system where people can learn and contribute the highest value to the organization, the system preserves its hierarchy: "Because I have this position, I will fight tooth and nails to preserve its existence."

We end up with a vicious circle where a fixed mindset entrenches itself and becomes a self-fulfilling prophesy.


Example 3: Transitive preservation mechanisms

When an organization would take steps to fix their problems one by one, they could do something about it - for example, let's say the organization would choose to get rid of the hierarchy in an attempt to remove the need for Resume/CV processing:



They will soon discover that the hierarchy isn't what led to the need for CV processing, although by direct causation, the primary construct which made Resumes necessary no longer exists. Even if the entire management layer would leave, people would still think in titles and positions, would still feel a person's value to the organization could be defined by their CV - and would think that CV's are still a good idea. Eventually, people would resort to "fixing the problem" of absence of hierarchy by - reintroducing hierarchy.
The transitive nature of systemic dependencies would rengenerate the system back to former status quo.


The complexity of the system

We just took one small example on three items from the system model - and there's a whole lot more to it. For example, large hierarchies with clear boundaries set people apart: "Those sales peeps" or "That's an IT problem" are just examples of common statements we often hear.
To control this separation, reports are introduced - and reports without consequences are meaningless, so systems of reward and punishment are introducted - which induces fear, both on punishment and reward (Fear of Missing Out) - which leads to shoving problems under the rug, which reduces transparency, which makes it more difficult to trust -- yada yada.

Regardless of where we look, a corporate system makes sense when looking at it from within the system: if we would abolish any single component, there would be more problems, so we need to re-introduce said component.

The real issue behind such a complex system is its tendency to meet the Laws of Irreducible Complexity.


Self-Preservation

A corporate system preserves itself due to a number of closed and transitive feedback loops: for example, even if we would remove the "Reporting" and "Rewards/Punishments" components from the system, there would still be the problem of distance and absence of trust, which seems most logical in the Enterprise world to fix via introducing the abolished mechanisms.

Delayed effect

Change isn't instantaneous. An organization suffering from strong negative system variables or weak positive system variables won't spontanenously fix their problem by changing their components. For example, if we have a high fear factor, stopping extrinsic incentives isn't going to remove the fear - removal of fear takes a long time, and some people might never overcome the specters of the past.
Removing a systemic component and dealing with the systemic variable by introducing a "repair construct" (such as coaching) need to go hand in hand - yet aren't a guarantee for successful change.

Change your mind!

Startups and small companies get by quite well without any of these mechanisms, and many larger organizations (such a volunteer organizations etc.) can also do without such artifacts.
Why does it work there? Because the basis is completely different. Instead of investing into hierarchies and titles, they invest into getting meaningful work done. Instead of introducing reports, they work on creating transparency and trust. Instead of creating a value plaque to hand into HQ, they talk about what matters to them. Instead of hiring for fit, they hire for value - and so on.

You can't reinvent a corporation by abolishing or fixing one mechanism - you have to start with the mind and work on everything at the same time!


Complex, yet simple

This model contains a lot of assumptions and simplifications. Organizations are significantly more complex, and the mechanisms which make people tick could be innumerate. I wouldn't be able to fit all important factors into this model and still let it be readable.

When attempting to make changes to a complex system, we need to understand the important components, variables and levers. What we consider "un-important" and neglect in our modeling might crawl out of the cave and bite us at the most inconvenient moment. Even with the above model, careful consideration needs to be exercised before trying to change a system.



Conclusion

There is no simple way to change an established organization, even when that organization is a dreadful place to work.

It's much simpler to build up a new organization with a blank slate and without all the harmful constructs than fixing an existing system.
Where this is not an option, the process of change relies on constant feedback about the current state of the system and permanent discovery of the hidden systemic factors which would snap the old system back into place.

Wednesday, October 31, 2018

My discovery journey to FaaS

Moving from monolithic systems to autonomous services is more of a mindset challenge than a technical challenge, although depending on the architecture of a system, the latter can already be tremendous. In this article, I want to describe my own discovery journey which changed how I perceived software systems forever.


Introduction

I was working for a client on an Information Discovery project which gathered and evaluated data from a range of other platforms which were basically a Stovepipe Architecture, so we had brittle, incomplete data objects from a wide range of independent systems which all described the same business object. There were two goals: First, link the data into a common view - and second, highlight inconsistencies for data purification. So to say, it was a fledgling Master Data Management system.



Stage 1: The Big Monolith

Although I knew about services, I never utilized them to their full potential. In stage one, my architecture looked something like this:




The central application ran ETL processes, wrote the data to its own local database, then produced a static HTML report which was sent to users via mail.
The good news is that this monolithic application was already built on Clean Code principles, so although I had a monolith, working the code was easy and the solution flexible.

The solution was well received - indeed, too well. The HTML reports were sent to various managers, who in turn sent them to their employees, who in turn sent them to their colleagues who collaborated on the relevant cleanup tasks. This was both a data protection and consistency nightmare - I couldn't trace where the data went and who was working with which version. So I moved from an HTML report to server-side rendering within the application.


Stage 2: Large Components

My application became two - an ETL and a Rendering component, both built on the same database. I had solved the problem of inconsistent versions and access control:


But there was another issue: Not everyone needed the same data, and not everyone should see everything. There were different users with different needs. The Simplicity principle led me to client-side rendering: I would pass the data to the frontend, then let the user decide what they wanted to see.


Stage 3: The first REST API

I cut in a REST layer which would fetch the requested data from the backend based on URL parameters, then render these to the user on the browser:


This also solved another problem: I wouldn't need to re-create the report in the backend whenever I made changes to layout and arrangement. It enabled true Continuous Delivery - I could implement new representation-based user requests multiple times a day without having to do any changes to any data on the server. The cycle time was three to five relevant features - per day, and so the report grew.

Guess what happened next? People wanted to know what the actual data in the source system was. And that meant - there was more than one view.


Stage 4: Multiple Endpoints

Early attention to separable design and SOLID principles once again saved the day. I moved the Extraction Process out of the ETL application and into autonomous getter services: 



This made my local database asynchronous with the data users might see, but this was a price everyone was willing to pay - it was enough if the report was updated daily, as long as people had access to un-purified raw data in real time. Another side benefit was that I pulled in pagination - increasing both performance and separability of the ETL process as a whole.

Loose coupling allowed me not only to have separate endpoints for each Getter, it allowed me to completely decouple each getter from a central point: I could scale!

As the application grew in business impact, more data sources were added and additional use cases came in. (To keep the picture simple, I'm not going to add these additional sources - just imagine there's many more).

Stage 5: Separate Use Cases

This modification was almost free - when the requirement came, I did it on a whim without even realizing what I had done until I saw the outcome:



Different user groups had different clients for different purposes. Each of the client needed only a subset of data, and that data was a subset of the available data - I could scale clients without even modifying anything in the core architecture!

And finally, we had network security concerns, so we had to pull everything apart. This was a freebie from a software perspective, but not a freebie from an infrastructure perspective: I separated the repositories and deployment process.


Stage 6: Decentralization

In this final stage, it was impossible to still call it "one application": I ended up with a distributed system with multiple servers, each of them hosting only a small set of functions which were fully encapsulated and could be created, provisioned, updated and maintained separately. In effect, each of my functions was a service running independently of its underlying infrastructure:


And yes, this representation omits a few of the infrastructure troubles I had, most notably, availability and discovery. The good news is that once I had this pattern, adding new services became a matter of minutes - Copy+Paste the infrastructure provisioning and write the few lines of code that did what I wanted to achieve. 



Conclusion

As I like to say, "The monolith in people's heads dies last". Although I knew of microservices, I used to build them in a very monolithic way: Single source repository, single database and single deployment process. This monolithic approach kept infrastructure maintenance efforts low and reduced the complexity of maintaining system integrity.

At the same time, this monolithic approach made it difficult to separate concerns, pull in the necessary layers of abstraction to separate use cases, resulted in downtimes and a security nightmare: When you have access to the monolith, everything is fair game: Both availability and confidentiality are fairly easy to compromize. The FaaS approach I discovered for myself would allow me to maximize these two core goals of data security with no additional software complexity.

Thanks to tools like Gitlab, Puppet, Docker and Kubernetes, the infrastructure complexity of migrating from is manageable, and the benefits are worth it. And then, of course, there are clouds like AWS and Azure which make the FaaS transition almost effortless - when the code is ready.


Today, I would rather build 20 autonomous services with a handful of separate clients that I can maintain and update in seconds than a single monolith that causes me headaches on all levels, from infrastructure over testing all the way to fitness for user purpose.


This was my journey. 
Your mileage may vary.