When we talk about OOP, we think of classes and classes and so on. But mostly we don’t care about being lazy. I love it when programmers are lazy. It means they will write less code doing more work (being lazy the write way). More and more people often write too much code and that’s just STUPID. Now now don’t get all worked up, it’s the reality of most of the code we see and It’s important to not be STUPID before being SOLID. Let me explain.
STUPID is a set of principles to avoid while writing code. Most of the time these are obvious things but we let them pass anyway. But they almost always have adverse impact on testability, quality, extensibility, maintainability, and reusability.
Ok STOP using singleton everywhere. It’s not a magic pattern. Most of the time you see singleton used as global state holder, and it’s just sad. This creates a lot of problems in testing since the instantiation cannot be controlled and they, by nature, can retain states (often hidden) across invocations. They also hide dependencies. Consider the following:
private DebtCalculator calculator = DebtCalculator.GetInstance(); //getting a singleton
public Account(IDebtCalculator c)
this.calculator = c;
Another, and perhaps a widely used example would be a database class that provides an instance of Database.
This looks easy and maintainable, yes? In reality, it’s just stupid code. This tightly coupled the client code with the Database class. Now if we want to get another instance, or connection to another database, this will be a big mess. Also testing this is always a problem. Adding new features (extensions) to Database class might create issues as well. Especially since any extension will be accessible to all the client code, regardless of need. This creates unnecessary and cluttered code and introduces security concerns.
Need I say more? Of course, I am not saying it’s an anti-pattern on its own. Rather most of the time it’s unnecessary to even have a singleton and the underlying problem can be solved much easier. So, use it wisely.
– Tight Coupling
Coupling is the measure of changes required in other modules to make a change in one module. The greater it is, the more coupled your code is. Tightly coupled modules are difficult to use and expensive to changes and hard to test. They also introduce cluttered code everywhere. In essence, it could be regarded as a generalisation of Singleton (global state). The moment we start using;
<some class>.<some method/ property> or
<some singleton instance>.<method/ property>
We tightly couple the client code with that class. This makes extending that class difficult, and testing the client code harder.
Private Logger log;
log = new Logger();
private ILog log;
public Account(ILog l)
log = l;// or any logger factory.
//now account is not dependent upon the Logger class.
Loose coupling makes testing, and feature extensions a breeze.
In theory, testing a piece of code should be the easiest of things. In reality, tight coupling, along with hidden dependencies makes it a lot harder and expensive to test modules. The result is bug prone modules. Whenever we don’t unit test our code because “there is no time”, the real reason is that our code is too hard to test
– Premature Optimization
o Don’t do it
o Don’t do it yet
A piece of code can be optimized to work as fast as possible only to later find out that it does not do what it’s supposed to. So:
o Make it work
o Make it right
o Make it fast
Of course, this does not mean making basic design mistakes or bad code should be allowed. When you follow standard design guidelines and maintained test cases, you optimized mercilessly as much as you want afterwards. Don’t waste your time in finding and using stupid micro optimization techniques that in production, does not do much.
Replacing foreach loops with for, unnecessary replacing strings with string builders, string.Format v/s Replace v/s bla bla. All those premature optimizations are just stupid, unless of course saving micro seconds and tiny bits of memory is a requirement in your code. Most of the time, these things are rarely the bottlenecks. Its design flaws, and wrong joins in queries, and untested code etc. that create problems.
These crazy don’t use <some stupid stuff> for micro optimization without need just distracts you from designing and writing testable and maintainable code
– Indescriptive Naming
The most obvious of the lot. Name you stuff right people. Classes, properties, methods, namespaces bla bla. Don’t write code that only you can understand. Write it for other to read and understand. Don’t use abbr. (pun intended). And follow the industry standards not yours.
DRY (don’t repeat yourself) is a key in writing good reusable, testable and maintainable code. And the most important, DRY helps avoiding runtime issues that slips through testing, undetected. I saw a piece of code where resources were used via relative paths converted to absolute ones everywhere. It went through testing but broke in staging because at a few places, it was still using the paths without conversion to absolute. The conversion was duplicated everywhere since it was just a single line. The solution, remove all conversions and configure it ONCE however you like and use whenever you need. Now that configuration can be controlled, injected, reused, and tested.
Programmers are lazy, and not the good kind of lazy, most of the time. Introducing any tight coupling open doors to copy pasting the same thing throughout the code because it now cannot be reused, and it’s just easy with control + c and control + v. who cares if it’s a horrible code smell that is neither testable nor maintainable. The worse thing about duplicate code; removing or fixing it is expensive with no payback on performance or anything.
In short, these are the ways of STUPID. Now we will move to SOLID and it would be easier to understand and relate those principles with these basic design and code issues in mind.