posted by owen on 2016-Apr-23.
I see the issue of clean code mentioned quite often with no substantial examples. Programming theorists (mainly the web development kind) often propose "patterns" as a way to achieve quality code and choose to avoid talking about the bottomless pit of things that can cause an unsuccessful project. They prefer to spend thier time talking about unicorns instead of real problems facing programmers.
In my opinion the best code is no code at all. If you can't solve a problem with no code, at least try to solve it with as little code as possible. Each line of code is a possible bug, bottle neck, or creates extra work for the CPU. Web programmers are digging themselves into a hole. One should aim to have as little code as possible, less code, less bugs, code that is easy to replace with better code, and code that doesn't hide its meaning.
There is no way to avoid writing crap software. It is an imperfect medium, unless you have a robots.
There are also other considerations which I wrote about several years ago. But the main caveat is this; there is no such thing as "code quality", "clean code" or good quality code. Code quality is a made up term used to try understand why so many projects fail. The projects fail because they did not solve the client's problem OR fail to adapt to a changing environment. Programming is about solving problems, not stringing abstract classes together until you get bored and refactor the whole project.
Programming is dynamic - code is dynamic.
We should be encouraging new programmers to dive deep into new ways of solving problems instead of training them to use Java OOP patterns from 20 years ago. We need new ways to build rocketships, bigger, better, stronger. There ARE better WAYS (plural) to build software.
That said, lets look as a few misconceptions I have come across recently;
Polymorphism makes code simpler
Its quite the opposite polymorphism creates room for expanding abstractions that give room for logic bugs. In most cases all one needs is a list of items and not classes with slightly different bits of code. Data should not be replaced with classes that need to be juggled in memory. Hiding business logic inside a object model will only lead to long nights and missed deadlines. Programmers need to realise that modeling the physical world inside a computer is not necessary.
Simple versus Complex code
This is depends on the solution that the program is trying to solve. A complex program often requires a complex solution. Even if you apply a simple solution to complex problem the simple solution - should - eventually reach a level of equilibrium with the problem it is trying to solve. If you a see a simple solution to a complex problem - it is too good to be true - there is often hidden code or features are missing from the solution. One cannot avoid complexity or physics.
if you had a choice would you write "1+1=2" or "1++" or "New GenericNum = New OneNum.plus(New OneNum).ToNum()"?
Designing logic around classes
This is a growing problem in application design. There is a growing breed of OOP developers who think in terms of classes which results in bloated software that often never gets finished - video games locked at 30 FPS. If I have 200,000 bank account types YOU DO NOT NEED to create 200k classes to abstract each account type. IT MAKES NO SENSE. 200k classes that inherit from super classes will only result in an unmaintainable mess of spaghetti code and tests. Not to mention all your batch processes will be bottle necked by slow initialization code. Fast code is often more important than code structure especially in systems which require high throughput. How do we solve this problem? You create a system of rules - NOT A SEA OF MODELS.
If you have to use automated scripts to set up your environment then your tech stack might be too big. A big tech stack is like a big tree waiting for a small axe to cut it down. The first flaw in your stack will make your entire code base useless because it takes too much thought to set up. KISS. Less is more.
A common sign of an OOP developer who cannot adapt to separation of concerns. If you like building sand castles with on wet sand WITH wet sand then it will always get washed away. It is the same thing with code. A database is your friend stop fighting it.
DRY versus KISS versus Refactoring
People often talk about these things separately but they are interrelated. You will eventually realise that by trying to keep your code cohesive you end up creating complicated management systems inside systems (eating your own dog food). Developers often refactor simple pieces of code in order to not repeat themselves while making the entire system complicated - adding more and more code. Little functions everywhere that do little jobs. Classes with 30 methods are really one big method refactored into 29 sub methods that call each other in an invisible hierarchy.
So instead of creating simple consistent code they start making branching code and create bottlenecks - forks in the program.
Your client has 200k types of accounts but you realise that 100k of them are "similar" so you create a bottle neck class for those 100k account types. What ends up happening is that those 100k account types share common code and the moment that one of those types need to be unique you end up hacking a fork in the road so that you concrete an exception. It is like a magic little IF statement hidden in an interface.
Code that is easy to change versus easy to replace
These are not the same thing. One can create the most elaborate design that no one wants to change because the amount of code is too much for any one person to understand. Do not assume that you have job security. No matter how good your documentation is there is no way you can think of all the edge cases. Create code that solves problems but is not in the way of other programmers. Stop with the API shit. Make your code easy to replace.
Long functions versus Object soup
One stereotype is that long functions are bad. But what about an object soups? A long function will give room for abstraction and is often a very simple sequence. An object soup created to abstract a long function is really a system within a system. You start out with a sequence of tasks that are performed in order (aka long function) BUT then you decide abstract it away into multiple smaller classes that are detacted from its parent. This is bad because you've created a little system within a system. This system is running on a logic of its own. Its playing by its own rules that you have to think about independently of the rest of the program.
Code that is open for extension
This is another one of those code traps that appear in OOP code. You spend alot of time making your bad code extensible instead of keeping your code simple enough for all the programmers on your team to understand. News flash; no one wants to extend your bloated code. Do not put bottlenecks in your software for other people to extend - it is a waste of time. People with access to the full source code will modify your code to solve new problems as they arise. THEY WILL DEPRECATE YOUR ENTIRE CODEBASE IF THEY HAVE TO because it is easier and often cheaper than extending old code. You DONOT WANT a trail of dependences/extensions attached to a piece of code you wrote 10 years ago. Create a external API - internal APIs are dumb bottlenecks.
Being afraid to change your own code
I am not sure where this comes from. Maybe your code is a complicated mess with a million edge cases or it is a glass house but if you are afraid to change your own code it is a sign that you do not understand the design of the system/pattern you are modifying and you probably should study/test it a bit more before you change or add anything to it. Or have someone else look at it in detail. Maybe hire some testers or consultants. Extending bad code is only going to make it worse.
High cohesion and low coupling, how much code is too much?
So lets say you have 200k classes and you try to organise them using inheritance. Lecturers never dive into this black hole of what to do when you have lots and lots of code. They often talk about things in isolation like "in this case you do this" and "in this other case you do that". Lecturers do this because they do not want to focus on the real problem with inheritance - class organization. Why do I have 200k classes?
I have 200k classes because classes are maintainable.
I have 200k classes because they are easy for my project manager to read.
I have 200k classes because the client asked me to write them.
I have 200k classes because of TDD and abstraction.
I have 200k classes because I like complicated object trees and UMLs.
I have 200k classes because it gives me more lines of code.
I have 200k classes because maintaining a tree structure is fun and it makes me feel good about my self.
I have 200k classes because I am not sure what the future holds.
I have 200k classes because it helps me manage change and scope explosion.
In programming everything you do is for a reason. Some people are doing things for the wrong reasons.
This API is better than that API
All APIs are crap in some way. The bigger it is the more crap it is and it wastes developers time.
If youâ€™re overseeing a team of developers, my advice regarding coding standards is to let it be. If the people are any good, they make come up with a standard themselves, which they will then fully support. If theyâ€™re not that good, coding standards is the least of your problems. - Ferdy
There is no need to focus on "code quality". Write your code to solve. There will be all sorts of problems relating to teams, models and processing speed etc. There is no "right" way to "write" code. There are alot of bad solutions to problems and alot of ways to waste time. Understand how systems work and spend alot of time experimenting. Expanding your knowledge base is the best way to know what works and what doesn't in a given situation. Magic bullets do more harm than good.
So the next time someone talks about design patterns or code quality ask them to show you some good quality code that solves a problem. They wont be able to because they do not know the problem you are trying to solve. And even if you tell them the problem they won't be able to tell you what to do because they spend all their time thinking about code quality instead of solutions to problems.