wtorek, 11 sierpnia 2015

The Clean Code Trap

   Often times instead of just smoothly bashing away at the keyboard to produce fresh lines of code I hit the creative block. I sit in front of the screen with one thought in my mind "this isn't clean... I can't do that". After dozens of such incidents I've came to agree with one obvious conclusion: making the software work is the main goal, following principles and patterns is just a tool.

Important Distinction

   Clean Code is mostly about how easy it is to change or add new features, how easy it is to understand by a human being and how easy it is to test it.

   Clean Code isn't about following all the principles, SOLID, patterns and other hard rules you've read over the course of your career. These are just all optional tools, that may help you in making your code cleaner.

The Cost of Principles

   Every time you constraint your code to a principle or a pattern, you make a tradeoff. By making your code more abstract, easy to change or test you're making it more complex, add more classes, interfaces and indirection - it makes it harder to read and grasp by a human being.

   The hard task of Object Oriented Design is to find the golden mean to all that. It's hard, but there are a lot of rules of thumbs for each pattern that you can follow and one general I've come up with:

Don't let patterns create code, let the code create the patterns.

   Don't make the code and constantly look for occasions to force a pattern in. Don't create patterns just for the sake of creating patterns. Familiarize yourself with all the principles, all their pros and cons, know them by heart, and while creating code the need to use one will come naturally.

   Each pattern is a mean to some end, you have to ask yourself and find hard reasons to use one each time. It works similarly with anti-patterns: when you have a need to use one, but just battle with yourself because you know you shouldn't, ask yourself why shouldn't I use one in context of my code. Here are some examples:

I Feel Bad When I...

  • Downcast - Using downcasting is said to be a code-smell - a bad OOP design. "You should use polymorphism instead". Don't be afraid to use it! It's there for a reason. If you can't find another way, or just feel it's natural to do it in your context, just do it.
     
  • Use Singletons - It's thought to be an anti-pattern by many. I don't like it, but sometimes it just saves you a lot of hassle, dependency injection, delegating etc.
     
  • Use Static Classes/Methods - You can't test them, you can inject them, but they're the easier way to use utility methods.
     
  • Use Magic Strings/Numbers - My rule of thumb is: I create a constant for a magic/number string mostly when a) it's unclear what it is b) it's duplicated in the code. Don't be afraid to write Object.Height = 0; if it makes sense to you - all programmers know what it means.
     
  • Don't create interfaces for each dependency - It's reasoned, that we need to create an interface for each dependency, because it's the only way we can mock it in unit tests. For a lot of languages you can mock an object and it's behaviors without using an interface. For example, for Objective-C you use method swizzling and in Java you use reflection (implemented in Unit Test frameworks). It saves you a lot of time, complexity and you don't have 100 useless inteface files just for the sake of unit tests. It was such a relief when I deleted 15 protocols in my iOS project. You still need to pass concrete dependencies, but that's good.
     
  • Use Cross Cutting Concerns - If it doesn't bother you, that's fine! Getting rid of these is hard and usually bloats the code or makes you use libraries.
   When you hit a creative block, ask yourself: is it really that bad in the context of my code, or am I just being blocked by those stupid rules again? It's important to remember: these rules are easy to understand and apply in the void, out of context, but it turns out that it's a whole different thing when trying to apply on living software. Sometimes doing something which is deemed a bad thing in general, might be reasonable in your code.

   If you really, really feel you're doing something bad: just do it!!



Shia really wants you to do it
   Because you're here to make software for real people for the most part.Making it nicely is the second objective. Just do it and forget about it. Mark it as TODO if it makes you feel better

   Go take a walk, be with your loved ones and I guarantee you that you'll find the right way after you've stopped thinking about it :)

Bonus: Your Code Is Too SOLID