DEV Community

Don't over-engineer!

Sami Pietikäinen on February 07, 2019

Most if not all programmers nowadays are familiar with the concept of clean code. In short, the clean code principle means a development style that...
Collapse
 
aleksikauppila profile image
Aleksi Kauppila

Interesting read, thanks Sami!

I haven't yet experienced this kind of situation. However i'm very familiar with the opposite. :)

I've heard a more than a few time the mantra "don't over-engineer" as an excuse to not do design at all. The thought is usually "in which class could i cram this piece of code" which imo usually indicates that there isn't enough abstraction. Also object have too many responsibilities, know and do too much.

Create abstractions only when they contribute positively to the design by removing duplication or decoupling modules for instance.

Yes, but beware of primitive obsession. If it's not in the business domain or isn't a clear or well known pattern then i suppose it creates confusion.

Sometimes the code base looks as if the author read "the Gang of Four" design pattern book and tried to apply every single one of them in a single code base.

Someone smart has said that don't design to patterns, but refactor into patterns.

I'd be curious if you could show me an example where things are clearly over-engineered?

Collapse
 
samipietikainen profile image
Sami Pietikäinen

First of all, thanks for reading and commenting! Very good observations indeed.

I think fixing the primitive obsession is a prime example of a situation where the added abstraction and complexity (new classes and types, for instance) have a significant positive impact to the overall design. But as you remarked, it is important not to misinterpret "don't over-engineer" with don't design at all.

The sentence about overuse of design patterns is a bit exaggerative and I am by no means against them in general. In fact they can convey a lot of information by providing a common vocabulary (if I see that something is for example an observer or a factory I immediately have a pretty clear idea what it is). Still, it is important to avoid "when you have a hammer, everything looks like a nail" type of situation where same patterns are applied to all problems whether they are a good fit or not.

I have encountered this mainly in some older C++ codebases that I have worked with. Though, the opposite "no design at all" might be even more common as you said. Unfortunately these have been closed source so I cannot directly link to any code.

One concrete situation I have seen is overuse of abstract classes and interfaces where many classes have accompanied abstract class or interface even though it does not provide any value. For instance, internal classes that do not need to be heavily decoupled or only one concrete child class. I suppose they are added "just in case" but could be refactored in when actually needed. Another case is own implementation of common algorithms or containers without documentation or rationale why the standard ones were not used.

I would say that most of the time things are not grossly over-engineered but sometimes you'll notice that it takes extra time to understand some piece of code only to realize later that it should not have been that complex.