This article continues my series inspired by the book “Software Architecture — the Hard Parts” by Ford et al. In my experience the book is missing the hardest and the most challenging parts.

The hardest parts of software architecture are, ironically, the softest ones. They relate closely to the organization’s power structure, history, culture, and sources of uncertainty.

In the first and second part of this series I introduced my top 4 actual hardest parts of software architecture.

In this part I'll introduce six patterns that I’ve found useful when struggling with these vicious problems.

This article series was originally published on Medium.


There are no silver bullets to address the problems I have presented in the two previous posts. I find ideas from domain-driven design especially useful here. Concrete methods such as Event stormingDomain storytelling, or User story mapping deserve a separate post.Instead of diving into details, I rather share the overall principle I try to follow, when creating plan and vision of architecture.

Open-minded curiosity over logic and best practices

Photo by Frederick Marschall on Unsplash

Best practices and cold logical calculations take you far. In overall, it’s good to know the tradition and upcoming trends. For instance, trade-off analysis patterns and practices introduced by Ford, Richards, Sadalage and Dehghan in The Software Architecture — The hard part is greatEvans’, Walsh and Brandolini’s ideas about Domain Driven Design are awesome. SOLID principles & Clean Architecture by Robert C. Martin provided a foundation for software design. And so on.

Then again, software systems and software development are intrinsically (corporate) political and dominated by social rules of power, wealth and influence rather than the rules of logic. The corporate political and social aspect of software development is more extensively discussed in agile and lean literature than in architecture discussion. The whole agile movement is a political/social paradigm shift rather than just a technical or pragmatic one. The ideals of software architecture move slowly from the modernistic realm of logic toward a more pragmatic, pluralistic postmodern approach that addresses better power distribution and social influence.

In short, overemphasizing logic and the best practices is, in practice, annoyingly arrogant and contemptuous from the point of view of business stakeholders and other developers of the teams. Arrogance and contempt often lead to low trust and motivation and unnecessary complexity. Low trust and motivation alone harm the delivery more than sub-optimal solutions that are not aligned with all the best practices. You need to set the bar for technical excellence, but you should not do that at the expense of political trust and influence.

When planning a technical solution, consider the following:

1) How can you provide evidence of progress early and frequently thereafter 

How to make progress visible early and frequently to (a) increase trust and shared understanding among the stakeholders and (b) make possible lack of trust and shared understanding a painfully visible problem?

I underline that not all evidence of progress is equally good. The wrong kind of evidence (“partially done work”, in particular) creates false optimism. You should seek political trust and strong social bonds and tackle foreseeable trust issues as early as possible by making them apparent.

E.g., start by asking, “When things go like in a dream, what is that like? How do you know we succeeded in this project or initiative?”

2) Make tech language easy to relate with and approachable for everyone

How do you first convert technical jargon into language the business stakeholders can relate to and then help those who do not have expertise on the used technology expand their expertise and understanding with ease?

You cannot discuss technology without using ‘technological language’. Yet you should consider how to make the entry point into tech wonderland approachable and appealing. It’s naïve to dream that anyone can translate the technical side of software into a ‘non-technical business language’.

3) Make business problem easy to immerse in, grasp and experiment with

How do we express business problems so that it is easy for tech-oriented experts to relate the business side of the problem and immerse into the role of the end-user and the sponsor of the work? In short, how might you help people to be curious?

Whereas you cannot and should not protect business people from technology, you should neither protect the tech-oriented people from business, no matter how business averse they might be.

✨ Subsidiarity principle and autonomy over coordination and coherence

If you don’t necessarily need to delegate decision-making authority to a centralised authority, you should not do so. A central authority should perform only those tasks that cannot be performed at a more local level.

In practice:

4) Distribute power and trust by default

Those who do the work should choose the tools, libraries, and technologies unless there is a strong need for coordination with the organization and the teams. If coordination is necessary, it should be the minimal and grand maximum amount of decision-making power to those whom the decisions have the most immediate impact. For instance, I find attempts to consolidate the tech stack often dysfunctional. Business cases where you should, say, rewrite a large code base using React and C# with Angular and Java (or vice versa) are rare. Usually, rewriting solutions to consolidate the tech stack and maximize reusability is a waste of time and a guaranteed way to ruin motivation and proactive decision-making. If the benefits of consolidation and shared practices are apparent and significant, express them with precise and unambiguous language and make them open for falsification.

5) Facing reality is the foundation of wisdom

You should accept that no single source of priorities and business goals exists if that is the case. For instance, it does not help stubborn insist that “the business should set the priorities” if they over and over again fail to do so. Instead, priorities should be seen as parts of pluralistic political agendas that are innately unsure and based on insufficient information. In practice, those who have the closest relation to the customer and those who feel the pain of poor architectural decisions are most likely to react in a timely order. Hence, they should also have the decision-making power to do so, even if this may reduce the coherence of the architecture and business models. Again, coordination is necessary, but it should focus on the constraints relevant to everyone and the transparency needed for accountability, not the control mechanisms and excessive upfront planning.

6) Beware “bullshit jargon” trap

If finding shared priorities that hold seems to be hard, consider what kind of language is needed for an agreement and commitment. Maybe the prioritization language contains an excessive amount of bullshit and jargon.

In my experience, the most common reason for the lack of commitment is that the goal, plan, and vision are seen as over-simplistic bullshit. People just don’t believe them, but they also feel that they cannot constructively disagree or ask questions. The used language is unreachable, and they fear that their questions are stupid.

For instance, an architect might justify the deployment of yet another service by saying that it’s necessary because of the separation of concerns. It’s maybe true, but it’s also potentially bullshit from developers’ point of view.

Overarching and abstract tech concepts (e.g., separation of concerns or inversion of control) can be handy, but the justification of tech decisions should be, most of the time, far more concrete, tangible, and testable (or falsifiable).

Consider addressing concrete concerns instead, such as “What is the worst thing that can happen if we deploy solutions for these two needs as a part of the same service instead of separating them into two microservices and vice versa?”

Summary

The hardest things in the software architecture are partially non-technical: the used language, the lack of epistemic foundation, conflicting of the models of reality, and the social and political reality or the organizations.

Current architectural pattern and practices do not adequately address these problems although especially Domain Driven Design tradition offers multiple pragmatic and good tools as pain killers.

In my opinion, architecture should pay more attention on the (corporate) political realities and the language needed to agree on priorities and goals. The architectures tend to offer overly rigid “big plan” that build too much on unsound assumptions about unchangeable and relatively stable priorities and goals, and fails to reveal emerging trust issues and false optimism until it’s too late.

The architects and tech leads commonly consider too little psychological aspects of the teams and experts, and harm motivation and willingness to take responsibility by delegating too little decision making power.

Both tech and business leaders should be wary of the “bullshit jargon” trap. People won’t truly commit in a plan that seems mostly bullshit from their point of view.