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".

9
  • 12
    Bob Martin wrote a book about it. May 30, 2013 at 3: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, 2013 at 4:55
  • 1
    Joel spolsky blogged it here : joelonsoftware.com/articles/Wrong.html
    – Rudy
    May 30, 2013 at 6:43
  • 3
    Why not ask the developer that called your code "ugly"?
    – Bernard
    May 30, 2013 at 7:45
  • 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, 2013 at 9:45

9 Answers 9

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.

15
  • 1
    +1. Might add "robust to change" or "Not fragile".....otherwise it wont be clean for long.....
    – mattnz
    May 30, 2013 at 4:40
  • I think flexible architecture covers that. May 30, 2013 at 4:43
  • 2
    I don't think complexity belongs here - some problems are computationally heavy, but that doesn't make them unclean.
    – kba
    May 30, 2013 at 5:02
  • 3
    @kba: Cyclomatic complexity. Many algorithms can be simplified and still perform the same function, by refactoring. I also included the word "relative." May 30, 2013 at 5:59
  • 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, 2013 at 11:39
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.

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'

2
  • 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, 2013 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, 2013 at 14:04
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.
8
  • 1
    Comments require 50 reputation. In the meantime, please post real answers. May 30, 2013 at 3:25
  • 1
    Sorry. Will be careful next time.
    – Nabil
    May 30, 2013 at 3:26
  • 1
    That's not a problem I think, he is not asking for specific language. @Eric
    – Nabil
    May 30, 2013 at 3: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, 2013 at 9:05
  • 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! Nov 13, 2017 at 10:29
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.

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...)

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.

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.

Not the answer you're looking for? Browse other questions tagged or ask your own question.