I feel like this just replaces one vague word "good" with a bunch of other vague words like "readable" and "maintainable".
Like of course, maintainable is good. But what makes code maintainable? When we're teaching new developers, what do we tell them to do to make their code maintainable? How do we distinguish between code that is maintainable, and code that is not maintainable? That's really the important thing; just knowing it should be "maintainable" doesn't particularly help.
And "readable" is even more complicated. Sure, there are some syntactic things that help readability—consistent indentation and spacing, good variable names, organized files, shorter lines. But beyond that it kinda breaks down. What makes a method readable? Well, probably a small number of lines, few branches, single purpose. That's good. But when you extend that to a codebase, you end up with code that you need to jump between a dozen methods to follow what happens in any given call. Is that readable? Or if you look at it from a class level, having a few methods where the whole chain of logic is in a single place is readable—but then you end up with giant god methods that do way too much. Is that readable? Presumably the balance is somewhere in the middle, but how do we recognize it? Just saying code should be "readable" doesn't really help.
Or "covered by automated tests"—definitely tests are helpful. Except for bad tests, which are harmful, and make fixing bugs or refactoring a painful process. So "covered by tests" can be good, or it can be bad, and adding the wrong tests can make your codebase worse. How do we distinguish between good tests and bad tests?
So I agree that the things mentioned are true about good code, but way too vague to help write better code.
But, see, "good" is just this word. It's hard to test.
"Readable", though, I can test simply by trying to read it. That is, I can test someone else's code by trying to read it. I can't test my own that way; as the author, I'm not qualified to read it for understandability, because I already understand it.
So in practice, this boils down to "Read each other's code. If you can't read it, say so. If they tell you they can't read your code, fix it." That is actually fairly simple to put into practice. It doesn't help you get it right the first time, but it shows you where you got it wrong, and tells you how to know when you've fixed it. That's a big step forward from "good".
What that means, though, is you can only determine if code is readable after it's written, and read by other people. And I agree with you. But that also means that, while you're writing code, or thinking about the code you're going to write, or trying to decide between two possibilities, 'readability' doesn't mean anything. So you can't use it to guide you towards more readable code; instead it can merely be used to decide which code should be replaced / refactored / rewritten. And you can't use it to teach new developers how to write better code.
> And you can't use it to teach new developers how to write better code.
Yes, you can. New dev writes code. It gets code reviewed. New dev gets told: "That's ugly/too complicated/hard to understand. Here's some suggestions for how to re-write it." Over a few years, new dev learns what not to do (which is about the same as developing a sense of taste, or learning a style).
It's not something that can be put into a one-hour training class, though...
It's harder in practice than you make it out to be. Because our insecurity hinders our ability to say "your code is too complicated for me to understand".
Plus, some code is supposed to be more complicated than others, you can't always solve difficult problems with simple solutions. So unless you can understand the code and come up with a simpler solution, just complaining that it's too complicated is not gonna help anyone.
I cannot upvote this more than once, so I feel obligated to let you know how much I agree with this.
"Readability" may be a personal thing, but you'll reach convergence pretty quickly by following the approach you outlined. I see it as no different to something like writing, in that respect, in that an editor and a writer begin to converge on a style together without really setting out in the first place to do so.
I think you underestimate the value of culture in code quality (or any operational quality for that matter).
More vague words can certainly help, when coupled with a culture where regular discussion of key values is part of operations.
So that's still vague: Suppose you have management that says, "We only want and reward 'good code'. And we think 'good code' at least consists of 'readable', 'testable' and 'maintainable' code. The rest, my dear operations, is up to you and your team. And you know what, please a Powerpoint a month about how you measure metrics based upon those vague words. But hey, make the measures durable, and don't try and fool us with 90%+ scores from the get-go."
The hope would then be that even 'vague' words can empower the team to measure and improve upon their own interpretation of those words. That could be different from team to team, from company to company. But at least it puts quality in the forefront and that place in the organization where it matters and is measurable / improvable.
This is why I also find it a good question for recruiting. People who only want results, but feel all time documenting is time lost, will give answers reflecting that. It might be an OK attitude, even winning in some circumstances, but would not fit in a quality-central culture.
What about developers experience? Would a 2 year experienced developer ever call a 30 years experienced developers code 'readable', 'maintainble', (add more buzzwords)? Probably not. The older developer may use constructs that the younger has never heard of. If the consequence is, use simple code that everybody can understand, then we never use all of our potential.
My hunch is, it is crucial to keep developers and avoid situations where you have to maintain other peoples code as much as possible.
Just a quick idea, as I was writing this:
Lets compare software with fiction: assume, an author has written a quick draft for a story. It works great, it has more potential, some parts still don't fit in.
Would you honestly take the story away from the author and give it to a handful of others to finish it and turn it into a bestseller? It is likely, that you get a mix of styles that gets worse and worse, the more people touch it.
An author can give a book to different people for proofreading, copyediting, and substantive line Editing.
Some of the "voice" of the author might indeed be lost just because good copy editing normally is about 20% of a draft , but it could be argued that what's left is better for it.
I agree though that one should try to keep the overall tone/style the same
This procedure is called code review in software development. If done right, it can add great value to code especially, if the author has the last word and we coders develop the gentleness of the best fiction editors.
I've always felt that it's a fools errand to define things like that. Certainly things like "readability" are completely community/language centric, it would seem. I wonder if this post presents enough focus for respective communities (both languages and workplaces) to converge on their own definition of these things.
I'm always surprised that "It works." is not #1 on these lists.
I get that as developers, it really matters quite a lot whether the code is good. But on a higher business level, software development is a tool, and the most important thing to the business is that it works. Working well and making it better and more efficient are incremental improvements to the business... but code that doesn't work is a deal breaker.
Beautiful readable, testable, maintainable code that fails to meet the business need is still a failure.
It's easier to make Beautiful readable, testable, maintainable code that fails to meet the business need into working code than it is to turn ugly, unreadable, untested, unmaintainable (but working) code to a state where it's not a tragedy waiting to happen.
Edit, in a less snarky tone:
If beautiful, readable, testable maintainable code is buggy, I'd bet money on the project being structurally sound, but the developer having failed to understand something about the business requirements. It'll likely take a little while to get familiarised with the structure of the code, and then some more time to identify (and fix) the parts of the business logic that are not working as expected.
Ugly, unreadable, untested, unmaintainable code that "works" usually doesn't actually work, not really anyhow. It works fine for the cases that make the bulk of day-to-day work, but is almost certainly going to fail horribly when you hit an unusual corner case, and fixing that corner case is going to be a pain, because the lack of structure and testing is going to make it really easy to accidentally break something, and really hard to identify that this has happened (and why).
I'm conflating them because, in my experience, they're not independent. There are, of course, plenty of exceptions, but those characteristics tend to go hand-in-hand.
It's also often the case that what superficially looks like "ugly reliable code" actually means code that was, at one point, very simple and tidy but has been battle-hardened by years of maintenance. It's ugly because code that implements a lot of complexity tends to look scary as hell.
Finally, it's ultimately a truism: truly unreadable code is also code that's hard to modify, and very few systems will go through their lifetime without changes. Even if it works fine today, it'll not meet business requirements tomorrow, and its unmaintainability is a liability.
It's on this list as "does well what is intended to do". In fact the article specifically discusses the fact that people, when surveyed, did not mention "it works" as a priority:
Works: writing code should always have one purpose, deliver some value to somebody. Writing code that works, that it’s actually deployed somewhere making somebody happy is one of our top priorities. So we were kind of surprised every time a developer didn't include that item in the answer.
I guess it depends on the work the code is supposed to do. There's the proximate business problem for which the code provides an answer and then there are all the other business problems which a piece of code might create despite solving the proximate business problem.
There's a business case for optimizing on each...and one for everything in between.
I think your point goes without saying, code that actually works is the first thing.
But a dimension you've missed... Code that works but isn't readable, testable, maintainable, will end up costing your business dearly. It's a nightmare for any developer working on any task - finding a bug, iterating, new feature, whatever - to have to work with a shitty code base. You could quantify the losses in $ stemming from having to work with shitty code... not only that but you'll have a lot more trouble finding technical help (I'm not alone that I'll ask in an interview "What's your technical debt like?", if the answer is bad, that's probably the end of the interview.)
My definition is another: "Great code contains maximum entropy towards to its purpose while being easily understandable and maintainable."
Each part is interconnected to ensure quality and efficiency:
1. Maximum entropy means that your codebase should contain as much concentrated "information" as possible in relation to its size. Free of copy & paste code and repetitions that can be reused in libraries, methods and classes. This ensures less code to maintain , easier to spot bugs and easier to spot patterns.
2. Understandability (that includes readable): That means no blob classes or methods with an infinite number of purposes. Each layer of abstraction simple enough to keep in mind in its entirety.
3. Maintainable: It should be bug resistant, making it hard to do the wrong things and easy to do the right (for example putting required parameters into constructors rather than fields or properties). You should be able to replace and/or modify individual parts without side effects. Having as little code as possible also helps with this.
I think "covered by automated" tests are nice ... in some cases. It is far from a rule that they're a panacea for every kind of project, code and/or situation nor are all kinds of code wort the effort (models & algorithms: yes, UI: usually no). It also depends on the team and methodology.
That good code does what its suppose to do and should be bug free should be a given :)
I think I get what you're saying with "maximum entropy", but it's the wrong term for what you're trying to express. Really unreadable, terse code is highly entropic, but it's not good code. If you use descriptive variable names, that decreases from the entropy of the code.
yes maximum entropy = high information density. When you compress a file it usually leds to higher entropy. I agree that being terse in itself isn't the primarily goal, that's why I said "while being" ie has to reach the understandability and maintainability criteria as well
If you think I'm using the term wrong I'd appreciate a reference, thanks
Is that in order of importance? I'd put readability above everything else. Compact code is nice but I'd rather have self-documenting code, even if it means several more lines of code added to the functions.
Its hard to put a clear hierarchy of importance since it's a rather fine balance. As you say going for maximum compactness makes it much less understandable (Regex anyone?). That's also why i used the term entropy rather than compactness.
It's not primarily the number of characters we're optimizing for but code as information dense and devoid of redundancies as possible.
I actually think you should be verbose to the point of building a DSL-like syntax for your solution to improve readability. Even for instance addint small properties and methods that simplifies reading. It's much easier to read
if (CanWrite && WillFitDisk)
than
if (File.Position != File.EOF && Disk.AvailableSpace > Buffer.Size)
Even if reusability of those small methods and properties aren't high
So I see it as "compact" as possible as long as you fulfill understandability and maintainability.
high entropy in information theory is as much information per unit as possible as I understand it, but I confess I had to look it up to make sure :) I think the confusion is from physics where entropy is more about disorder
There is this paper [1] by John McCarthy on what he calls Elaboration Tolerance:
Elaboration tolerance is the ability to accept changes to a person’s or a computer program’s representation of facts about a subject without having to start all over.
This could make a good definition of what is 'good code'.
"Second, because if you write good code chances are that the product you are building will be much better."
If "better" means anything related to user experience, adoption or commercial success I think that correlation is about zero. Even the dumbest idea can be implemented by good code.
I would have expected better to mean, in this circumstance, less likelihood of there being issues that impact the user - something that almost certainly has a correlation! No amount of "good practice" will protect again an idea being rubbish.
I'm not surprised readable is so highly ranked, nor do I disagree that it should be. I am however somewhat surprised that SOLID doesn't have a higher representation. I find that in general, as long as you keep code clarity and readability sacred, you can write testable code by following the SOLID principles. Seems to me it provides the basis of 'good code'.
Their team page at https://www.intenthq.com/about-intent/ looks like a classic British social class structure; the people-people, so-called "movers and shakers" at the top, the mere techies all scurrying around on the bottom rungs, and QA almost falling off them. Even the office admin is presented above all the technical people.
Anyway, negative, small-minded and snide observations aside, here's my totally unscientific summary of their completely scientific survey:
Readable
Simple (as in not entwined)
Functional/Verifiable
Maleable/Maintainable
Composable/Reusable
Efficient
But of course all of these aspects are also very subjective.
Great code is mostly pure, dense, defines clean interfaces, and favors composition and reuse. Maintenance, testability , readability etc. are just side effects of well written code.
That is a very good point. Surprisingly, it didn't even made in top 50. But, I guess the intent here was to capture what developers think is a good code aesthetic, apparently the sample set of the survey do not feel a happy user is one of it.
I think that is the most telling aspect of this article: developers are cult unto themselves. The user is, seemingly, secondary to the purpose of writing code in many cases ..
Well is it scientific or pseudo-scientific? In all seriousness, I assume when you ask someone what makes good code, they will assume the code is correct already.
I don't think the post wants to be scientific and stands at the beginning to be pseudo-scientific (actually, aren't all investigations based on methods like surveys or questionnaires pseudo-scientific by definition?).
On the other hand it also says:
"To be fair, it’s also true that some of the developers had given that for granted (or at least that’s what they said when asked) but it can be symptom of some underlying problem."
So it's true that most of the developers asked assumed that the code was correct already but, in my experience, I've also seen in some cases (too many) that some developers believe that they are above everything and they don't worry enough about the value that the code should delivere.
I think it's the same symptom as the "throw over the wall" problem. Some developers tend not to worry about anything that is not coding.
Pseudo-scientific, since it offers no way to determine if a piece of code meets their requirements. "Readable", "Maintainable", etc., have no a priori meaning.
OT: I need a css style editor that is point-and-click (or copy-and-click) simple. (I currently use Stylish.) I need something that lets me select a paragraph, adjust a style, and it automagically adjusts the class/id style for the page. This light text stuff blows- and unfortunately it kind of biases me against his ability to determine "readabilty" even though that is completely unfair.
I would define good as
Fit for purpose,
Maintainable, and id judge this primarily by SOLID
Tested, prefferably TDD aor BDD
and finally not iver commented, good code should convey what it does without the need for comments, and as code evolves, comments rarely are updated.
Like of course, maintainable is good. But what makes code maintainable? When we're teaching new developers, what do we tell them to do to make their code maintainable? How do we distinguish between code that is maintainable, and code that is not maintainable? That's really the important thing; just knowing it should be "maintainable" doesn't particularly help.
And "readable" is even more complicated. Sure, there are some syntactic things that help readability—consistent indentation and spacing, good variable names, organized files, shorter lines. But beyond that it kinda breaks down. What makes a method readable? Well, probably a small number of lines, few branches, single purpose. That's good. But when you extend that to a codebase, you end up with code that you need to jump between a dozen methods to follow what happens in any given call. Is that readable? Or if you look at it from a class level, having a few methods where the whole chain of logic is in a single place is readable—but then you end up with giant god methods that do way too much. Is that readable? Presumably the balance is somewhere in the middle, but how do we recognize it? Just saying code should be "readable" doesn't really help.
Or "covered by automated tests"—definitely tests are helpful. Except for bad tests, which are harmful, and make fixing bugs or refactoring a painful process. So "covered by tests" can be good, or it can be bad, and adding the wrong tests can make your codebase worse. How do we distinguish between good tests and bad tests?
So I agree that the things mentioned are true about good code, but way too vague to help write better code.