Clean code: bad code
Feeling the code smell
What is bad code? Why we write bad code? Well Uncle Bob ask us many questions and then help us to understand how to improve gradually and start writing clean and maintainable code. We must learn to recognize bad code (code smell) and let us to update and improve existing code without breaking anything (refactoring). Let's start with some specific terms that will help us to understand and recognize bad code (or bad design). NOTE: every rules of clean code is valid for any modern programming language. Here we have all principles useful to recognize bad code. Rigidity: the inability to change or be changed to fit changed circumstances. The software is difficult to change. A small change causes a cascade of subsequent changes. This can happen if we have too many dependencies and too many parts, modules or areas are realated each other. Fragility
- The design is easy to break
- Changes cause cascading effects to many places
- The code breaks in unexpected places that have no conceptual relationship with the changed area
- Have no conceptual relationship with the changed area
- Fixing the problems causes new problems
- Telltale signs
- Some modules are constantly on the bug list
- Time is used finding bugs, not fixing them
- Programmers are reluctant to change anything in the code
Immobility \ non reusabiliy
- The design is hard to reuse and the code is so tangled that it is impossible to reuse anything.
- Telltale sign: a module could be reused but the effort and risk of separating it from the original environment is too high
Viscosity of the software
- changes or additions are easier to implement by doing the wrong thing
Viscosity of the environment
- the development environment is slow and inefficient
- high compile times, long feedback time in testing, laborious integration in a multi-team project
Needles complexity Design contains elements that are not currently useful
- too much anticipation of future needs
- developers try to protect themselves against probable future changes
- agile principles state that you should never anticipate future needs
Extra complexity is needed only when designing an application framework or customizable component Telltale sign: investing in uncertainty Needles repetition The same code appears over and over again, in slightly different forms
- are developers are missing an abstraction?
- bugs found in a repeating unit have to be fixed in every repetition
Telltale sign: overuse of cut-and-paste Opacity The tendency of a module to become more difficult to understand
- Every module gets more opaque over time
- A constant effort is needed to keep the code readable, easy to understand and communicate its design
Telltale sign: you are reluctant to fix somebody else’s code or even your own!
How to avoid all these troubles?
That's the big question. To avoid all these pitfalls, we must have control of our code to always see and know what's happening and what we can do to add new features and refactor the existing code. This can be easy for small projects but it can be very hard on a big project in the real world so must know how to proceed. The elements on the following list are techniques and concept we must learn and use to write clean code.
- Use OOP
- Learn and apply the S.O.L.I.D principles
- Learn and practice Test Driven Development (TDD)
- Design Patterns
- Learn Behaviour Driven Development
- Agile testing, 100% code coverage must be our aim
What about (big) projects with legacy code?
I've worked with whole and big platforms with legacy code and not a single line of tests! In the real world this is considered highly unprofessional; especially for a big company. It was terrible. All bad code principles and symptoms you have seen above become true and the everyday work soon becomes frustrating and slow. On the other side, it's impossible to start refactoring a large amount of code for many and some obvious reasons. So the Michael Feathers 's book working effectively with legacy code can help us. Essentially we isolate the legacy code parts and start building new features on top of the existing and working code! I'll come back on legacy code with more specific posts and examples.