20

I am an intern at a small software company, doing typical grunt work. Many tasks that the actual developers are doing are above my head however I finally got to see some real "action" and write some code myself. I will admit the task was perhaps a bit too difficult for me but I managed and my coded worked in the end. When my mentor was doing code-review he had said to me "Man, this part is ugly." When I said, "Why? Is something wrong with it?" he replied, "No, the code works, but it's just not clean code." The concept of of clean code is one I have run across a few times before, especially now since that I get to hang around professional developers. But what exactly is it that makes code "clean"? In other words what is the criteria?

I have heard in formal mathematics, a "beautiful" proof, is one that is ideally as clear and as short as possible and uses creative techniques. Many people know that in literature, "good" literature is one that can express feelings effortlessly and elegantly to the extent that one can "feel" it. But one can't "feel" code (at least I can't) and I think most would agree that short code is not necessarily the best (as it could be very inefficient) or even that the most efficient way is always preferred (as it could be very long and complex). So, what is it! Please, try to enlighten me to just what exactly makes code "clean".

yannis
  • 39,547
  • 40
  • 183
  • 216
Eric
  • 502
  • 4
  • 10
  • 12
    Bob Martin [wrote a book about it](http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882). – Robert Harvey May 30 '13 at 03:17
  • 9
    Such feedback without additional explanations from _mentor_ is surprising. In my understanding this role includes explaining what is clean/unclean code and how to write cleaner code. – maxim1000 May 30 '13 at 04:55
  • 1
    Joel spolsky blogged it here : http://www.joelonsoftware.com/articles/Wrong.html – Rudy May 30 '13 at 06:43
  • 3
    Why not ask the developer that called your code "ugly"? – Bernard May 30 '13 at 07:45
  • @Eric The most efficient code is not the first ideal of code. The first ideal is correctness. The second ideal of code is not efficiency. It is repeatability, or stability: can I expect the same kind of result every time. If it can do those two things, then other goals or values are possible, but efficiency may not even be third overall on that list of goals. Readability, maintainability, transportability, or others may come before optimization or efficiency [to execute]. – JustinC May 30 '13 at 09:17
  • 3
    In my experience a mentor saying something like "Man, this part is ugly" isn't what i'd call mentoring and it's certainly not constructive. What he should have said is "We could maybe do it better by doing X, or moving X into a Helper class, etc, etc". Making snide and unhelpful comments about a piece of code during code review is not the sign of a good mentor. – crmpicco May 30 '13 at 09:45
  • Just today on dzone https://medium.com/on-coding/a70ca8382884 – deltree May 30 '13 at 13:01
  • Just wait for the first time you "feel" the code you're writing. It's euphoric. :) – asteri May 30 '13 at 13:16
  • @Bernard The OP did ask their mentor why the code was considered ugly. The answer was "it's just not clean code". – user May 30 '13 at 13:24

9 Answers9

34

In my estimation, clean code has the following characteristics:

  1. It is clear and easy to understand,
  2. It is loosely coupled,
  3. It has relatively low cyclomatic complexity,
  4. It has a sensible, flexible architecture,
  5. It is easily discoverable,
  6. It is well-designed and
  7. It is testable.

Note that these are all subjective, although principles like SOLID and practices like TDD can go a long way towards achieving these goals. Also note that, as with most software dynamics, they're not necessarily mutually compatible; there are always tradeoffs.

Also note that I didn't mention performance at all, because code that is highly performing is often the opposite of clean.

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
  • 1
    +1. Might add "robust to change" or "Not fragile".....otherwise it wont be clean for long..... – mattnz May 30 '13 at 04:40
  • I think flexible architecture covers that. – Charles Sprayberry May 30 '13 at 04:43
  • 2
    I don't think complexity belongs here - some problems are computationally heavy, but that doesn't make them unclean. – kba May 30 '13 at 05:02
  • 3
    @kba: [Cyclomatic complexity](http://en.wikipedia.org/wiki/Cyclomatic_complexity). Many algorithms can be simplified and still perform the same function, by refactoring. I also included the word "relative." – Robert Harvey May 30 '13 at 05:59
  • @kba With abstraction, clean code can hide those ugly, complex details that are 'essential' to programming as Fredrick Brooks, Jr. would say. – Despertar May 30 '13 at 07:09
  • I think I might remove well-designed from your list as it seems to be somewhat begging the question – jk. May 30 '13 at 08:07
  • My boss thinks, that clean code is when we use paradigms, which we don't need... when we define functions each 4 lines of code... and when all use the language which noone know just because everyone around use it... damn. – Nakilon May 30 '13 at 08:08
  • @Nakilon Many very short functions are often far better than even a few longer ones. The shorter a function is, without losing expressiveness and meaning, the better. Ideal functions would be zero parameters, one expression, and one return path. – JustinC May 30 '13 at 08:55
  • @Nakilon: clean code is language-agnostic. And if you use a language which everyone around you uses, too, there seem to be a lot of people knowing the language - so your bosses *"which noone knows"* does not make sense. – Doc Brown May 30 '13 at 10:01
  • One thing is missing from your answer: The code must be well documented. It doesn't have to be lengthy, but the comments must clearly explain (a) what each function is doing, and (b) the purpose and reasoning behind any complex or unusual code. Another point to bear in mind is that functions should be well-delineated; avoid using one function to perform two tasks, as that reduces maintainability. Aim to make it possible to "remove" a buggy function and replace it with a working one, without changing any other code. – Paddy Landau May 30 '13 at 10:10
  • 1
    That's a good description of the notion of clean code. Anyway, during a code peer-review as described in the question, using such a subjective and imprecise qualifier should be avoided. If your colleage think you code is ugly, he should be able to tell why. – MatthieuW May 30 '13 at 11:39
  • @mattnz 1,2,3 and 7 asures the code is robust to change and not fragile. That's why robust and not fragile are nor mentioned here. 1,2,3 and 7 take the subjetivity out of robust. – Tulains Córdova May 30 '13 at 12:34
  • @PaddyLandau: I didn't include documentation (even though it is important) because it is not code, and the cleaner the code is, the less documentation it should need. – Robert Harvey May 30 '13 at 14:49
  • @DocBrown, they don't know (neither language specific features, nor standart libs, nor language specific paradigms), but use it. That's the point. – Nakilon May 30 '13 at 16:55
  • @RobertHarvey occasionally, I have a very high cyclomatic complexity due to use of a pattern matching DSL that I wrote for the domain. The lambdas that make up the cases are aggregated into the overall complexity by the analysis tools. However, I found that the alternatives were far less readable. – Aluan Haddad Nov 13 '17 at 08:52
13

I think Robert Harvey has a great answer but I'd like to expand on what I believe is the most important part:

  1. It is clear and easy to understand

A lot goes into writing good code. But later on we'll find that we spend as much or more time reading code then we do writing it. Writing clear, easy to understand code is critically important to the concept of clean code because ultimately it makes all that time we spend reading easier and less time consuming.

  1. It should be well formatted. Pick standards and be consistent. Look around at other style guides in the language of your choice. Pick what works best for you or your team, document it and be consistent.

  2. Class names, member names, variable names should be expressive and descriptive of what they're doing. Avoid meaningless names. Naming really is one of the hardest things to get right in programming and often will be specific to the domain that you're working in.

  3. Keep it short. The guy/girl reading your code doesn't want to read a novel. They want to understand how functionality works or how you solved a problem. Make that clear to them. Abstract small pieces of functionality into expressive methods and build a short, descriptive "story" for them on how the bigger piece works.


A lot of things goes into writing clean code. But, in my opinion, making it clear and easy to understand is the single most important thing you can do.

Also read Robert Martin's book.

Charles Sprayberry
  • 1,606
  • 1
  • 12
  • 21
2

My answer is not as constructive as Robert Harvey's answer. But I can add some options which I am using during development. Considering performance issues some of them should avoid or remove when publishing in real world.

  1. Use comments in your code. Maybe several supervisors may have to look upon your work after your coding.
  2. Use meaningful words for variables, functions, and methods. Not just a, b, c, etc.
  3. Avoid using several whitespaces between code. It's annoying.
  4. Lines of code should be in a sequence. It makes code more readable.
Peter Mortensen
  • 1,050
  • 2
  • 12
  • 14
Nabil
  • 139
  • 4
  • 1
    Comments require 50 reputation. In the meantime, please post real answers. – Robert Harvey May 30 '13 at 03:25
  • 1
    Sorry. Will be careful next time. – Nabil May 30 '13 at 03:26
  • One of those is on HTML. Those are nice suggestions, but many of those are not code-agnostic and deal with style, not content. – Eric May 30 '13 at 03:26
  • 1
    That's not a problem I think, he is not asking for specific language. @Eric – Nabil May 30 '13 at 03:27
  • 1
    @NewBil Code should be expressive enough that it is easy to understand without comments. If you need a comment to communicate the intent or consequence, often the code should be rewritten in a way that would eliminate the need for the comment. And consistent whitespace is helpful for creating readable space and delineation of one section to another. Or by working with the other aspect of whitespace use, density, and compressing very closely related lines together. – JustinC May 30 '13 at 09:05
  • @JustinC Many people argue about comment, but I think comment makes a code more readable. For a section of code one line of comment is a summary, so that reader can understand what is going to be in next. And here I agree that consistent whitespace is helpful and I support it. But from my experience I saw some people use several unnecessary whitespaces(I don't know why) that makes code fragile. I said to take care of this. – Nabil May 30 '13 at 09:16
  • What do you mean by *"Avoid using several whitespaces between code"*? An empty line between every line of code? – Peter Mortensen Nov 12 '17 at 21:18
  • 1
    @PeterMortensen pretty much every beginner/junior dev I've come across has gone through a phase of adding 4+ empty lines between functions or just randomly throughout the code. Good devs separate concerns and concepts using methods/classes, beginner devs use whitespace, and bad devs do nothing! – GoatInTheMachine Nov 13 '17 at 10:29
2

Additionally to other answers, there can be actual ways to feel about code. By feel, I mean instinctively interact with code.

First, the formatting of the code itself can be easier for people to read and understand using some basic principles that help us read the code. Gestalt Principles can help anything be more quickly and easily understood by humans (applied heavily in data visualization). Using these principles for simple things like aligning comments, placing spaces and blank lines in the right place all help people read code more easily at an instinctive level.

A lot of my coding conventions and formatting is based on making it easier to read first at a subconscious level.

Which feels more readable?

int x; //This is an x
string foo; //Foo here
MyObject baz; //Instance of MyObject

int x;        //This is an x
string foo;   //Foo here
MyObject baz; //Instance of MyObject

EDIT

To Michael's comment about having a long declaration. Our minds are forgiving, so the laws don't have to be followed exactly.

int x;        //This is an x
string foo;   //Foo here
MyObject baz; //Instance of MyObject
MyTypeWithSomeAwfullyLongName bar;
long UUID;    //The Law can be broken and still help

The Law of Proximity should mean most people like the second version better. It's the same reason we have columns and tables to organize data.

Another example, based on the Law of Symmetry

function fooBarLongMethodName() {
    return null;
}

function fooBarLongMethodName()
{
    return null;
}

The law of symmetry states that the mind perceives objects as being symmetrical and forming around a center point. It is perceptually pleasing to divide objects into an even number of symmetrical parts.

So it is more pleasing for the mind to see the symmetry in the second example, being able to see both the open and close braces in line.

These examples should instinctively make reading code easier. But there are also learned patterns that it takes time for you to take advantage of, these are based on the Law of Past Experience.

So secondly, understanding the intent of certain code, and knowing when it's being used incorrectly (especially without having to investigate or know much about previous code). This article talks about naming variables so that you can see from the names when they're are being used incorrectly. Once this pattern of naming and use have become habitual, it's possible to recognize an issue with the code by site and without having to investigate much of the other code.

Finally, these lead into a larger idea of Code Smells. The idea that certain patterns that emerge in code can commonly signal an issue somewhere in the code. This sometimes shows up as a sentiment "This unit testing code is ugly, why is it even necessary?" and the answer to that question is maybe "Oh, you're using Singletons for everything.". This is the hardest to teach or learn and probably only comes with experience.

So I hope this helps expand on the other answers as to why or how people can consider code 'beautiful', 'good', or 'ugly'

CLo
  • 368
  • 1
  • 11
  • The problem with the second part of your variable declaration block is if you need to add `MyTypeWithSomeAwfullyLongName bar;`. Are you then going to edit each other declaration? (The person doing the following merge will love you for it.) If you select good variable names, the need for such comments generally disappears entirely. – user May 30 '13 at 13:30
  • @MichaelKjörling True, it was just a matter of finding a good example off the top of my head. Also, not really a hard rule, you can break it for just that one line and the law will still keep its effect. However, it does matter how often you break it, if a certain percentage of the lines are too long the effect will be lost. – CLo May 30 '13 at 14:04
1

I'll add a short answer on the importance of clean code, because it was only tangentially evoked in other answers.

"Clean code" is important, because during the total life of the product, or product line, you have maybe spent some weeks to write that module, but it will "live" for years or decades in your code base.

So maybe typically:

  • Time spent writing code: 10%
  • Time spent maintaining code: 90%

By writing clean code, you are easing the work of people who are going to have to review and update it in five years. And in some cases, that person will be you!

(I have already found myself wondering "Would wrote that code?" and by checking in the version control system, it was actually me a few years before...)

Peter Mortensen
  • 1,050
  • 2
  • 12
  • 14
Xavier T.
  • 1,612
  • 13
  • 15
1

I noticed several answers here touch on style/layout, i.e. cosmetics of code. I think that there is a distinction to be drawn between code that is clean and code that is tidy. Ideally you have both, but the first is more important.

As an analogy I might decide to tidy up my kitchen (stack the dishes away, rearrange, sort jars in the cupboards, etc.). The same with code - you can align the text, format, whitespace, naming conventions, breakdown into smaller files, etc.

None of that will mean your code will be clean - and when I cook later/compile my code I might still get a bug (stomach bug/segmentation fault, my analogy is holding well...)

You can kill bugs of course (boiling water, soap/a patch, a hack), but it is much better to avoid them entirely - that is to have clean code. So you design your kitchen to your needs, plenty of space, clear worktops/have a separate meat vs. vegetable chopping board, etc./nicely factored design, single responsibility principle, KISS, YAGNI, etc. The analogy breaks down, because I need my kitchen to be tidy before I can cook. Whereas you don't need tidy code to have it compile and work, as long as the design is clean.

It just means it takes a little longer for the average developer to navigate your kitchen/code and work out where everything is, but at least that is possible, but it is not possible for them to see a swathe of salmonella and E-coli on a kitchen surface. They can only trust that there isn't because you've got several obvious bottles of antibacterial spray in the cupboard under the sink where they would normally expect to find it/you designed your code in the canonical way for the problem it solves.

Now (an unadulterated opinion): inexperienced developers (it doesn't matter what their seniority is) get distracted by tidiness when they should be more concerned about dirt.

Peter Mortensen
  • 1,050
  • 2
  • 12
  • 14
Benedict
  • 1,047
  • 5
  • 12
0

As per me (and for most others) it fully depends on the readability of the code.

If I can read the code and understand it, it is clean or else it is not clean. Good naming and other things are of course important. But then unfortunately readability mainly depends upon a person's technical understanding in data structure or the programming language.

A simple example: Imagine that I wrote a program in C++. I was fascinated by the new features added in the C++11 standard, and I wrote my program using functional programming. So all the loops and iterations over the containers, I replaced by accumulate (reduce, fold), transform (map), any (filter), currying, etc.

Now this program is clean and concise for anyone who knows the concepts and the language features. Unfortunately those who are new or do not even heard about functional programming, are going to struggle. They will say that the code unnecessarily use the confused APIs, and complex to understand. These things can be done using loops, which is more clear and clean. They are still right as where they stand, but the code is actually better. Hence the readability and cleanness depends upon the individual.

Peter Mortensen
  • 1,050
  • 2
  • 12
  • 14
Manoj R
  • 4,076
  • 22
  • 30
0

If you are wondering what all these means practically, well for a change from academic programming, you would need to have meaningful variables and function names firstly.

Secondly, your codes needs to be organised such that it is easy to follow. That is you need to understand code separation (understand why people likes MVCs), you need to put functional things in models and in view have only things which will be used for the frontend and Controller to plug them all in. So that if a person comes to read your code these separation will actually help them focus on the bit they want for quick update etc.

Thirdly, you also need to be organised at modular level, you shouldn't have functions for example ticketing algorithm in some other module like payroll or accounts etc. You should also design modules in a way that if you can easily remove the module and the system should still work without its functionalities (also that means you can easily plug in modules as well).

Finally, also a good practise I think to keep helper functions separate from all modules so that they can be called from anywhere.

I should also have a look at different design patterns and learn how to use them as they do help your codes to be more organised and manageable.

0

You may already read (or not) about S.O.L.I.D. patterns. But I expect such question requires more specific answer. Please take a look at Doom 3 Source code review. Even you are not familiar with the game development you still can understand the code. In my opinion, it is an example of the Clean code.

Disciple
  • 643
  • 6
  • 13