I have spent the last twenty years writing code that I called clean and that other people called clean and that I now think was bad code, which is a strange sentence to land on because the word clean was the whole point. The book said clean and the blog said clean and the senior engineer in the chair beside me said clean, and we measured ourselves against it the way junior monks measure themselves against a rule they have not yet read in the original. We wanted our code to read like prose, our classes to be small, our abstractions to be thin, our dependencies to be injected, and our DRY to be DRY, and for a long time the rules served us, and then they started serving the rules more than they served us, and that is the part nobody puts in the book.

It started for me around 2010, at Tata Consulting Services, where I was part of the backend team and I was very serious about clean code. I had read the book twice and watched the talk and I could recite SOLID in my sleep and I had a folder of bookmarks for every Uncle Bob blog post that mattered. We built the system the way the book said to build it, which is to say every layer had an interface, every interface had a single responsibility, every dependency pointed inward, the classes were small, the methods were small, the abstractions were thin, all the rules applied with the discipline of a convert, and the code read like prose on a good day, and a new engineer joining the team needed around six weeks to understand a feature because every line of business logic lived behind four interfaces, two factories, and a dependency injection container that we were all proud of in different ways. Java Struts was more indirection than reflection.

I think back on that codebase with something close to embarrassment because the user experience of working in it was horrible and shipping through it was worse. Every PR was a thirty-file diff because the interfaces meant every change rippled outward, every bug fix was a thesis defense because the abstraction meant nobody could find the line to change, and every new feature was a quarter of meetings before the first commit because the abstractions had to be re-arranged before the feature could land. We had built a temple and the temple did not match the road outside.

I started to notice that the engineers I respected most were quietly ignoring most of the rules, which was itself a useful piece of data. One of them, who had spent ten years at a large American tech company and had shipped things I had used without knowing, kept writing repositories that returned raw structs instead of repositories that wrapped the struct in a method called getRepository. He had nothing against the pattern. He had something against the pattern landing in his code. Another engineer, who was the best debugger I knew, kept inlining things that the book wanted factored out, because in her hands the inlined version was easier to find when the bug arrived at three in the morning, and “easier to find” beat “cleaner to read” by every measure she cared about. Both of them were right, and both of them would have failed the SOLID interview I had been planning to give.

The argument I want to make is about the cargo cult, which is the version of the principles that treats the words as the thing, and the principles themselves mostly describe real phenomena. Single responsibility is good advice when you mean it, dependency injection is good advice when you have a reason for it, DRY is good advice when you have actual duplication, and the others are mostly good advice in the same conditional sense. None of them are bad. The bad thing is calling the principles clean and defending them with the same missionary confidence the book uses to defend itself. Clean code is a smell, because clean is a thing the author says about their own code, and the author is in the worst position to verify it, which is the argument I think the book missed.

The argument is also that acronyms proliferate because they make a complicated thing look portable, which is the same reason consultants use them and religions use them and lawyers use them, and engineers should be more suspicious of their own acronyms than they currently are, and SOLID is a word that lets you have an opinion without having a position, DRY is a word that lets you delete a line of code that you did not want to maintain and feel principled about it, KISS is a word that lets you not write the abstraction and feel like you took the high road, and YAGNI is a word that lets you leave a hole in the system and feel like you were being disciplined. None of these are wrong. None of them are principles either. They are moves in a conversation that has been compressed into four letters because somebody wanted the conversation to fit on a slide.

I think the worst version of the cargo cult is the part where we name our own code clean, simple, robust, easy, fast, perfect, definitive. We are not entitled to these names. We did not earn them. The work we just finished is too close to our face for us to be the judge of it, and the future we are imagining when we name it is not here yet. A class called SimpleRepository is a class that has not yet been modified, a service called TheEmailService is a service that has not yet had three product pivots land on top of it, and a function called parseInput that catches every exception is a function that has not yet been asked to fail differently in production. The names we pick reveal what we are hoping for, and the code only tells us what we have.

I do not know what the right reading is. I have been deleting interfaces in my current project and the code gets shorter and more honest with every deletion, and the next engineer who joins us will not have to read the abstraction to understand the system, which is the only metric that has ever mattered to me. The interfaces did their job, which was to help me think through a phase of the system that needed designing. They are no longer earning their place, so they are going. The senior engineering manager I worked under in later in 2012 used to say code is a moving target and the right shape today will be the wrong shape tomorrow, and I did not believe him then and I believe him now.

I am suspicious of any book that calls itself definitive, which is the part of the critique that goes deeper than the SOLID conversation. The patterns are useful, the names are wrong, and the personalities behind them are mostly fine, and the whole craft is older than any of them and will outlast most of them, and the best thing I have learned in ten years is that the engineer I want to be is the engineer who deletes most of what the books told him to write. The good code is shorter, calmer, and has fewer opinions about itself, and the bad code came pre-opinionated, which is the smell I have been chasing for ten years. I think the next ten years will be the era of writing less and shipping more, and the senior engineers I know are already there. The rest of us will catch up.

Tell me what you deleted last. I am @troysk704.