Kategorien
Book

Thougts on Clean Architecture from Robert C. Martin

After recently reading Clean Code from the same auther, now I followup on Clean Architecture from Robert C. Martin. While Clean Code focusses mostly on the smallest entities of software development and in a simplified manner can be called bottom-up, Clean Architecture naturally comes from top-down. Clean Code is much easier to apply in examples such as my current pet project, Clean Architecture is something more abstract for me, as I do not really have a huge software project at hand to apply.

Down the darkest path comes the idea that strong and stable architecture comes from authority and rigidity. The architect’s mandate is total and totalitarian, the architecture becoming a dystopia for its developers and a constant source of frustration for all.

Down another path comes a strong smell of speculative generality. A route filled with hardcoded guesswork, countless parameters, tombs of dead code, and more accidental complexity than you can shake a maintenance budget at.

The path we are most interested is the cleanest one. It plays more to our strengths than our weaknesses. We create things and we discover things. We ask questions and we run experiments. A good architecture comes from understanding it more as a journey than a destination, more an ongoing process of enquiry than a frozen artefact.

Kevlin Henney in the Foreword

Kevlin’s words chime very well with my personal understanding of good software architect mindset. In my career, I have seen all of the above, and I am glad in my current project all architects have the latter. However, its not a closed book. Many managers, suppliers and developers still demand for what I would call static enterprise architecture, with different rationale behind. While management sees architecture as a definition of tools, libraries and complete set of boxes to ultimately save money by „clarity“, suppliers want something fixed to make an offer towards and have something to blame when problems arise.

I’ve seen it happen. I’veworked in projects where the design and architecture of the system made it easy to writeand easy to maintain. I’ve experienced projects that required a fraction of theanticipated human resources. I’ve worked on systems that had extremely low defectrates. I’ve seen the extraordinary effect that good software architecture can have on asystem, a project, and a team. I’ve been to the promised land.

Introduction

This is an important statement, easy to overlook and ignore. Most of us know reality well enough to have skepticism regarding the applicability of clean approaches to corporate software development. The constant stress by deadlines, tight budget, competing stakeholder’s requirements and technology fights often overrules the best intentions. But giving up is no option. Every new project, every new week its worth to keep trying to establish a bit better code, a bit better architecture. Our own future selfs, and our professional spirits will be thankful.

The goal of software architecture is to minimize the human resources required to build and maintain the required system.

What is design and architecture?

I am not sure if I would call the above „The“ goal, but certainly its „a“ central goal. Replacing „human resourcues“ by „effort“ for me would make this goal statement more generally applicable. Effort can include human resources, but also license cost, mental imbalance and turnover.

On pages 5ff, Martin gives a case study of a company sinking exponentially more engineering staff while creating exponentially less output. Interesting and highly relatable. I hope I find ways to calculate according metrics also for my private and professional projects.

And that’s the answer to the executive’s dilemma. The only way to reverse the decline in productivity and the increase in cost is to get the developers to stop thinking like the overconfident Hare and start taking responsibility for the mess that they’ve made.

The developers may think that the answer is to start over from scratch and redesign the whole system—but that’s just the Hare talking again. The same overconfidence that led to the mess is now telling them that they can build it better if only they can start the race over. The reality is less rosy:

Their overconfidence will drive the redesign into the same mess as the original project.

What is design and architecture?

Martin is focussing here on the software developers and provoking them to not take management influence as an excuse for their own failure to maintain sane software projects. He has done the same in Clean Code. Personally, I can see both sides. Of course management often overrules developers to gain what they call „speed“ by effectively telling them to hack some dirty solution together. On the other hand I have seen enough developers either having a messy approach or giving up on management on the slightest push. So being somewhat in between I always try to balance and find tradeoffs. It sounds tempting to target only clean approaches and refuse deadlines completely, but its unrealistic and being too hard here my backfire. I know a developer who is so strict in his believes (and judging only by the technical content he is always right), that he is notorious to be ignored. Who wants to work with somebody who is not willing to compromise at all? (Me, yes, but many other managers take the short path and just go to the next developer)

Thus the final version of the SRP is:

A module should be responsible to one, and only one, actor.

SRP: The Single Responsibility Principle

Finally I got it. For a long time I really struggled to internalize the Single Responsibility Principle. All the other definitions or descriptions kindof made sense, but failed me to be applicable in a crisp way. With the above definition using the actor I got it 🙂 Apart from the SRP, Martin of course also introduces also the other SOLID principles.

While the SOLID principles apply to class interdependencies, he continues to establish three principles on component interdependencies. Naturally, they relate to the SOLID principles, so I wondered if there are ways to generalize a set of principles to apply them on any level of software, from systems via components to classes (and maybe even functions).

The Reuse/Release Equivalence Principle:

The granule of reuse is the granule of release

Component Cohesion

I really liked this principle, it sounds so obvious and clear, however I never thought about release cadence as architectural principle. Nice!

The Common Closure Principle and the Common Reuse Principle are very similar to the Single Responsibility Principle (see above) and the Interface Segregation Principle from SOLID, so both didn’t sound so new.

In the section on Component Coupling, Martin introduces two interesting metrics: Instability and Abstraction. After some reasoning, he defines the area around low instability and abstraction as the zone of pain and the area around high instability and abstraction as zone of uselessness. Classes on the „main sequence“ in the diagonal from (0/1) to (1/0) instead are considered sane. Exceptions of course apply, e.g. for database schemes (stable and very concrete).

I checked around and really could find a tool which calculates and displays the metrics for my pet project code. I directly added it to my CI pipelines. See below the recent output. Seems I need to check some of my code.

The strategy […] is to leave as many options open as possible, for as long as possible.

What is architecture?

Only 135 pages in Martin asks the question „what is architecture?“, and his answers really surprised me, it was nothing I really expected. In the following pages he gives many examples (really many, probably too many) for this. For Martin, „details“ such as external interfaces (IO, databases), frameworks, the web are not relevant for the core business rules. The latter are for him the core and to be untainted from all such details.

A good architect maximizes the number of decisions not made.

What is architecture?

I think again this is the provocative author, but in the context of his definition of „decision“ and „details“ this makes sense.

And then, thankfully, the Agile Software Development revolution arrived and put architects like me out of our misery. I’m a programmer. I like programming. And the best way I’ve found to have a positive impact on code is to write it.

The dinosaurs of Big Architecture—typically to be found wandering the primeval plains of Big Process—were wiped out by the asteroid of Extreme Programming. And it came as a blessed relief.

[…] The problem with leaving architecture to programmers is that programmers have to be able to think like architects. It turns out that not all of the stuff we learned during the Big Architecture era was of no value. The way that software is structured can have a profound impact on our ability to keep adapting and evolving it, even in the short term.

[…] Learn how you can incorporate design principles and Clean Architecture into your development processes […]. Perhaps, before you commit code, ask a colleague to review it with you. And look into the possibility of adding a code “quality gate” to your build pipeline as a last line of defense against unclean architecture. (And if you don’t have a build pipeline, maybe it’s time to create one?)

Most important of all is to talk about Clean Architecture. Talk about it with your team. Talk about it with the wider developer community. Quality is everybody’s business, and it’s important to reach a consensus about the difference between good and bad architecture.

Be mindful that most software developers are not very architecture-aware, just as I wasn’t 25 years ago. More experienced developers clued me into it. Once you’ve wrapped your head around Clean Architecture, take the time to wrap someone else’s head around it. Pay it forward.

[…] The real journey starts here.

Jason Gorman in the Afterword

I think thats perfect last words without any more need of commenting!

Kategorien
Coding

State of Pipelines

Just a brief update on my current pet project’s Jenkins pipelines setup. The Jenkins BlueOcean graph probably already covers it mostly:

I have parallelized some „Fast Tests“ – all of these take less than a second to run currently due to the small codebase. If any of them fails it doesnt make sense to proceed. Currently these contain

  • phpmd: „mess detector“ using the clean code ruleset to identify unclean code.
  • pdepend: Some code analytics I learned while reading „Clean Architecture“ (review will come to the blog soon I hope).
  • phan: Static Code Analysis
  • phpunit: Unit testing

After those I run API tests with schemathesis. This takes one minute (configurable) and sends random payload to my REST API as per the generated swagger file.

Last but not least I run some acceptance tests, as described in Adventures with PHPUnit, geckodriver and selenium.

For a while I also parallelized the latter two test activities in a „Slow Tests“ block, but I learned that the test execution was very unreliable due to the load the test environments put on my server. So for now they run sequential.

Today I finished some major clean code refactoring and I am happy to say that I could rework most of the code and the tests in place ensured that functionally nothing broke without me checking the actual application manually once! This is a major achievement for me personally, as all my former pet projects based on heavy manual testing on basically every change.