Douglas ’ Blog

My reflections on programming

~ Dec 04, 2023 ~

When I was younger, I discovered that I could create games with programming. That was the spark that led me to pursue a career in programming.

But years later, in my internship, I got into web dev and changed my focus. Everything was new, and I was eager to learn about frontend, backend, databases, and AI.

Then, I became interested in best practices. I wondered: “How do I write better code?” That led me to learn Clean Code, SOLID, Design Patterns, Clean Architecture, Domain Driven Design (DDD). I thought I knew everything there was to know about software architecture. I believed I could design any software. There was nothing more to learn.

Later, I found a book titled: “SOLID is not SOLID”. It was the best six dollars I ever spent. The author showed that SOLID is not helpful and gave clear examples.

It was the first nail in the coffin of the so-called best practices.

I also started applying Clean Architecture on frontend just to be disappointed. I applied to personal and job-related projects only to realize that it becomes a bloated source code with so many files with just five lines or less. Everything felt off, but that’s how the ‘experts’ say to structure your code.

Another nail in the coffin.

Then, I saw some videos and blog posts about software being in decline.

Software has become bloated and complex. The vast majority of software is slow, bloated, and unreliable. One reason is we made up rules, the so-called best practices, that should improve developer time, but there is no evidence of this outcome. To make matters even worse, we make up so many excuses as to why it’s the way it is and that we can’t do anything about it to make better software. We completely lost control of software quality. We waste time and energy regurgitating the best practices to new developers.

We also use hype-driven development. Use the latest tech in production without considering the pros and cons, like the microservices fad. That helps to make software harder to develop.

We reinvent the wheel in basic stuff like CRUD operations instead of using a framework like Rails. We are wasting time and energy by using the JavaScript ecosystem. There is nothing wrong with reinventing the wheel, but our wheel is worse.

We use React.js where it’s not needed, and React.js itself is a poor abstraction that needs a framework, state, and fetching library to add to the bloat and work properly. All this is to make some web pages with forms and validation.

So much over-engineering!

We can make better software that is fast, reliable and maintainable.

In conclusion, you should ignore every random abstract rule, guideline, or fad or at least find a way to measure to prove it has benefits for your use case.

My advice to every programmer is:

Forget all best practices. It’s all fluff. Focus on real problems. Programming is about moving data from one place to another. That’s all.

Here’s a list of things you should ignore and a short explanation of why I think this way:

Ignore Clean Code

You can write good code without reading Clean Code. Reading Clean Code doesn’t make your code good.

Ignore DRY

By following DRY, you might create the wrong abstraction.

Ignore Refactoring

The Refactoring book is useless because it focuses so much on OOP. The only techniques that I think it’s worth are:

Also, have a look at semantic compression.

Ignore SOLID

Read the book

Ignore Design Patterns

The only purpose is to patch deficiencies in the language, especially OOP languages. The authors agrees that some patterns don’t make sense in another language because they have better mechanisms to solve a problem. The excerpt from the book:

…some of our patterns are supported directly by the less common object-oriented languages. CLOS has multi-methods, for example, which lessen the need for a pattern such as Visitor (page 331). In fact, there are enough differences between Smalltalk and C++ to mean that some patterns can be expressed more easily in one language than the other and most of this languages existed before Java and C++, which are the target languages of the book.

The strategy pattern, for example, existed way before the book. In C you could pass a function pointer to a sort function

Ignore Clean Architecture

Clean Architecture is overrated and not needed. There is no point in discussing each variant and its differences. (ports and adapters, onion, hexagonal). You can achieve modular and testable code without Clean Architecture.

If you really want Clean Architecture, you can apply pure functions to your code.

From a personal experience with Clean Architecture, I wrote a recipe manager for my mom. It is a simple app with CRUD operations on a Recipe table. The catch is the recipes are in Portuguese, and Portuguese words have accents. So, to make the search work, I needed a Postgres extension to remove the accents from the search query and the recipe title. Even when applying Clean Architecture, my code was bound to the database, and I couldn’t replace it if I wanted. It was crucial to the solution.

Ignore DDD

DDD is overrated and not needed even in complex projects. You don’t need DDD to improve communication.

Remember that there is no silver bullet.

Ignore OOP

There is no proof that OOP provides any benefit.

OOP generally leads to bad performance:

Several books tries to patch OOP:

  • “Object-Oriented Design Heuristics” by Arthur J. Riel.
  • “Object Thinking” by David West
  • “Elegant Objects” (Vol. 1 and 2) by Yegor Bugayenko

Those books show that OOP is flawed as they provide guidelines to write better OO code. It’s about 1200 pages of heuristics! Try to remember all that!

Michael Feathers wrote a blog post saying that his book “Working Effectively with Legacy Code” should be named “Working Effectively with Object-Oriented Code”. He also says that functional code is honest code.

There are many successful non-OOP projects: Git, Linux, Redis, Nginx, Postgres, and SQLite. You can write successful software in OO, procedural, and even assembly.

Modern languages, such as Rust, Go, and Erlang, do not explicitly adopt OOP and do not encourage it, and some older languages are moving away from the paradigm. It applies to Java, C#, and C++.

Ignore Test Doubles and TDD

Ignore test doubles terminology. All you need is data and a function for testing purposes. Forget the test pyramid. Focus on integration tests. Focus on writing tests, not on TDD.

Always remember that software without tests is not maintainable.

Ignore Microservices and Microfrontends

Microservices and Microfrontends are Conway’s law. The same applies to frontend and backend separation. Most of the time, you don’t need microservices, only for some specific cases.