DEV Community

Cover image for What is bad code?
stereobooster
stereobooster

Posted on • Edited on

What is bad code?

Seems to be an obvious question, but I haven't seen one authoritative answer to this. People can have opinions about code quality for sure, or people can use phrases like "Bad code is bad code, whether it compiles or not." (from this article).

But can we define what is bad code? Can we all agree on that one definition?

I guess this definition will change over time. Shall we make a committee which will publish a new definition every year?

What I'm trying to say is that this is not a trivial problem to decide if this code is bad or is good, the same way as it is hard to say if this is the best chess move or not (I can give you an answer, but how you gonna know it is true, it is hard to test).

It is possible to identify some parameters of code, like LoC, coverage by tests.

Other parameters are harder, for example, readability. Readability depends on the reader.

We - developers like to throw around those terms like 10x programmer, bad code, etc. But in practice those terms like mythical creatures. Everybody has different ideas, sometimes definition is "I know it when I see it".

How we suppose to have constructive discussion throwing those ambiguous terms around.

Photo by Maria Teneva on Unsplash

Top comments (48)

Collapse
 
bradtaniguchi profile image
Brad

Like most things in life, I'd say the real answer is purely relative.

I believe the most important thing to know isn't if it's bad or good, its can it be made better?

The reason why there is no set rule for "perfect code", or "bad code" is its all relative. There are some red flags, and code smells, but I'm sure there are cases where these rules are to be broken. 😉

I believe all code could be improved. To believe all code is bad is a way you can go about improving yourself and code, rather than considering things black and white.

Collapse
 
stereobooster profile image
stereobooster

is its all relative

👍

But this means that you can't just throw around this phrase without specifying what exactly you want to say. There is no single definition of bad code everybody agrees on...

all code is bad

The best code is no code.

Collapse
 
bootcode profile image
Robin Palotai

I agree that it's mostly relative and purpose-determined, though everyone develops some personal aesthetic sense over time.

Gerald Weinberg writes in his timeless piece The Psychology of Computer Programming that an objective question to ask is if the code lives up to the requirements.

Collapse
 
anwar_nairi profile image
Anwar

About your last link, this issue made me lmfao: github.com/kelseyhightower/nocode/.... Plenty more like this one in the issues!

Collapse
 
purepandemonium profile image
Joshua Morgan

Any definition that a lot of developers can all agree with is going to be pretty general. I'd define bad code in light of what ideal good code is.

  • Good code does what it's supposed to. Bad code doesn't do what it's supposed to.
  • Good code is easy to read and maintain. Bad code is difficult for your successor (or yourself) to read and modify.
  • Reading good code can be surprising, whether it teaches you a new concept or has an elegant solution. Mostly it's obvious and straightforward to the point of being boring. Reading bad code can be surprising and holds your interest with pitfalls and unexpected behavior.
  • Good code uses the right tool for the job and makes it clear the developer is "thinking in" that language and its strengths. Bad code disregards the standards and solves problems with a club (e.g. loops and complicated flow control in your routine SQL queries is a bad sign).

Readability is a tricky one, because it depends so much on the context and the reader. A novice will have a hard time following very dense code written to solve a difficult problem, but that doesn't automatically mean it's bad code.

Maybe this question of definitions is missing a piece. The more complete question might ask "bad code for what?" Without context or a stated purpose, it's not fair to judge code in a vacuum.

There's a lot of code written for code golf. It's largely impenetrable and undocumented and probably doesn't even solve a real problem! Does that mean it's bad? Because I think it's beautiful and clever and perfectly suited to the situation.

And any written definition for judging good code from bad is going to be either so general or so contentious as to be useless without taking context into account.

So, my definition of bad code? It depends.

O Rly Books: It Depends

Collapse
 
stereobooster profile image
stereobooster

I like your response. I will question parts of it to make it even better

Good code does what it's supposed to.

But how to know what it suppose to do? We can write specification, but typical software specifications are partials, they are not formal specifications. Not a lot of people write models and check it with TLA+, right?

It can be quite expensive to write the specification. And this is hard to write full specification if you don't know full requirements, if your business needs to response to market changes.

The second part it is quite hard to verify that software is working according to the specification, we can prove that some portion of software confirms to some portion of spec, but to prove it confirms 100% we need to use formal verification, which is hard and expensive.

Good code is easy to read and maintain

Readability. I agree. But this means we need to give definition for readability to accomplish definition of good/bad code.

Without context or a stated purpose, it's not fair to judge code in a vacuum.

💯this what frustrates me when people use this phrase in the context "bad code is bad". Bad for what? Maybe there were reasons for it?

Bad code can be replaced. If it can't be replaced, problem not in the code, but in communication - nobody took time to write down all requirements in any other form rather than code, and nobody can reverse engineer this code. This is not a bad code problem, this is organisational problem.

Collapse
 
shiroihana013 profile image
ShiroiHana013

Oh man the point you made about good code being so elegant you learn from it. I started a new job as a software developer. The database was down for a week so I spent a week reading line by line the code. There are two parts to the code.

  1. Complex models written by non programmers.
  2. Refactored code for processing the models with multi-processing.

The refactored code was so easy to read and understand. I was able to learn from it.

Example using wrappers in Python to deserialize JSON files instead of manually decoding

I recently started debugging part of the models that haven't been refactored and it's so bad I don't think even the guy who wrote it knows what it is doing.

Collapse
 
stereobooster profile image
stereobooster

I recently started debugging part of the models that haven't been refactored and it's so bad I don't think even the guy who wrote it knows what it is doing.

But the question is your problem in the bad code itself or the fact that there is no other documentation of requirements rather than code itself? (Otherwise you can throw it away and rewrite from the scratch).

Do you know in which conditions this code was written?

  • Maybe it was first job of the person? Then poor quality is due to lack of mentorship and lack of code reviews (bad culture)
  • Maybe there was pressure from the management, which lead to the result (again bad culture)
Thread Thread
 
shiroihana013 profile image
ShiroiHana013

The first person who programmed it has a PhD in statistics and has little to no background in programming. The "documentation" I have to compare it against is an Excel sheet with complex formulas. The logic in the Excel is completely different from the logic in the Python he wrote.

Collapse
 
codemouse92 profile image
Jason C. McDonald • Edited

Irrelevant P.S. I'm a so-so chess player myself, but I would think a chess grand master with a grasp of the underlying concepts of the game could quantifiably (rather than subjectively) define and explain whether "that chess move" is at least a candidate for best.

In any case, he could still whip my tail.

P.P.S. Apparently a single board position in chess is NOT NP-complete. (See also). Therefore, a "best move" is provable, at least in some cases.

Collapse
 
stereobooster profile image
stereobooster • Edited

NP complete problem is hard to solve but when you got the answer it is very easy to check. For example, factorisation of numbers, if I will give you number which is product of two very big prime numbers it will be hard for you to find which numbers are those, but if I will tell you at least one you will be able to check it immediately. So yes chess is not NP complete. (Link to the video I provided in the article says the same ¯\_(ツ)_/¯)

The link you provided mentions PSPACE. Here is comparison of NP-complete vs PSPACE-complete.

However, if that's not the lens you're looking through, then (based on the suspicion that NP ≠ PSPACE) there's a difference between NP-completeness and PSPACE-completeness. If a problem is NP-complete, then even if you can't solve the problem efficiently, you can still check "yes" answers efficiently. On the other hand, if NP ≠ PSPACE and you have an instance of a PSPACE-complete problem you're convinced has a "yes" answer, there might not be any efficient way to convince someone else of this.

-- What is practical difference between NP and PSPACE-complete?

This quote says basically the same. For NP-complete problem it is easy to confirm the correctness of answer for PSPACE-complete it is hard to "convince" the correctness of given answer.

Collapse
 
codemouse92 profile image
Jason C. McDonald • Edited

Thanks for your response. Good insight.

Based on my link and your comment, I'm still not certain that all that applies to a single board position, which has a very limited number, even a countable number, of possible moves. So, whether a move is the "best" is going to depend on your definition of "best" (there's that same pernicious relativity we keep hitting in regards to "bad code".)

If we're talking about "the move that is going to create the least immediate disadvantage" (minimizing the value of the pieces at risk of immediate loss), that's definitely P.

If we're talking about "in the context of the whole game", it would depend on the number of moves out from the end of the game, because (off the top of my head), the number of possibilities to be analyzed for, say, three moves from checkmate would be the possible moves for this turn times the possible moves for next turn, so on and so forth. (Not strictly calcuable, mind you, since the number of possible moves changes depending on the previous term. NP again.)

In other words, a chessmaster could easily explain whether a move is "best" in the context of endgame. That's not even remotely NP. I think that's precisely why there are entire books of endgames to study.

But the entire game of chess from the start is NP-hard (although not NP-complete, as I cited.)

Or to put that another way...

(In spooky voice) It depeeeeeeeeeeeeeends.

Thread Thread
 
stereobooster profile image
stereobooster

For anybody who reads this conversation and not sure what is NP-hard vs NP-complete:

This means that NP-hard problems might be in NP, or in a much higher complexity class, or they might not even be decidable problems. That's why people often say something like "NP-hard means at least as hard as NP" when trying to explain this stuff informally.

The halting problem is a good example of an NP-hard problem that's clearly not in NP

-- Trying to understand P vs NP vs NP Complete vs NP Hard

Thread Thread
 
stereobooster profile image
stereobooster • Edited

In other words, a chessmaster could easily explain whether a move is "best" in the context of endgame.

It makes a lot of sense from chess player point of view to study endgames and openings, but this logic doesn't apply to study of complexity. Talking about endgames is like comparing sort algorithms for almost sorted arrays. Nobody interested in that.

People are talking about big O notation (sometimes about big Theta). Right?

"It depends" applies to common knowledge, like subject of this article (what is bad code), but I don't think it applies to scientific or mathematical discussion. (Unless we are talking about philosophical interpretation, but we are not in that situation anyway).

To be fair I already lost the thread of conversation...

Thread Thread
 
codemouse92 profile image
Jason C. McDonald • Edited

Well, I don't want to lose context. I was referring to what you said in the article.

...the same way as it is hard to say if this is the best chess move or not (I can give you an answer, but how you gonna know it is true, it is hard to test).

There are some values of "best move" which can be quantifiably stated and proven. In the same way, there are some values of "good code" and "bad code" which can be quantifiably stated and proven. Just because the sum total is NP-hard or NP-complete doesn't mean that all parts therein are also NP.

In any case, thoroughly interesting conversation! Thanks.

P.S. "Almost sorted" actually does make for some interesting sorting algorithmic efficiency discussions. There are forms of "almost sorted" that actually bring out inefficiencies in certain sorting algorithms.

Thread Thread
 
stereobooster profile image
stereobooster • Edited

Yes, I know that this thread is addressed to my reference to chess. But what you try to say to me? This is how I see it:

  • Me: Post a link to the video which says that chess is outside of NP-complete field
  • You: Apparently chess is not NP-complete. Here is a link.
  • Me: Yes. Chess is not NP-complete, because... Your link mentions PSPACE-complete, the difference between PSPACE and NP is...
  • You: ...But this all depends, because for endgames situation is different...
  • Me: Yes, but we are talking about classes of complexity so we should compare worst cases ¯\_(ツ)_/¯

Where this going?

Thread Thread
 
codemouse92 profile image
Jason C. McDonald

The overarching point is, you said "you can't prove that X chess move is best." And I just proved that, actually, yes, you can in some cases.

Thread Thread
 
stereobooster profile image
stereobooster

I mean obviously in some case it is provable, like one move before checkmate. But I talked about general case, the same way as you talk about worst case in big O notation...

Thread Thread
 
codemouse92 profile image
Jason C. McDonald • Edited

Yes, and if we go alllllllllllll the way back to the original topic of the article, some "bad code" situations are provable. It is not entirely subjective.

And the chess analogy mirrors that.

Which is my point.

Thread Thread
 
stereobooster profile image
stereobooster • Edited

True like this one

A second pass on this. THIS is bad code because it is ambiguous to the reader.

8 / 2(2 + 2)

There's a big internet argument as to whether it's 1 or 16, and it is bad code because there are multiple justifiable results from it, and the next person to come on the code may have a different interpretation.



but to me this seems like outlier, rather than typical example
Thread Thread
 
codemouse92 profile image
Jason C. McDonald • Edited

I provided you an entire list of quantifiably "bad code" principles in my other comment. None of them are outliers, IME; I've yet to find a single contradiction to any of them in any discussion about coding practice. :)

Collapse
 
jacoby profile image
Dave Jacoby

All good code is alike; bad code is bad in its own way. -- Leo Tolstoy

The code I'm working with is bad in that I'm having to dig though hundreds of global of questionable necessity, and functions like modify_all_variables() that's ALL side-effects, so that it's hard to know what the behavior actually is, much less modify or replace it.

But there are many other ways to have bad code.

Collapse
 
stereobooster profile image
stereobooster • Edited

The quote 😂

A lot off side effects in one function, means that it is hard to "load" the code in the head, right?

. source

The lack of modularity and proper abstractions makes it hard to modify. Is it bad "editability" (inventing the word in the same vein as "readability")?

Collapse
 
jacoby profile image
Dave Jacoby

I always ❤ MonkeyUser.

I think there's more to it than that. For example I try to keep subroutines to where I can see everything they do in one screen, and while that used to be 24 rows by 80 columns (standard VT100 terminal size, back in the day), for VSCode on a HD monitor, I'm running 55x90 or so. Even fairly straightforward code can be hard to track if it's into the KLOCs without structure.

In my case, with modify_all_variables(), I don't know what's in it, I have once found where it is (I don't believe it's in the program at hand) and I would have been much happier to see var new_vals = modify_all_vars(old_vals), as this cuts the scope to what's being modified to new_vals and old_vals, giving me much less to fit into my head.

So, yes, I guess, although that "lost" feeling comes more when I'm very full-stack, leaping a lot from CSS to HTML to JS to backend code (in my case, Perl) to SQL to Bash and back and forth a lot. I swear, there have been days when I could not pull together a complete sentence after that bulldada, but this is less bad code than all eggs in my basket.

("Editability" has past usage at least as far as 2009, and while it may not be in Webster's, anyone who understands read -> readable -> readability should be able to get editability, so we should start lobbying the OED.)

Collapse
 
jacoby profile image
Dave Jacoby

A second pass on this. THIS is bad code because it is ambiguous to the reader.

8 / 2(2 + 2)

There's a big internet argument as to whether it's 1 or 16, and it is bad code because there are multiple justifiable results from it, and the next person to come on the code may have a different interpretation.

Collapse
 
curtisfenner profile image
Curtis Fenner • Edited

Bad code is code that costs more than it needs to.

Some of the ways that code costs us is when:
It's too slow/uses too many resources, it does the wrong thing, it's too hard to understand, it's too hard to change, or it's too hard to delete.

Code is bad code (and not merely solving a complex problem) when there is a way to (re)write it that would be faster, does the right thing, is easier to understand, is easier to change, and is easier to delete.

Collapse
 
stereobooster profile image
stereobooster

It's too slow/uses too many resources

Who cares if it still produce more money than it spends? (There are people which will ask this question)

it does the wrong thing

Assuming we know what the right thing is. I mean we can know some portion of requirements. The question is: which portion is it 20%, 50%, 80% (based on Pareto principle)? To makes sure software is doing 100% correct thing we need formal specification and verification, which is hard.

it's too hard to understand

I call this "bad readability" (I count how much people mention this in comments)

it's too hard to change, or it's too hard to delete

sounds reasonable

Collapse
 
codemouse92 profile image
Jason C. McDonald • Edited

There's a lot of great answers in the comments already, but for what it's worth, here's what I've observed:

I agree there's a lot of relativity to it. What is "good code" or "bad code" depends on your language, your paradigm(s) (object-oriented, procedural, functional, etc.), your project, your standards, and so on and so forth.

However, I think there are some common traits of bad code, including...

  • Lack of clarity. If someone who has a reasonable grasp on the language cannot discern what it does, there's a problem.

  • Lack of readability. Different languages are capable of different levels of readability (e.g. in general, COBOL source is not going to be as readable as Python, for example), so we have to compare apples to apples, but when style convention and consistent formatting are ignored, the code is going to be an eyesore.

  • Poor naming. x, foo, and xztoab tell us nothing about what the variable or function does. Use self-commenting code principles.

  • Lack of appropriate intent commenting. Without going into the entire debate about commenting, many programmers agree that if the programmer's intent for a block of code is unclear from the code itself, that's what a comment is for. (Comment WHY, never WHAT.)

  • Lack of proper structure. Regardless of what paradigm(s) you follow, there are structures that the code should be organized into. When this organization is lacking or misapplied, we get spaghetti code. (Also, see below.)

  • Lack of clear responsibility. I think the single-responsibility principle can be applied to most structures, regardless of paradigm. A function for writing to a file shouldn't also be the home of the network-checking code. An object for storing high scores shouldn't also contain sound volume settings.

  • Magic numbers. What is that 976 doing in the super important math calculation? We have no idea! Important (and otherwise seemingly arbitrary) numbers should generally be named, usually by assignment to a variable or constant.

Long story short: code should be well-structured and well-formatted (as appropriate to the language/paradigm), (therefore) readable, (therefore) maintainable.

We could, of course, go pretty deep into the principles of clean coding, DRY, SOLID, and the like, but the exact rules will depend on your language and paradigm. (And even then, they're not a magic bullet.)

Ironically, I think most programmers can agree on what very bad code is. We mainly start having difficulty agreeing when it comes to what good code is, and that (again) depends largely on the nature of your language and paradigm.

Collapse
 
michaelrice profile image
Michael Rice

I'd be surprised if you could get folks to agree on what bad code is, but there are Bob Martin's "code smells" that seem like a helpful start....

Collapse
 
stereobooster profile image
stereobooster

I would question opinions of this author after his latest comments

Collapse
 
darkes profile image
Victor Darkes

What has Bob Martin said that's been controversial?

Thread Thread
 
nyc4m profile image
Baptiste Prunot

Yeah I would like to know also

Collapse
 
michaelrice profile image
Michael Rice

Oh Uncle Bob? I'd totally forgotten he'd caused some controversy.....

Thread Thread
 
stereobooster profile image
stereobooster

Yes Uncle Bob. I didn't mean you, sorry for confusion.

Thread Thread
 
michaelrice profile image
Michael Rice

Haha - yeah - for just a second there you made me sweat 😅 wondering what my recent comments had been!! :-)

Collapse
 
anwar_nairi profile image
Anwar • Edited

I guess yes, it really depends. I remember this time I was working on my project and my lead dev said that this:

if type(users) is list:
  for user in users:
    ...

was not good code, and this:

if users:
  for user in users:
    ...

was better.

So first, I should say in my defense I come from another programming language than Python so this was not very intuitive for me (now I got used to it even if this is still weirdo).

So I guess everything is relative since we do not share the same standards, backgrounds, intentions, and objectives.

answer proposition

Only if we should give an absolute definition, I would say that a bad code is a code that does not cover the use cases. If we need an algorithm to do X,Y,Z in a context C, and it only does X,Y, or it does X,Y,Z in a context D, so it is a bad code for me.

Then, we could say what is a code that does X,Y,Z in a context C,D? Is this bad code because it does too much? I would have said no some months ago, but now that I have some issues with some codes that tried to anticipate too much but in a bad way, I would say yes.

Collapse
 
stereobooster profile image
stereobooster

It would be nice if we can specify what exactly code suppose to do, but we can do this only to some extent. To fully specify code we need to use some kind of formal specification and verify it with TLA+ or similar to make sure specification itself doesn't contradict. In practice only a small amount of code (very important code) goes through this process, the rest get only partial specification. The biggest question is how much is specified? Is it 30%, 50%, 80%? How we gonna know it without actually writing the whole specification and measure percentage?