SOLID premature optimizations

I think that every sane developer agrees that the SOLID principles are good and useful and when the time comes, you should apply them… but in this blog post I will concentrate on the: when the time comes part.

I will probably get a lot of hate for writing this blog post, probably some people will consider me a sub mediocre developer for saying this… The idea is that, in my opinion, applying the SOLID principles for every part of the code is premature optimization and instead of making your code more maintainable it will make it a rigid and unmaintainable mess. Optimizations doesn’t refer only to speed improvements but also to architectural improvements. For example: hiding all dependencies behind interfaces is something that a lot of SOLID developers do. Why? Because they are preparing the code to be modular, testable and changeable,  even though, they don’t really have multiple implementations for the interfaces yet. Also, they often change the if statements to strategy patterns even though, at that moment, the if statement is small and really readable and will probably remain like that for a long time. Changes like this will split the logic in multiple files, when you want to read the condition you will need to check 3 classes instead of a few lines in a single file, in short, it will make your code more complex that it needs to be.

computer-1886313_640

In my opinion this is wrong. It’s like having a piece of hardware, a computer, with all parts interchangeable, movable: it simply doesn’t scale. It’s OK for your RAM pieces, HDD and other components to be movable, but these individual components are not modular at all. You can’t change the pieces inside your CPU or RAM chip and most components on the Motherboard are glued to that plastic… otherwise it would be painfully slow or impossible to assemble a working PC. Look inside your Mac Book!, it’s modular till a point, but some components are not modifiable or movable! This is an absolute requirement for a stable and robust architecture. Some parts of your applications should be modular and accessed via interfaces, but not all of them.  As in any other engineering field, sadly, you can’t blindly follow some rules and expect to obtain a good design. You must sit down, analyze the requirements and apply some principles when needed and constantly adapt the design to the new requirements. No premature optimizations regarding the design will help you avoid the constant need for refactoring and redesign. Don’t forget SOLID are not programming rules but programming principles, you can and should apply them, but when the time comes, do it softly… gently 🙂 .

If you found this post useful, please feel free to share and give it a LIKE , so others can find it too! Also if you want more content like this please hit the FOLLOW button. Thanks 😊

4 thoughts on “SOLID premature optimizations

  1. Some experienced developers also refer to coupling and cohesion.
    I think that’s your point, module should be small until you really see how it can be reused, but its submodules should not have interfaces (as long as there are no candidates for runtime substitution), they should be COHESIVE and use each other as much as possible.
    Even if constructor is called directly in some function that’s ok from my point of view, why someone has to write unit test for submodule, not public interface?

    1. Yes, exactly my point. Even in case of submodules maybe you want to have some interfaces and unit tests, and that’s also fine, but not as a general rule for the entire application. That’s over-engineering and introduces unnecessary complexity to the code base.

  2. Your point of view in my opinion is somehow similar to monolithic vs. micro services architecture (mostly related to the backend development): If I do understand you correctly, your point of view imply that one should not separate concerns (and thus split components into small, very focused ones) ASAP, but rather develop the app without addressing the subject until most of contracts and concerns are apparent and then refactor to improve the app’s architecture, by separating components that are reasonable to have as separate components.

    I agree on that, it sounds reasonable.

    You definitely right about the premature problem, when devs are trying to lay down the best architecture possible from the beginning without actually considering the trade-offs of the approach they follow.

    At the same time, it’s the experience behind those decisions that matters, not the approach itself. I see developers with tons of experience in architecture designing that can define the contracts ahead, though they don’t try to over-engineer things, rather they define the “ground” rules the project components must obey so the project can grow without introducing a mess that **often is a real reason for refactoring, not the need of adaptation**.

    So, as you said in another medium article on subject, the moderation is a key. I’d like to continue on that:
    **the moderation is the key; as are the reasoning and the experience behind your decision**.

    1. Exactly, in my opinion this also applies to monolith vs micro-services and actually to anything related to software development. People often try to find a magical fix-it-all solution but there is no single answer. You’re also right, there are some really smart dudes that have so much experience, they can actually make really good design decisions up-front, but usually those are the developers who militate for KISS (for example Bjarne Stroustrup here: https://www.youtube.com/watch?v=nesCaocNjtQ or Anders Heljsberg here: https://www.artima.com/intv/handcuffs.html)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s