101

I attended a software craftsmanship event a couple of weeks ago and one of the comments made was "I'm sure we all recognize bad code when we see it" and everyone nodded sagely without further discussion.

This sort of thing always worries me as there's that truism that everyone thinks they're an above average driver. Although I think I can recognize bad code I'd love to learn more about what other people consider to be code smells as it's rarely discussed in detail on people's blogs and only in a handful of books. In particular I think it'd be interesting to hear about anything that's a code smell in one language but not another.

I'll start off with an easy one:

Code in source control that has a high proportion of commented out code - why is it there? was it meant to be deleted? is it a half finished piece of work? maybe it shouldn't have been commented out and was only done when someone was testing something out? Personally I find this sort of thing really annoying even if it's just the odd line here and there, but when you see large blocks interspersed with the rest of the code it's totally unacceptable. It's also usually an indication that the rest of the code is likely to be of dubious quality as well.

Josh K
  • 23,019
  • 10
  • 65
  • 100
FinnNk
  • 5,799
  • 3
  • 28
  • 32
  • 61
    I sometimes encounter people who comment out code, checkin and say "I might need it again in the future - if I remove it now I'll lose it". I have to counter with "Er, ...but that's what source control is for". – talonx Oct 25 '10 at 10:31
  • @talonx - Thanks for the Déjà vu. I've had that conversation at least a half dozen times myself. – JohnFx Oct 25 '10 at 15:11
  • 1
    Ugh, I'm working with a programmer now who leaves huge amounts of commented out code and lots of blank lines and crud in the code. So terrible. – Ken Oct 25 '10 at 16:40
  • 6
    Sometimes, particularly when optimizing, it's handy to leave the old code as a comment, so you know what the obscure optimized code is replacing. Think of leaving a 3 line swap with temp in place when replacing it with a one line bit twiddling swap. (Although, I see no need to use a one line swap -- EVER, unless programme size is of critical importance.) – Chris Cudmore Oct 25 '10 at 17:02
  • @Ken: I think I know that programmer. I see tons of blank lines and I know instantly who was responsible, and I know immediately where my next refactoring will be ;-) – Mike Spross Oct 26 '10 at 22:01
  • 4
    I'm maintaining/cleaning up code written by one of our engineers, who coded some useful things but admits he isn't a programmers. As I consolidate stuff I'll comment out his old code and then later we go over the changes and I show him how I replaced his with something smaller/more efficient/easier to understand. Afterwards I strip out those blocks then I check it in. Having the old code there has benefits because he sees how things can be done more simply and I can remember why I changed things when we're talking. – the Tin Man Nov 04 '10 at 07:19
  • Yeah - commented code is annoying - http://technikhil.wordpress.com/2010/02/18/commented-code-is-a-bad-code-smell/ – Nikhil Nov 04 '10 at 09:43
  • 8
    I leave stuff that "might be used" in for 1 commit, then if things don't break down or a need is not found, it gets removed on the next commit. – Paul Nathan Nov 16 '10 at 22:35
  • 24
    Hmm. `printf("%c", 7)` typically rings alarm bells for me. ;) –  Dec 13 '10 at 15:03
  • 1
    @talonx, if you remove all trace of it in the source, any future maintainer - including you - will not even _know_ it is in the repository without having to look... –  Dec 20 '10 at 10:10
  • 1
    @Thorbjørn - to a point, but a note in a changes text file can be checked in blame to determine which revision the change occured in. Personally, I don't have old commented-out code in current files, but I do have a junk folder, holding files I don't use now but may want to partially resurrect in the future. –  Dec 23 '10 at 09:44
  • @fennec Only "printf()" rings alarm bells for me. LOL ;) – Olivier Pons Dec 23 '10 at 10:21
  • @Steve, sure it can, but would you actually DO that? I don't think so. Code once deleted is essentially deleted for ever. And having half-baked code snippets outside the source repository just proves this point. –  Dec 23 '10 at 17:02
  • @Thorbjørn - sorry, but I have resurrected old code before now. I don't just dump any deleted code in the junk folder, but only the code that may still turn out to be useful. Tends not to be "half-baked snippets" but substantial libraries that aren't being used at the moment, and which I therefore cannot be bothered maintaining to resolve bugs that turned up when I changed compilers. Getting a bit light at the moment - haven't changed compilers since I dropped VC++2003, so most stuff has either been purged or resurrected. The half-baked snippets go in a journal program. –  Dec 24 '10 at 03:54
  • @Thorbjørn - also, to correct a misperception, my junk folder is *in* the source repository. –  Dec 24 '10 at 05:05
  • @Steve314, so you actually don't delete code, you just move it out of the project, but still keep it in source control. Then you don't delete it and leave no trace in the current sources, which is what was being discussed. –  Dec 24 '10 at 10:54
  • @Thorbjørn - as I said, I don't comment out old code, but I do do something very similar, stated in contrast to my initial point about blame. IOW the possibility exists, but its a pedantic point about an approach that I admit I don't and wouldn't use myself. –  Dec 29 '10 at 04:02
  • The fact that they gave it to me is a strong hint. – biziclop Mar 04 '11 at 19:29
  • I hate commented-out code myself, but I kind of have some sympathy because version control systems (at least the ones I know) do not have easy-to-use ways of searching for deleted content in an existing file. – JoelFan Nov 15 '12 at 12:53
  • @JoelFan, do you use git? `git log -p ` will give you a complete patch list for the entire history of a given file. There's probably even a built-in way to search, but I find it easiest to just pipe it through grep: `git log -p | grep `. There's also the programs gitk and qgit and the website github which all have easy-to-use search interfaces for all history. – Ben Lee Feb 25 '13 at 21:09
  • @Ben Lee, no, svn – JoelFan Feb 25 '13 at 23:33

60 Answers60

129
/* Fuck this error */

Typically found inside a nonsense try..catch block, it tends to grab my attention. Just about as well as /* Not sure what this does, but removing it breaks the build */.

A couple more things:

  • Multiple nested complex if statements
  • Try-catch blocks that are used to determine a logic flow on a regular basis
  • Functions with generic names process, data, change, rework, modify
  • Six or seven different bracing styles in 100 lines

One I just found:

/* Stupid database */
$conn = null;
while(!$conn) {
    $conn = mysql_connect("localhost", "root", "[pass removed]");
}
/* Finally! */
echo("Connected successfully.");

Right, because having to brute force your MySQL connections is the right way do things. Turns out the database was having issues with the number of connections so they kept timing out. Instead of debugging this, they simply attempted again and again until it worked.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
Josh K
  • 23,019
  • 10
  • 65
  • 100
  • 19
    If only I could upvote this 6 times! All good examples. I also dislike arrogant/funny comments (especially if they include swearing) - it might be slightly amusing the first time you read them but get very old (and hence distracting) very quickly. – FinnNk Oct 24 '10 at 22:14
  • 5
    I like your example, although I would say that in a certain contexts, multiple nested if statements are unavoidable. With a lot of business logic, the code can be a bit confusing, but if the business itself is confusing to begin with, to simplify the code would be to less accurately model the process. As Einstein said: "Things should be as simple as possible and not one bit simpler." – Morgan Herlocker Oct 25 '10 at 01:15
  • 2
    @Prof Plum -- What example can you give? Usually the alternative to multiple nested if's is to break it out into (many) methods. Junior developers tend to avoid this as though it's less desirable than the if's; but usually when pressed they say "if's do it in fewer lines". It takes someone confident in OOP to step in and remind them that fewer lines != better code. – STW Oct 25 '10 at 01:29
  • 2
    @STW That is a good point, however, I would say that it depends how deep the nesting is. I would certainly agree that anything more then three nests deep is often in need of refactoring, because its going to get pretty hairy. Insurance quoting, however is a good example where multi-nesting can actually model the real world quite well. With exceptions to certain rates/premiums, the manual will literally read something like "if this is a property and if it has a minimum rate below 5.6 and if it is in NC and if it has a boat on the premises, then do such and such." with many other options. – Morgan Herlocker Oct 25 '10 at 01:44
  • 4
    @josh, if "they" are colleagues then I would ponder on why you did not say "we"... –  Oct 25 '10 at 02:28
  • @Thorb: I must be missing something. Please highlight what if causing the confusion. – Josh K Oct 25 '10 at 03:06
  • @Josh, you said "Instead of debugging this, they simply attempted again and again until it worked.". If "they" refers to colleagues who had written said code, then perhaps it would be interesting to find out why you said "they" and not "we". –  Oct 25 '10 at 03:37
  • +1 for the nested if statements – billy.bob Oct 25 '10 at 08:33
  • @Thorb: "They" weren't colleagues. I was brought on to optimize the queries because none of "them" could figure it out. ;) – Josh K Oct 25 '10 at 13:06
  • 1
    The pattern of "this sometimes fails, we don't know why, so we ignore or retry it until it works" is a massive red flag to me. If something is broken, then it's *broken* and it needs to be *fixed*, not worked around. Yes, there are times when you can't fix it - but they are very rare, and should be explained with a comment. I have a colleague (or two) who, when confronted with some unexpected behaviour, will spend maybe an hour trying to figure out why it's happening, then just slap a try-catch on it and call it fixed. Makes me furious. – Tom Anderson Oct 26 '10 at 12:30
  • +1 overall. Using try-catch for application logic is like using a taser to motivate developers to work. It may work but it will do more harm than good. The "F*** this error" made me lol too. – Evan Plaice Nov 19 '10 at 21:42
  • @Evan: Just pray you never have to Java with use raw JDBC, as any database operation can throw `SQLException`, and being a checked exception, the compiler will whine at you if the try/catch block is missing. – Powerlord Nov 22 '10 at 16:55
  • @ Tom Anderson the problem is that what is typically broken is that fact the DBAs report to a different business group and even getting access to the database involved negotations that make the typical middle east peace accord look like the PTA – Martin Beckett Dec 18 '10 at 21:44
  • 1
    @STW - moving complexity into the call graph doesn't mean you have reduced complexity. You could end up reducing readability and maintainability by breaking the logic into separated fragments rather than keeping it in one chunk. There's good reasons to keep functions small and simple, but a guideline is just a guideline. Ultimately, a readable function is one that is easy to read, irrespective of guidelines that might seem to be violated. –  Dec 23 '10 at 09:53
  • 1
    Nested "if" statements are sometimes clearer than one big "if" (i.e. if (c1 && c2 && c3) else if (c1 && (c4 || c5)) really gets on my nerves, if prefer if (c1) { if (c2 && c3) else if (c4 || c5) } ) => For far more complexe "if" I prefer to see nested "if". – Olivier Pons Dec 23 '10 at 10:26
  • @Steve314 -- I agree, there is always a minimum level of complexity that can be reached, and in some/many cases the result is still quite complex. Rather than leaving it in a single method though I would consider refactoring into a new class of simple methods – STW Dec 27 '10 at 15:35
  • At least with a non-sense comment, there's no fear of removal. When you get the "I don't know wtf I'm doing." type comment, it's worth fixing. – JeffO Aug 04 '11 at 17:16
  • That comment was the funniest thing ever. Thank You Very Much – Caffeinated Feb 25 '12 at 03:38
  • @Morgan Herlocker I too work in insurance and coding rules as you describe is not the way to go. First of all, Property vs Auto risks should be defined in different class heirarchies (hence you don't need to check Property rules in your Auto class) Secondly, insurance is inherently a very dynamic sector where rules change all the time. Hard coding rules in such an environment often leads to software rebuilds. Try externalizing your rules in configuration files (such as look up tables or even complex xml files validated by schemas) – Constantin Mar 06 '14 at 09:34
105

The major red flag for me is duplicated code blocks, because it shows that the person either doesn't understand programming fundamentals or was too scared to make the proper changes to an existing code base.

I used to also count lack of comments as a red flag, but having recently worked on a lot of very good code with no comments I've eased back on that.

Ben Hughes
  • 2,009
  • 1
  • 12
  • 15
  • 1
    +1: I saw some code from the colleague who touted himself as a linux expert, who wrote a simple looping application as one long function, the whole thing over and over in main(). Yikes. – KFro Oct 25 '10 at 04:32
  • 4
    @KFro, that's loop unrolling. Thats what compilers do all the time :) VERY efficient! –  Oct 25 '10 at 06:23
  • 3
    @Thorbjorn: Sometimes, you have to help the compiler a little; after all, you are the smart human and he's just a dumb computer. – yatima2975 Oct 25 '10 at 10:16
  • 3
    Another reason i've seen: the consultant was paid to implement the feature as quickly as possible (that's why tests and documentation are missing too, of course). Copy/paste is faster than thinking about how to do things right. – LennyProgrammers Dec 13 '10 at 17:07
  • Last time I had to do it, it was two separate programs that had to make the same calculation. The choice was creating a new dependency with a really specific function or putting comments in both places. – David Thornley Dec 13 '10 at 17:24
  • 4
    Avoiding code duplication can be an obsession. In a language like C++, it isn't always as easy as it should be to factor out the varying parts yet still have robust and efficient code. Sometimes, a bit of cut-and-paste is the more practical option. Also, the optimisation principle can apply - cut-and-paste can get you a quick and easy solution which you can refactor later *if* needed. You *may* be saving a maintenance headache for later, but you know for certain that you're avoiding delays right now. –  Dec 23 '10 at 10:02
  • 1
    @Lenny222 : We've been working for 6 months to full-rewrite – Olivier Pons Dec 23 '10 at 10:31
  • 1
    @Steve - For a statically typed language, C++ is great for factoring out varying parts. If you don't want to do it with inheritance, you can do it with template functions. – kevin cline Aug 04 '11 at 08:12
  • @kevin - cut-and-paste can be more flexible than a template. Metaprogramming is complex, fragile, and the error messages are insane, so unless every use is going to be identical barring a simple template parameter substitution, cut-and-paste can sometimes be the better solution. Better 5 lines of almost-duplicate code than 50 lines of template metaprogramming overhead. –  Aug 04 '11 at 19:25
  • 1
    @Steve: It depends on how many times you are going to "almost-duplicate" those five lines. And as soon as you start "almost-duplicating" ten or fifteen lines you are creating a real maintenance problem. Better for the team to step up and learn to deal with C++ templates than to cut-and-paste the application to death. BTW, I have seen this happen, except they had cut-and-pasted three nested loops a hundred or more times. Then the customer asked for a major extension and the estimate was so high that the application was put into 'maintenance-only' mode and the development team was laid off. – kevin cline Aug 08 '11 at 02:03
  • @kevin - absolutely. I said cut-and-paste **can be** a better solution. I never said anything about making a habit of it. As for your extension cost problem, a small amount of cut-and-paste is (potentially) a small technical debt. If needed, you can repay it by refactoring later. If the debt shows signs of accumulating, you treat it the same as any other technical debt - make sure you pay it off before the bailiff shows up. –  Aug 08 '11 at 04:37
76

Code that tries to show off how clever the programmer is, despite the fact that it adds no real value:

x ^= y ^= x ^= y;
Rei Miyasaka
  • 4,541
  • 1
  • 32
  • 36
64
{ Let it Leak, people have good enough computers to cope these days }

Whats worse is that's from a commercial library!

Reallyethical
  • 561
  • 5
  • 10
  • 33
    This doesn't ring alarm bells. It practically kicks you between the legs. – Steven Evers Oct 27 '10 at 00:17
  • 1
    thats... just... so... wrong... – SpacePrez Nov 16 '10 at 18:57
  • 16
    Daughter is a meth addict. Who cares, at least she won't become obese. ::sigh:: – Evan Plaice Nov 19 '10 at 21:52
  • 17
    When I find myself in times of trouble, mother buntu comes to me. Speaking words of wisdom, let it leak. LET IT LEAK .. LET IT LEAK. LET IT LEAK oh LET IT LEAK. If it just leaks one time, it's not a leaaaaaak. (if you read this far, +1). I really need to consider decaf. – Tim Post Dec 13 '10 at 14:57
  • 13
    "As the deadline fast approaches, LEAKS are all that I can see, somewhere someone whispers, 'Write in C...... eeeeee!!!'" – chiurox Dec 18 '10 at 14:32
  • 9
    Once upon a time there were two OSes. One leaked and crashed if it ran for more than 49days, the other was perfect and would run for ever. One was launched in 1995 to a huge fanfair and was used by millions of people - the other never shipped because they are still checking that it is bug free. There is a difference between philosophy and engineering. – Martin Beckett Dec 18 '10 at 21:52
  • 1
    Actually, that crash was because the OS used a 32 bit millisecond counter that overflowed after 49 days -- not because of a leak. Leaving a commodity desktop OS on for more than a day was unthinkable back then. There *is* a leak that exists even today, though: endless ctrl+z. – Rei Miyasaka Dec 20 '10 at 16:00
  • @MartinBeckett - the software running on the Space Shuttle had a different focus. You may want to read on http://c2.com/cgi/wiki?TheyWriteTheRightStuff (but that software was much more expensive than Windows95). –  Feb 16 '12 at 13:11
  • 1
    @ThorbjørnRavnAndersen - yes they invested millions of $ per line on code to control a vehicle that had so many intrinsic safety flaws it should never have flown. If they had spent half the SW money on better O-rings it might have been better engineering – Martin Beckett Feb 16 '12 at 16:46
63
  • 20,000 (exaggeration) line functions. Any function that takes more than a couple of screens needs re-factoring.

  • Along the same lines, class files that seem to go on forever. There are probably a few concepts that could be abstracted into classes which would clear up the purpose and function of the original class, and probably where it is being used, unless they are all internal methods.

  • non-descriptive, non-trivial variables, or too many trivial non-descriptive variables. These make deducing what is actually happening a riddle.

Dominique McDonnell
  • 1,273
  • 11
  • 14
  • all great examples, particularly the 3rd one for maintenance programmers. – Anonymous Type Oct 25 '10 at 02:50
  • 2000 lines function would not be exaggeration, i have seen one :( The file that contain this monster is one class, 35000 lines long. – Julien Roncaglia Oct 25 '10 at 09:29
  • A.k.a The God Class. This is one of the original Anti-Patterns. – yatima2975 Oct 25 '10 at 10:18
  • 9
    I tend to limit functions to 1 screen whenever possible. – Matt DiTrolio Oct 25 '10 at 16:08
  • 20
    1 screen is even a stretch. I start feeling dirty after 10 or so lines. – Bryan Rowe Oct 25 '10 at 20:10
  • @Matt, @Bryan, Code Complete has a section on length of functions. It recommends functions of between 250-100 lines of code, based on studies correlating length of function to number of bugs. I cannot believe it, and I agree that smaller is better. Anything that I can't see all at once I feel I can't fit in my mind. – Dominique McDonnell Oct 25 '10 at 20:53
  • 56
    Okay, I'm going to voice what may be an unpopular opinion. I say it's code smell to write functions that are atomic, top-to-bottom processes that are broken into separate functions because the developer is clinging to some "functions should be short" cargo-cultism. Functions should be broken along FUNCTIONAL lines, not just because they should be some mythical "right size". That's why they're called FUNCTIONS. – Dan Ray Dec 23 '10 at 13:11
  • 7
    @Dan, Functions shouldn't be short for the sake of being short, but there is only so much info you can hold in your head at one time. Maybe I've got a small brain as for me that limit is a couple of screens :). Breaking functions into multiple functions when they start to test that boundary is necessary to avoid mistakes. On one hand it provides encapsulation so you can think at a higher level and on the other it hides what is happening so makes it harder to work out how the function works. I think that breaking functions up should be done to aid readability, not to fit some 'perfect length'. – Dominique McDonnell Dec 23 '10 at 21:37
  • 2
    @Dan, I agree with @Dominic on this and add a further point: for ideal readability, all the code within a function should be on the same abstraction level. Thus either making calls to other lower-level functions which implement specific steps in the actual process, or doing concrete low level API calls to do the grunt work, but not both. So when I refactor to *Extract Method*, it's often more to separate the distinct abstraction levels rather than just to make the parent method shorter. – Péter Török Jan 28 '11 at 09:44
  • 6
    @Dominic, @Péter, I think the three of us actually are saying the same thing. When there's a good reason to factor code into a smaller function, I'm for it. What I'm rejecting is shortness *for the sake of shortness* in function design. You know, a call stack that's three times longer than it needs to be, but at least those functions are short. I'd rather debug a tall function that does one thing well and clearly than chase the execution path through a dozen chained functions that are each only called from the previous one. – Dan Ray Jan 28 '11 at 13:08
  • @Dan, I've been in this racket for about forty (40) years. In all that time, other than big finite state machines, I've seen exactly one (1) procedure that NEEDED to be more than one printer page (about 60 lines) long. Everything else could ALWAYS have been broken down into sub-page chunks, that would have been easier to understand and easier to maintain. (The procedure in question was the FORTRAN IV STARTRK game's photon torpedo routine. It parsed the command, simulated the torpedo's flight, handled target/weapon interactions, and occasionally simulated recursion.) – John R. Strohm Nov 15 '12 at 16:05
54

Comments that are so verbose that if there were an English compiler, it would compile and run perfectly, yet doesn't describe anything that the code doesn't.

//Copy the value of y to temp.
temp = y;
//Copy the value of x to y.
y = x;
//Copy the value of temp to x.
x = temp;

Also, comments on code that could have been done away with had the code adhered to some basic guidelines:

//Set the age of the user to 13.
a = 13;
Deduplicator
  • 8,591
  • 5
  • 31
  • 50
Rei Miyasaka
  • 4,541
  • 1
  • 32
  • 36
  • 15
    There is, it's called COBOL :-) – Gaius Oct 25 '10 at 14:16
  • 1
    please upvote < Wasn't begging for upvotes, just showing off some intercal-foo. – Tim Post Dec 13 '10 at 15:01
  • 28
    The second case isn't the worst. The worst is: /* Set the age of the user to 13 */ a = 18; – PhiLho Dec 20 '10 at 10:13
  • 4
    @PhiLho - no, even worse is when the `/` from the `*/` is missing, so all the code to the end of the next `*/` is ignored. Luckily, syntax highlighting makes that kind of thing rare these days. –  Dec 23 '10 at 10:18
  • Oh man, this is almost what I thought comments were supposed to be like in my first semester of Java. You see, the professor instructed us to write comments in our programs, but we (or at least I) did not know how detailed we must be. – Mark C Mar 14 '11 at 03:06
  • 3
    Worse again, `a` for user_age? Really? – glasnt Mar 24 '11 at 03:05
  • 1
    @MarkC I tend to group code in "paragraphs" of several lines of code all needed to achieve a single effect, and then if I do need to comment it, I'll write a comment at the top of the "paragraph": `//swap x and y`. How much code should constitute a "paragraph" is probably quite subjective, but I go with somewhere around 5-6 lines of code max unless it's visibly repetitive. – Rei Miyasaka Aug 15 '12 at 10:18
  • This is ugly and pointless, but not necessarily 'bad code'. – Kirk Broadhurst Oct 19 '12 at 04:23
  • 1
    @KirkBroadhurst Bad commenting is bad code, because you can potentially hurt not only the human readability and aesthetics of the code, but also the human ability to keep the code maintainable in the future -- and unmaintainable code is bad code. – Rei Miyasaka Oct 19 '12 at 19:04
  • 2
    I used to maintain a code standard doc at a previous employer, one section of which was appropriate commenting. My favorite example was from MSDN: `i = i + 1; //increment i` – Michael Itzoe Nov 15 '12 at 14:25
44

Code that produces warnings when compiled.

Rei Miyasaka
  • 4,541
  • 1
  • 32
  • 36
  • 1
    There's a candidate for adding 'All warnings as Errors' compiler option to the makefile/project. – JBRWilkinson Nov 22 '10 at 15:07
  • 3
    I guess that could be useful if you're in a project with multiple people that you simply don't trust -- though if I were to join a project where that option's set, that in itself would have me worrying about how able the other programmers are. – Rei Miyasaka Dec 10 '10 at 15:22
  • 1
    I disagree with this. Some compiler warnings (like comparison between signed and unsigned, when you _know_ both values to be unsigned, even if the types are different) are preferable to littering code with needless casts. If I reduce code by using a portable signed integer that a function modifies _only_ if the integer has an unsigned value, I'm going to do that. – Tim Post Dec 19 '10 at 03:24
  • 13
    I'd rather clutter my code with an almost-superfluous `(unsigned int)` than clutter my warning/error lists with benign warnings. I'd hate for the warning list to become a blind spot. It's also much more of a PITA explaining to other people why you're ignoring a warning than it is to explain why you're doing a cast of natural `ints` to `unsigned ints`. – Rei Miyasaka Dec 19 '10 at 18:56
  • Occasionally, you have to work with an API that spews errors whatever you do. Classic examples are where the API is defined in terms of things that are broken by design (some old ioctl() constants were like that, and sometimes OS developers insist on using the wrong type in their headers) or where they've deprecated something without leaving a good replacement (thank you, Apple). – Donal Fellows Aug 04 '11 at 10:13
  • I had a programming project where in order for it to be portable (to run it on my home Windows machine but also on my schools' Macs), since it used OpenGL libraries which differed between the two machines, I had to make heavy use of defines on library function names so that I didn't have to basically write two different versions of the program. Ultimately, it meant I had warnings that I couldn't get rid of. But normally, I'd say yes, I agree with you. At work, we always have 'all warnings as errors' turned on, and that is good practice. – Ben Richards Aug 04 '11 at 18:40
37

Functions with numbers in the name instead of having descriptive names, like:

void doSomething()
{
}

void doSomething2()
{
}

Please, make the function names mean something! If doSomething and doSomething2 do similar things, use function names that differentiate the differences. If doSomething2 is a break-out of functionality from doSomething, name it for its functionality.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
Wonko the Sane
  • 3,172
  • 1
  • 24
  • 24
36
  • Maybe not the worst but clearly shows the implementers level:

    if(something == true) 
    
  • If a language has a for loop or iterator construct, then using a while loop also demonstrates implementers level of understanding of the language:

    count = 0; 
    while(count < items.size()){
       do stuff
       count ++; 
    }
    
    for(i = 0; i < items.size(); i++){
      do stuff 
    }
    //Sure this is not terrible but use the language the way it was meant to be used.
    
  • Poor spelling/grammar in documentation/comments eats at my almost as much as code itself. The reason for this is because code was meant for humans to read and machines to run. This is why we use high level languages, if your documentation is hard to get through it makes me preemptively form a negative opinion of the codebase without looking at it.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
Chris
  • 5,663
  • 3
  • 28
  • 39
36

Magic Numbers or Magic Strings.

   if (accountBalance>200) { sendInvoice(...); }

   salesPrice *= 0.9;   //apply discount    

   if (invoiceStatus=="Overdue") { reportToCreditAgency(); }
Deduplicator
  • 8,591
  • 5
  • 31
  • 50
JohnFx
  • 19,052
  • 8
  • 65
  • 112
  • 4
    Not really that bad with the second two, at least the discount is explained, and the "Overdue" is intuitive. The `200`, on the other hand... – Tarka Oct 25 '10 at 14:39
  • 10
    @Slokun - Intuitive isn't the point so much as maintainability and fragility. For example, consider what happens when the discount amount changes and 0.9 is hard-coded in six different places. Also, using strings instead of constants/enums is asking for trouble in languages with case sensitive strings. – JohnFx Oct 25 '10 at 14:43
  • +1 I just spent way too much time debugging a problem that turned out to be caused by a line 'timeout=15;' buried in a program. – aubreyrhodes Dec 13 '10 at 21:35
  • I think the last one is *sometimes* okay, depending on where that data for invoiceStatus came from. If it just came from a public api that returns JSON that was just decoded, checking against a hard-coded String constant is probably okay. Agree though that "200" and "0.9" are just magic constants and should not be hard-coded in this way. Even if they are only used in this one place, maintenance is easier if you define them in a configuration section separately rather than interspersing them in the logic code. And if they are used in multiple places, maintenance becomes *much* easier. – Ben Lee Feb 25 '13 at 21:30
30

The one I notice immediately is the frequency of deeply nested code blocks (if's, while's, etc). If code is frequently going more than two or three levels deep, thats a sign of a design/logic problem. And if it goes like 8 nests deep, there better be a darn good reason for it not to be broken up.

GrandmasterB
  • 37,990
  • 7
  • 78
  • 131
  • 6
    I know some people learned that every method should have only one `return` statement, but when it causes 6+ levels of if/then nesting I think its doing far more harm than good. – Darien Aug 04 '11 at 18:08
28

When grading a student's program, I can sometimes tell in a "blink"-style moment. These are the instant clues:

  • Poor or inconsistent formatting
  • More than two blank lines in a row
  • Nonstandard or inconsistent naming conventions
  • Repeated code, the more verbatim the repeats, the stronger the warning
  • What should be a simple piece of code is overly complicated (for example, checking the arguments passed to main in a convoluted way)

Rarely are my first impressions incorrect, and these warning bells are right about 95% of the time. For one exception, a student new to the language was using a style from a different programming language. Digging in and re-reading their style in the idiom of the other language removed the alarm bells for me, and the student then got full credit. But such exceptions are rare.

When considering more advanced code, these are my other warnings:

  • The presence of many Java classes that are only "structs" to hold data. It doesn't matter if the fields are public or private and use getters/setters, it's still not likely part of a well thought-out design.
  • Classes that have poor names, such as just being a namespace and there's no real cohesion in the code
  • Reference to design patterns that aren't even used in the code
  • Empty exception handlers without explanation
  • When I pull up the code in Eclipse, hundreds of yellow "warnings" line the code, mostly due to unused imports or variables

In terms of style, I generally don't like to see:

  • Javadoc comments that only echo the code

These are only clues to bad code. Sometimes what may seem like bad code really isn't, because you don't know the programmer's intentions. For instance, there may be a good reason that something seems overly complex-- there may have been another consideration at play.

Macneil
  • 8,223
  • 4
  • 34
  • 68
  • I fail to see how using the style from one language in another is a grievous error (2, 4, 8 spaces per indent...). If the student has little other style to follow, there's nothing wrong with being self-consistent. As the grader you see a billion programs so you're at the opposite end of that spectrum, but that isn't a reason to totally dismiss a different (but consistent) style. – Nick T Oct 25 '10 at 16:37
  • @Nick T: That's my point; the different style rang the warning bell, but it was a false alarm (the student got full credit-- nothing was dismissed). It's not an error, but the question is about the instant alarm bells. I was giving an example of a false alarm. – Macneil Oct 25 '10 at 17:06
  • So how to you code your struct in Java ??? – Guillaume Oct 26 '10 at 10:47
  • @Guillaume: First you can ask "what am I getting this value for?" Whatever common operations you have on those fields might make great methods. But I'm afraid maybe this discussion is losing focus from my original point: The question is asking for "alarm bells" that ring the instant you see code. On balance, it is better to code in the idiom of the language, but if the code is still sound, then it's *not* a big deal if you don't. My only point is that this measure usually works, but there are obvious exceptions. – Macneil Oct 26 '10 at 12:00
  • 18
    I see nothing wrong with classes that simply aggregate data - i.e., structs. That's what Data Transfer Objects (DTOs) are and can make code much more readable than say, e.g. passing in 20 parameters to a method. – Nemi Oct 26 '10 at 17:14
  • @Nemi: I don't disagree. There can be perfectly acceptable and idiomatic code that does just that. I'm just suggesting that 95% of the time, no, it's a warning sign and the code you're going to dive into *might* be unpleasant. I'm going to edit my answer so this is clearer for everyone. – Macneil Oct 26 '10 at 17:22
  • 1
    Your comment about structs is spot on. It's fine when the data is in its rawest form and will not be modified in any way. But 95% of the time you should have some functions in the class to format/operate on the data. I just remembered some of my code that essentially uses that pattern and ought to be improved upon. – DisgruntledGoat Oct 27 '10 at 14:42
  • 2
    +1 for inconsistent style and extra line breaks (I've seen random indentations, *no* indentation, random and changing naming conventions and more - and this in production code!). If you can't even bother to get that right, then what else can't you be bothered doing? – Dean Harding Oct 28 '10 at 05:19
  • 1
    I look for the declaration line of a method being indented too far relative to the body. This is a sign they copy-and-pasted from someone else's file. – Barry Brown Nov 20 '10 at 23:00
  • I'll have you know, I _sell_ my blank lines .. ads look great in comments! (ducks) – Tim Post Dec 13 '10 at 15:02
  • "Reference to design patterns that aren't even used in the code" +1 – SingleNegationElimination Dec 13 '10 at 15:03
  • @Nemi - you are right, DTOs aren't a code smell. They are a language smell. – kevin cline Aug 04 '11 at 08:18
  • @Dean: Those are actually some of the biggest red flags. A bit like seeing cockroaches on the floor of a restaurant kitchen. – Donal Fellows Aug 04 '11 at 10:17
  • 95%? Be careful of confirmation bias. – Darien Aug 04 '11 at 18:07
  • @Darien: This is in the context of grading assignments. If you read further I mention how I'll re-read and investigate each case. The characteristics I'm reporting on are those 95% cases. There are many other red flags and so I'm only telling you the most dramatic ones. – Macneil Aug 04 '11 at 20:59
25

Personal favorite/pet peeve: IDE generated names that get comitted. If TextBox1 is a major and important variable in your system, you've got another thing coming come code review.

Wyatt Barnett
  • 20,685
  • 50
  • 69
25

Completely unused variables, especially when the variable has a name similar to variable names that are used.

C. Ross
  • 2,926
  • 2
  • 26
  • 42
21

A lot of people have mentioned:

//TODO: [something not implemented]

While I wish that stuff was implemented, at least they made a note. What I think is worse is:

//TODO: [something that is already implemented]

Todo's are worthless and confusing if you never bother to remove them!

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
Morgan Herlocker
  • 12,722
  • 8
  • 47
  • 78
  • 1
    I just went through the excercise of having to produce a report of all the TODOs in our release product, plus a plan for dispositoning them. Nearly half turned to out to be obsolete. – AShelly Oct 26 '10 at 19:11
  • 1
    -1 TODO comments are used in MS Visual Studio to track parts of the project that still need work. IE, the IDE keeps a list that tracks TODOs so you can easily click on them and be brought directly to the line that the TODO exists on. I would rather see TODOs placed explicitly to see what work still needs to be done. See http://dotnetperls.com/todo. – Evan Plaice Nov 19 '10 at 21:49
  • 3
    @Evan Plaice: Wow, you mean the VS IDE recognises when you've implemented something and removes the `//TODO` comment? Awesome! – JBRWilkinson Nov 22 '10 at 15:06
  • @Evan; I did not say anything against the use of TODO's. They can be quite useful and I use them frequently. However, not removing them when the corresponding block of code is actually complete can be a nightmare for legacy code. Even if VS could automatically remove the TODO, neither it nor I would have an easy time looking at the algrorithm under it to tell if it had been fully implemented, or just partially implemented for particular cases. – Morgan Herlocker Nov 23 '10 at 18:51
  • @JBRWilkinson No, but it makes it easy to see what TODO comments still exist in the code so it reduces the chance that leftover TODO's are left in the code. – Evan Plaice Nov 25 '10 at 02:36
  • 4
    @Prof Plum Why not just create a policy where the person responsible for a TODO puts their name in the comment. That way, if there are some leftovers it – Evan Plaice Nov 25 '10 at 02:37
  • 1
    @Evan +1 "puts their name". – Morgan Herlocker Nov 29 '10 at 20:23
  • 3
    Better plan than `// TODO `, use your bug tracker, that's what its for! – SingleNegationElimination Dec 13 '10 at 14:58
  • Doxygen _does_ help you manage them a bit better. At least you see them after generating documentation and say "Aww, snap, I fixed that last month, my bad .." – Tim Post Dec 13 '10 at 15:00
  • @Evan Plaice: "annotate" function of source control tool can be also used to track the author of TODO (to some extent). – MaR Aug 04 '11 at 11:59
20

A method that requires me to scroll down to read it all.

BradB
  • 443
  • 2
  • 8
  • 14
    Hmm.. this depends on what's being implemented. It would not be unreasonable for this to occur when implementing some complicated algorithms, as that is how they are defined. Of course, if the majority of methods are that way, that is a red flag. – Billy ONeal Oct 24 '10 at 23:51
  • 9
    As a blanket statement then I disagree, wasting time constantly refactoring so that everything fits this kind of self imposed rule actually increases the overall cost of the project. – Anonymous Type Oct 25 '10 at 02:48
  • 1
    I disagree that this rule can increase the overall cost of a project but I guess that is subjective because it would be dependant on the developer(s). If you keep to the general principle of "separation of concerns" whilst developing then re-factoring would be less of a task if one chose to do it. Something for consideration is how much would it cost three years down the line when developers who didn't code the original project are trying to bug fix a bunch of methods with 300+ lines of code? How much does that cost? – BradB Oct 25 '10 at 08:18
  • 18
    I am more annoyed at scrolling right than at scrolling down. Whitespace is "free." – Wonko the Sane Oct 25 '10 at 13:37
  • I have a portrait oriented 22 inch lcd so that changes your metric a bit =) – Eric Oct 25 '10 at 16:55
  • 4
    I'd rather scroll than have to skip all over the file (or multiple files) to figure out what the code is doing. – TMN Oct 25 '10 at 17:15
  • @Eric, did long lines for a while. Stopped when I found out it 1) printed badly 2) was royally messed up when then Eclipse formatter touched it –  Nov 22 '10 at 09:37
  • What size font do you use? – JBRWilkinson Nov 22 '10 at 15:05
  • I remember at university Intro to CS we had to write C++ program and I just didn't have time to figure out the smart way to do it so I ended up doing a bunch of inefficient and repetitive stuff. It had a bug so I went to the teaching assistant's office hour and as he scrolled down my overly repetitive program, he said, "I can't hold my breath any longer, for a fairly simple program, if I can't scroll through your file in a single breath, something is seriously wrong." – chiurox Dec 18 '10 at 14:25
  • +1 to Wonko - I like to have margins displayed at 80 and 132 chars in my editor. Obviously the exact numbers are for historic reasons, but the basic idea is to remind me to not (often) go too far to the right. Even on a huge monitor, the width is better used displaying two or more files (or views into the same file) side-by-side. On the other hand, a file with several thousand text lines won't bother me. That's what bookmarks are for. Breaking the file into pieces doesn't make it more readable - only more fragmented. –  Dec 23 '10 at 10:26
  • Oh come on, I've seen projects that have *SQL Statements* that don't even fit on one screen! How do you expect the methods that use them to fit? – Joshua Carmody Aug 04 '11 at 17:20
20

Conjunctions in method names:

public void addEmployeeAndUpdatePayrate(...) 


public int getSalaryOrHourlyPay(int Employee) ....

Clarification: The reason this rings alarm bells is that it indicates the method likely violates the single responsibility principle.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
JohnFx
  • 19,052
  • 8
  • 65
  • 112
  • Hmmm...if the function name accurately defines what the function does, then I disagree. If the method does two separate things that would be better to separate, then I *may* agree, depending on the context. – Wonko the Sane Oct 25 '10 at 15:07
  • 2
    That's the point. The conjunction implies that it is very likely it does more than one thing. Per the question it is just something that raises my awareness that something MAY be wrong. – JohnFx Oct 25 '10 at 15:23
  • 3
    Now what if you have to add an employee and update their payrate in several places? If that method contains two method calls (`addEmployee(); updatePayrate();`), then I don't think that's a problem. – Matt Grande Feb 27 '12 at 16:36
14

Linking obviously GPL'd source code into a commercial, closed-source program.

Not only does it create an immediate legal problem, but in my experience, it usually indicates either carelessness or unconcern which is reflected elsewhere in the code as well.

Bob Murphy
  • 16,028
  • 3
  • 51
  • 77
9

Language agnostic:

  • TODO: not implemented
  • int function(...) { return -1; } (the same as "not implemented")
  • Throwing an exception for a non-exceptional reason.
  • Misuse or inconsistent use of 0, -1 or null as exceptional return values.
  • Assertions without a convincing comment saying why it should never fail.

Language specific (C++):

  • C++ Macros in lowercase.
  • Static or Global C++ variables.
  • Uninitialized or unused variables.
  • Any array new that is apparently not RAII-safe.
  • Any use of array or pointer that is apparently not bounds-safe. This includes printf.
  • Any use of the un-initialized portion of an array.

Microsoft C++ specific:

  • Any identifier names that collide with a macro already defined by any of the Microsoft SDK header files.
  • In general, any use of the Win32 API is a big source of alarm bells. Always have MSDN open, and look up the arguments/return value definitions whenever in doubt. (Edited)

C++/OOP specific:

  • Implementation (concrete class) inheritance where the parent class have both virtual and non-virtual methods, without a clear obvious conceptual distinction between what should/should not be virtual.
user
  • 2,170
  • 8
  • 25
  • 36
rwong
  • 16,695
  • 3
  • 33
  • 81
  • 19
    //TODO: Comment on this answer – johnc Oct 25 '10 at 08:55
  • 8
    I guess "language agnostic" means "C/C++/Java" now? – Inaimathi Oct 25 '10 at 14:51
  • +1 "Throwing an exception for a non-exceptional reason" couldn't agree more! – billy.bob Oct 26 '10 at 08:36
  • 2
    @Inaimathi -- TODO comments, function stubs, exception abuse, confusion of zero/null/empty semantics and pointless sanity checks are inherent to all imperative/OOP languages and to some extent all programming languages in general. – Rei Miyasaka Oct 28 '10 at 04:17
  • I believe that C preprocessor macros in lower case _are_ okay, but only if they evaluate their arguments only once and result in only a single statement. – Joe D Jan 02 '11 at 22:49
9

Using lots of text-blocks rather than enums or globally defined variables.

Not good:

if (itemType == "Student") { ... }

Better:

private enum itemTypeEnum {
  Student,
  Teacher
}
if (itemType == itemTypeEnum.Student.ToString()) { ... }

Best:

private itemTypeEnum itemType;
...
if (itemType == itemTypeEnum.Student) { ... }
Deduplicator
  • 8,591
  • 5
  • 31
  • 50
Yaakov Ellis
  • 1,012
  • 5
  • 12
8

Weakly typed parameters or return values on methods.

public DataTable GetEmployees() {...}

public DateTime getHireDate(DataTable EmployeeInfo) {...}

public void FireEmployee(Object EmployeeObjectOrEmployeeID) {...}
Deduplicator
  • 8,591
  • 5
  • 31
  • 50
JohnFx
  • 19,052
  • 8
  • 65
  • 112
  • 2
    +1: I have to work with some “REST” web services that return everything as pseudo-HTML tables, even where you pass in things that are a clear syntactic error. Not authorized? Input complete junk? Server over capacity? 200 (plus a message in a horrid format in a one column, one row table). AAaaaaaaaargh! – Donal Fellows Aug 04 '11 at 10:30
8

Bizarre indentation style.

There's a couple of very popular styles, and people will take that debate to the grave. But sometimes I see someone using a really rare, or even a home-grown indentation style. This is a sign that they have probably not been coding with anyone other than themselves.

Ken
  • 793
  • 3
  • 7
  • 7
  • 2
    or just a sign that they are a highly prized individualistic talent that hasn't become caught up in the web of homogonised coding practises that are in no way related to "best practises". – Anonymous Type Oct 28 '10 at 22:35
  • 1
    I hope you're being sarcastic. If someone is coding in such an unusual way, that should set off alarm bells. They can be as artistic as they want, but still... alarm bells. – Ken Oct 29 '10 at 02:23
  • 2
    There's a somewhat uncommon style (I believe it's called Utrecht style) that I find is quite useful despite being extremely uncommon outside of Haskell/ML/F#. Scroll down to "module Shapes": http://learnyouahaskell.com/making-our-own-types-and-typeclasses . What's nice about this style is that you don't have to modify the delimiter on the preceding line to add a new one -- which I often forget to do. – Rei Miyasaka Dec 14 '10 at 01:29
  • @ReiMiyasaka Seven years late, but...Utrecht style really irks me. I believe that it is an error in the Haskell specification not to impose another "layout rule" on vertically-organized lists. That way, the parser could detect a new list entry just by checking indentation, which is how everyone organizes their lists anyway. – Ryan Reich Jul 29 '17 at 19:18
  • @RyanReich Weird, seven years later, and I still like it. I do agree, though; for all its syntactical awkwardness and failings, F# also allows items to be delimited just by a newline and indentation (in most cases), which makes for tidy code. – Rei Miyasaka Aug 01 '17 at 23:11
7

Code smell: not following best practices

This sort of thing always worries me as there's that truism that everyone thinks they're an above average driver.

Here's a news flash for ya: 50% of the world's population is below average intelligence. Ok, so some people would have exactly average intelligence, but let's not get picky. Also, one of the side affects of stupidity is you can't recognize your own stupidity! Things don't look so good if you combine these statements.

Which things instantly ring alarm bells when looking at code?

Many good things have been mentioned, and in general it seems that not following best practices is a code smell.

Best practices are usually not invented randomly, and are often there for a reason. Many times it can be subjective, but in my experience they are mostly justified. Following best practices should not be a problem, and if you're wondering why they are as they are, research it rather than ignoring and/or complaining about it - maybe it's justified, maybe it's not.

One example of a best practice might be using curlies with every if-block, even if it only contains one line:

if (something) {
    // whatever
}

You might not think it's necessary, but I recently read that it is a major source of bugs. Always using brackets have also been discussed on Stack Overflow, and checking that if-statements have brackets is also a rule in PMD, a static code analyzer for Java.

Remember: "Because it's best practice" is never an acceptable answer to the question "why are you doing this?" If you can't articulate why something is a best practice, then it's not a best practice, it's a superstition.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
Vetle
  • 2,185
  • 15
  • 19
  • 2
    This may be pedantic, but I think it matters what average you pick. As I understand it, 50% of the world's population is below the median intelligence (by definition); but other averages do not work the same way. For example take the population (1, 1, 1, 5) which has an arithmetic mean of 2. – flamingpenguin Oct 25 '10 at 13:33
  • ummm, you cited the "what-superstitions-do-programmers-have" post where a user made a bold statement about curly braces with no source. I don't see that as a good example of best practices. – Evan Plaice Nov 19 '10 at 22:33
  • @Evan: yes, you're right. I added a bit more about that, hope this helps. – Vetle Nov 20 '10 at 10:58
  • 4
    The flipside of this is people who slavishly follow "best practices" without any critical thought as to why something is a "best practice". This is why I strongly dislike the term "best practice", because for some people it's an excuse to stop thinking and follow the herd. "Because it's best practice" is never an acceptable answer to the question "why are you doing this?" If you can't articulate why something is a best practice, then it's not a best practice, it's a superstition. – Dan Dyer Dec 18 '10 at 10:43
  • Very good comment, Dan! I added the two last lines to the answer. – Vetle Dec 20 '10 at 09:38
  • Actually, `50% of the world's population is below average intelligence` is incorrect. That's not how averages work. – Rob Aug 04 '11 at 02:46
7
  • Multiple ternary operators strung together, so instead of resembling an if...else block, it becomes an if...else if...[...]...else block
  • Long variable names with no underscores or camelCasing. Example from some code I have pulled up: $lesseeloginaccountservice
  • Hundreds of lines of code in a file, with little to no comments, and the code being very non-obvious
  • Overly complicated if statements. Example from code: if (!($lessee_obj instanceof Lessee && $lessee_obj != NULL)) which I chomped down to if ($lessee_obj == null)
Tarka
  • 1,588
  • 11
  • 14
6

Comments that say "this is because the design of the froz subsystem is totally borked."

That go on over an entire paragraph.

They explain that the following refactor needs to happen.

But did not do it.

Now, they might have been told they couldn't change it by their boss at the time, because of time or competence issues, but maybe it was because of people being petty.

If a supervisor thinks that j.random. programmer can't do a refactoring, then the supervisor should do it.

Anyway this happens, I know the code was written by a divided team, with possible power politics, and they didn't refactor borked subsystem designs.

True story. It could happen to you.

Tim Williscroft
  • 3,563
  • 1
  • 21
  • 26
6

Can anyone think of an example where code should legitimately refer to a file by absolute path?

Rei Miyasaka
  • 4,541
  • 1
  • 32
  • 36
  • Same goes for relative paths (moreso actually). Relative paths usually are relative to where the program was called from, not where the program resides. The only way I've really found to solve this is to have some absolute area (such as the home folder or appdata) where I can find a file that tells me where the program is located. Then I can use a "relative" path to the absolute path given in that file. – jsternberg Oct 25 '10 at 16:35
  • 1
    XML schemas count? – Nick T Oct 25 '10 at 16:45
  • 1
    System configuration files. Typically should be set by ./configure, but even that needs a default value somewhere. – eswald Oct 25 '10 at 16:54
  • Hmm do config files count though? And I'm tempted to think of XML schemas as "documents". – Rei Miyasaka Oct 25 '10 at 20:57
  • 4
    `/dev/null` and friends are okay. But even things like `/bin/bash` are suspect - what if you're one some kooky system that has `/usr/bin/bash`? – Tom Anderson Oct 26 '10 at 13:40
  • 1
    Web service client code generated by JAX-WS tools (JBossWS and Metro, at least) contains a hardwired absolute path to the WSDL file (twice!). Which is probably something wildly inappropriate like `/home/tom/dev/randomhacking/thing.wsdl`. It is *criminally insane* that this is default behaviour. – Tom Anderson Oct 26 '10 at 13:43
  • 1
    Oh yeah, /dev/null is acceptable. I've had nightmares with programs trying to access /bin/ and not finding it in Slackware Linux, back in the day. – Rei Miyasaka Oct 28 '10 at 04:10
  • 4
    about `/dev/null`: I have the habit, when developing on windows to keep apps and libs under `c:\dev`. Somehow, a folder `null` is always automatically created inside that folder. I swear I have no idea who does that. (One of my favorite bugs/features) – Sean Patrick Floyd Nov 22 '10 at 14:15
  • @Floyd Hah, yeah there are some bizarre "magic" file names. I keep all my stuff under `\users\rei\Documents` -- or, since Visual Studio makes a folder automatically, `\users\rei\Documents\Visual Studio 2010\Projects`. – Rei Miyasaka Dec 10 '10 at 15:14
  • Best practice in this area is to have a base directory set once somewhere and to locate all application files relative to that. (Or there could be multiple base directories for different uses, depending on platform conventions.) The current directory belongs to the user, and hard-coded filenames are just trouble. – Donal Fellows Aug 04 '11 at 10:27
6

Catching general exceptions:

try {

 ...

} catch {
}

or

try {

 ...

} catch (Exception ex) {
}

Region overuse

Typically, using too many regions indicates to me that your classes are too big. It's a warning flag that signals that I should investigate more into that bit of code.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
  • Catching general exceptions is only a problem if you rethrow them without doing anything. Really for most things one exception class would suffice. I tend to use runtime_error. – CashCow Mar 02 '11 at 13:18
  • +1 for the 'catch and throw away exception' example. If you're not doing anything with the exception, don't catch it. At the very least, log it. At the very, very least put in a comment explaining why it's okay to catch all exceptions and move on at that point in the code. – E.Z. Hart Mar 04 '11 at 19:09
5
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...
#define ...

Of course without any kind of documentation and the occasional nested #defines

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
Sven
  • 186
  • 7
5

C++ code with explicit delete statements (unless I'm looking at the innards of a smart pointer implementation). 'delete' is the 'goto' of memory management IMHO.

Closely related to this, code like:

// Caller must take ownership
Thing* Foo::Bar()

(And count yourself lucky if there's the comment!). It's not like smart pointers are rocket science. std::auto_ptr is made for this sort of thing (documenting and enforcing the intent expressed in the comment) and been part of the standard for ages now.

Together these scream unloved legacy code, or maintainers with a mindset stuck somewhere in the early 90s.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
timday
  • 2,502
  • 1
  • 18
  • 17
  • Unless it's an embedded system... – Ant Dec 18 '10 at 10:27
  • Would the embedded guys go anywhere near C++ at all though ? malloc/free in C are a different matter. – timday Dec 18 '10 at 10:43
  • Huh, I honestly never knew about std::auto_ptr. C++ used to be my language of choice, but for the past decade or so I've only been using it for homework (yes I've been in school for that long). Learned something new. – Rei Miyasaka Dec 21 '10 at 07:59
  • @Rei: If you like auto_ptr you'll love http://www.boost.org/doc/libs/1_45_0/libs/smart_ptr/smart_ptr.htm and maybe http://www.boost.org/doc/libs/1_45_0/libs/ptr_container/doc/ptr_container.html too. – timday Dec 21 '10 at 23:37
  • haven't they also got something like `boost_shared_smart_auto_ptr_container` already?? ;) – mlvljr Jan 27 '11 at 20:19
  • 1
    Also, in C++11 `auto_ptr` becomes [deprecated](http://en.wikipedia.org/wiki/Auto_ptr). – Lstor Aug 04 '11 at 07:57
  • auto_ptr is not without it's flaws and given C++0x's unique_ptr and std::move are a significant improvement, it's rightly deprecated. But that doesn't mean there isn't a ton of code out there in the last 2 decades which couldn't have been greatly improved by selective use of auto_ptr instead of raw pointers. I never quite understood why auto_ptr was so maligned myself; most people's objections seem to boil down to "but it doesn't work with the STL containers" and "the stealth move semantics are scary", which seem hardly sufficient to reject the class outright. – timday Aug 04 '11 at 11:01
5

Class naming conventions that demonstrate a poor understanding of the abstraction they're attempting to create. Or that don't define an abstraction at all.

An extreme example comes to mind in a VB class I saw once that was titled Data and was 30,000+ lines long...in the first file. It was a partial class split into at least half a dozen other files. Most of the methods were wrappers around stored procs with names like FindXByYWithZ().

Even with less dramatic examples, I've sure we've all just 'dumped' logic into a poorly conceived class, given it a wholly generic title, and regretted it later.

Bryan M.
  • 1,017
  • 9
  • 14
5

Functions that reimplement basic functionality of the language. For example, if you ever see a "getStringLength()" method in JavaScript instead of a call to the ".length" property of a string, you know you're in trouble.

Ant
  • 2,600
  • 2
  • 19
  • 25
4

When there are no comments or documentation whatsoever of what the code does or is supposed to do (i.e. "the code is the documentation").

Methods or variables with a number as suffix (e.g. Login2()).

leson
  • 101
  • 3
4
ON ERROR RESUME NEXT

Having to maintain Classic ASP applications is sadly a necessesity for most ASP.NET developers, but opening up a common include file and seeing that on the first line is soul-destroying.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
richeym
  • 3,007
  • 3
  • 22
  • 23
  • 1
    That brings back horrible, horrible memories. – E.Z. Hart Mar 04 '11 at 19:10
  • Oh god. I once had to maintain (by myself) a HUGE Classic ASP app that **relied** on `On Error Resume Next` to actually run properly because the "programmer" just tried the brute force code approach. I mean variables used before they are instantiated, calls to functions that don't exist, etc. I had to leave it in because it would have taken months (no joke!) to fix all the pages that broke when I removed it. I still have nightmares =( – Wayne Molina Apr 15 '11 at 20:09
  • +1, although this is compounded by bad language design. Why is canceling a print dialog box an error?! – asthasr Sep 18 '11 at 03:41
3

Code that cannot ever, logically enter the execution path.

var product = repository.FindProduct(id);

log.Info("Found product " + product.Name);

if (product != null)
{
    // This will always happen
}
else
{
    // **This won't ever happen**
}

or

if (messages.Count > 0)
{
    // Do stuff with messages
}
else if (messages.Count == 1)
{
    // **I hope this code isn't important...**
}
Deduplicator
  • 8,591
  • 5
  • 31
  • 50
rmac
  • 464
  • 2
  • 5
3

From my Java-centric perspective:

  • Non-standard coding style.
  • Non-private variables.
  • Missing final on fields.
  • Pointless or overuse of inheritance.
  • Huge classes or blocks of code.
  • Too many comments (they're probably just wishful thinking anyway).
  • Unstructured logging.
  • Getters and setters (interfaces should be about behaviour).
  • Duplicated data.
  • Strange dependencies.
  • Statics, including thread-globals.
  • For multi-threaded code, parts of the same class that are expected to be run in different threads (notably GUI code).
  • Dead code.
  • String manipulation mixed in with other code.
  • Generally mixing layers (higher level stuff, combined with iterating over an array of primitives or thread-handling, say).
  • Any use of reflection.
  • catch blocks without useful code (bad: comments, printf, logging or just empty).
3
  • Putting every local variable in the first feew lines of the method block. Especially in conjunction with long methods.
  • Using boolean variables to break out of loops / skip iterations instead of just using break / continue
Oliver Weiler
  • 2,448
  • 19
  • 28
  • Some languages *force* you to put the local variables on the top of the fnuction. For example X++ (Dynamics AX) requires you to put the in top and put a ; as block-closer. And for the second one there are also situations which require such way of working. For example when working with nested loops, if you want to jump out of 2 or 3 loops at a time you might need to have some flag to indicate whether the loop was terminated in a normal fashion or was terminated by a break statement and wish to take action based upon the type of loop quiting in the previous loop. – Gertjan Mar 24 '11 at 11:10
  • 1
    @Gertjan: "Some languages force you to put the local variables on the top of the [function]." Like, you know, *ANSI Standard C*. – Stuart P. Bentley Jun 07 '11 at 01:58
3
try
{
//do something
}
catch{}
Deduplicator
  • 8,591
  • 5
  • 31
  • 50
Tom Squires
  • 17,695
  • 11
  • 67
  • 88
2

anything with something like this

// TODO: anything could be here!

Edit: I should qualify that I meant this in production code. But even in code committed to source control this still isn't good. But, that could be a personal thing in that I like to finish the day off having tied off all my loose ends :)

Edit 2: I should further qualify that I meant when I see this in established code. Like something that's a number of years old and I am fixing a bug it. I see a TODO and that's when the alarm bells start ringing. TODO's (to me) imply that the code was never finished for some reason.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
Antony Scott
  • 137
  • 6
  • 4
    I would only agree in context, in production code yes but during development cycle I will often toss "todos" in places where I have an idea but it is to elaborate or involved to implement based on what I am currently working on. – Chris Oct 24 '10 at 21:54
  • I have to admit I'm guilty of TODOitis during development too. – FinnNk Oct 24 '10 at 22:00
  • 9
    You should use `TODO` comments for one thing and one thing only: leaving a note for yourself while you work on something related elsewhere. Only when `grep` says that there are no more `TODO`s are you allowed to commit. – Jon Purdy Oct 24 '10 at 22:07
  • 1
    @Jon Purdy I strongly disagree. When you're designing a project from scratch, it's easier to put down your ideas on a new project under development it may take 5 separate individual components to get a method to work. It's much easier to drop the TODOs in place and mark them off one-by-one. Some IDEs like VisualStudio fetch TODOs in the code and create a list similar to the debugging error list. – Evan Plaice Nov 19 '10 at 22:17
  • 1
    @Jon it's much better to commit early and commit often because it'll be easier to backtrack if something is broken. I typically commit after every new feature/module is completed and the project builds. A TODO could be a more time-consuming note like, "revise the comments for this module", in which case I'd come back to it when I switch mental context to commenting for documentation. IMHO, a rich revision history is **much** more important than clean code. It will save you if something breaks. – Evan Plaice Nov 19 '10 at 22:22
  • @Evan Plaice: That's valid. I do commit early and often, but I'm also known for doing a lot of development in my head before ever writing code, so I always just sorta write legibly and document as I go, and it works well for me and anyone who reads my code. `TODO: something unrelated to what I'm currently doing` simply never happens: I only use `TODO` comments for things that are build-breaking and immediately relevant, and high-level to-do list items ("add this", "refactor that") get maintained elsewhere. It's just a difference of workflow, I guess. – Jon Purdy Nov 20 '10 at 22:12
2

Anytime I read the following:

//Don't put in negative numbers or it will crash the program.

Or something similar. If that's the case then put in an assert! Let the debugger know that during run-time you don't want those values and make sure the code spells out the contract with the caller.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
wheaties
  • 3,584
  • 22
  • 23
2

Our legacy VB6 code, you can open any Module or form code page and find a screen full of Public or Global #&@! variables declared at the top, being referenced from all over the @&!!(*!# program. ARGH!!!!

(Whew, I had to get that out :-) )

HardCode
  • 614
  • 4
  • 12
2

For SQL:

The first big indicator is the use of implied joins.

Next is the use of a left join on tableB combined with a WHERE clause like:

WHERE TableB.myField = 'test'

If you don't know that will give incorrect results then I can't trust that any query you write will give correct results.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
HLGEM
  • 28,709
  • 4
  • 67
  • 116
2

As for magic numbers: they are bad if they are used in different places and changing it requires you to syncrhonise it in several places. But one number in one place isn't any worse than having one constant to denote one number that is still used in one place.

Furthermore, constants might not have much place in your application. In many database apps, those things should be stored in the database as per app or per user settings. And to complete their implementation they involve this setting and a place in the ui and a note in the end user documentation... all of which is kind-a overengineering and a waste of resources if everyone is perfectly happy when the number is 5 (and 5 it is.)

I think you can leave numbers and strings in place until there is a need to use this number outside that place. Then it is time to refactor things to a more flexible design.

As for strings... I know the arguments, but this is one more place there is no point in doing a one-string-to-one-constant conversion. Especially if the strings in place are coming from a constant implementation anyway (for example, imports that are generated from an outside application, and have a status-string that is short and recognisable, just like 'Overdue'.) There just isn't much point in converting the 'Overdue' to STATUS_OVERDUE when it is used in only one place anyway.

I am very much for not adding complexity if it doens't actually create needed benefits on flexibility, reuse or error checking. When you need the flexibility, code it right (the refactor thingy). But if it isn't needed...

Inca
  • 1,534
  • 10
  • 11
2

Something like this

x.y.z.a[b].c

This smells like bio-hazard. This much member referencing is never ever a good sign.And yes this is a typical expression in the code I am working with.

Gaurav
  • 3,729
  • 2
  • 25
  • 43
2

Using a hidden object in the user interface (eg, a textbox) to store a value rather than define a properly-scoped and -typed variable.

MartW
  • 101
  • 3
2

Tightly coupled code. Especially when you see lots of things hardcoded (names of network printers, ip addresses, etc.) in the middle of code. These should be in a configuration file or even constants, but the following is just going to cause problems eventually:

if (host_ip == '192.168.1.5'){
   printer = '192.168.1.123';
} else
  printer = 'prntrBob';

Some day, Bob is going to quit and his printer will be renamed. Some day the printer will get a new IP address. Some day 192.168.1.5 will want to print on Bob's printer.

my favorite mantra: always write code like a homicidal psychopath who knows where you live will have to maintain it!

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
davidhaskins
  • 2,158
  • 2
  • 18
  • 26
2

Code that shows that the programmer never adapted, years ago, to Java 5:

  • Use of Iterators instead of “for each”
  • Not using generics in collections, and casting retrieved objects to the expected type
  • Using ancient classes like Vector and Hashtable

Not knowing the modern multithreaded ways.

Dave Briccetti
  • 400
  • 2
  • 7
2

This type of code:

        if (pflayerdef.DefinitionExpression == "NM_FIELD = '  '" || One.Two.nmEA == "" || 
            One.Two.nmEA == " " || One.Two.nmEA == null ||
            One.Two.nmEA == "  ")
        {                
            MessageBox.Show("BAD CODE");
            return;
        }

This is from a real live production codebase!

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
George Silva
  • 371
  • 1
  • 9
1

When the code looks like a mess: Comments with "todo" and "note to self" and lame jokes. Code that was obviously used at some point solely for debugging purposes, but was then not removed. Variables or functions with names that suggest that the writer did not consider that anyone would read it later. Often these names will be very long and unwieldy.

Also: If the code lacks rhythm. Functions of wildly divergent length. Functions that do not adhere to the same naming schemes.

Slightly related: It always makes me nervous if a programmer has slobby handwriting. Or if they are bad writers or bad communicators.

KaptajnKold
  • 933
  • 1
  • 6
  • 12
  • 1
    I was going to give you +1 but some of your comments are a bit of track. Best coder I ever met was also the most introverted person I ever met, took me 2 years just to get him speaking up for himself. And who cares about handwriting if you can type at 100+ wpm?? :D – Anonymous Type Oct 28 '10 at 22:37
  • Re. handwriting: I don't care if someone's handwriting isn't beautiful, but I do care if it's slobby and looks as if they couldn't even read it themselves. I'm really just talking from my own limited experiences, and yours may be different. – KaptajnKold Dec 15 '10 at 09:55
1

Anything that violates principles that are important. For instance, a few anti-patterns have been suggested (magic number -- see http://en.wikipedia.org/wiki/Anti-pattern). Anti-patterns are called that because they cause problems (also already mentioned - fragility, maintenance nightmares, etc). Also, watch out for violation of SOLID principles - see http://en.wikipedia.org/wiki/Solid_(object-oriented_design) Also, Code that doesn't consider separation of tiers (data access things inside the UI, etc). Having coding standards and code reviews help to combat this.

Tim Claason
  • 913
  • 7
  • 11
1

I once worked on a project where the contractor had tyepdef'ed every standard datatype from int to string including pointers to obscure names. His approach made understanding the code really difficult. Another style that warns me is premature flexibility; a product I once worked upon had the complete code in DLLs that were loaded in no predictable order. All this to accommodate future evolution. A few DLLs used thread wrappers for portability. It was a a nightmare to debug the program or predict the flow by reading the source code. Definitions were scattered across header files. It was no surprise that the code did not survive beyond second version.

VKs
  • 1
  • 1
1

Disgruntled comments demonstrating lack of restraint:

//I CAN'T GET THIS F^#*&^ING PIECE OF S$^* TO COMPILE ON M$VC

Either they're ill-tempered or they're not experienced enough to have learned that setbacks are inevitable in programming.

I don't want to work with people like that.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
Rei Miyasaka
  • 4,541
  • 1
  • 32
  • 36
1

Sometimes I see parts of a method that given all possible inputs, it would still NEVER run, so it shouldn't be there confusing people in the first place. An example would be...
If the method can only be called inside the context of an Admin superuser and I see something checking if the request user is not an Admin superuser... :/

chiurox
  • 1,498
  • 12
  • 17
1

Peephole optimizations on code that could be optimized with better structure, e.g. linear searches implemented in inline assembly when a binary search in plain C/C++/Java/C# would be appropriate (and faster).

Either the person is missing some fundamental concepts, or has no sense of priorities. The latter is much more worrying.

Rei Miyasaka
  • 4,541
  • 1
  • 32
  • 36
  • +1 - I just answered a question today where somebody was asking how to micro-optimize their Lua script that checks the distance between 800 vectors and [actively ignoring answers suggesting restructuring](http://stackoverflow.com/questions/6257148/lua-code-optimization-vector-length-calculation/6257315#6257315). – Stuart P. Bentley Jun 07 '11 at 02:02
1

The use of the synchronized keyword in Java.

Not that there is anything wrong with using synchronized when it is used right. But in the code I work with, it seems that every time someone tries to write threadsafe code, they get it wrong. So I know that if I see this keyword, I have to be extra carefull about the reste of the code ...

Guillaume
  • 745
  • 4
  • 7
1
  • $data - It's like advertising "Physical objects, now at a ridiculously low 100 per 5!"
  • TODO items in code - Use a bug/ticket/issue tracker so people know what's needed on a product level rather than a file level.
  • Work log in code - That's what version control is for.
l0b0
  • 11,014
  • 2
  • 43
  • 47
  • I think $data is a fine variable name in cases where you're writing a generic data processing/statistical function and one parameter is the dataset and the rest are configuration, etc. – dsimcha Mar 07 '11 at 00:42
  • @dsimcha: In such cases you can easily replace `$data` with something more usable, like `$samples` or `$magnitudes`. – l0b0 Mar 07 '11 at 10:12
1

@FinnNk, I agree with you about commented out code. What really bugs me is stuff like this:

for (var i = 0; i < num; i++) {
    //alert(i);
}

or anything that was there for testing or debugging, and was commented out and then committed. If it is only occasional, it is not a big deal, but if it is everywhere, it clutters up the code and makes it hard to see what is going on.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
Elias Zamaria
  • 154
  • 1
  • 10
1

This is a somewhat minor symptom compared to things others have listed, but I'm a Python programmer and I often see this in our codebase:

try:
    do_something()
except:
    pass

Which usually signals to me that the programmer didn't really know (or care) why do_something might fail (or what it does) -- he just just kept "fiddling" until the code didn't crash anymore.


For those coming from a more Java-esque background, that block is the Python equivalent of

try {
    doSomething();
} catch (Exception e) {
    // Don't do anything. Don't even log the error.
}

The thing is, Python uses exceptions for "non-exceptional" code, such as keyboard interrupts or breaking out of a for loop.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
mipadi
  • 7,493
  • 36
  • 35
1

Most of these are from Java experience:

  • String typing. Just... no.
  • Typecasting will often point to a code smell in modern Java.
  • The Pokemon Exception anti-pattern (when you gotta catch 'em all).
  • Cargo-cult attempts at functional programming where it isn't appropriate.
  • Not using a functional-like construct (Callable, Function etc) where it would be appropriate.
  • Failures to take advantage of polymorphism.
Ben Hardy
  • 101
  • 3
0

getters all over the place make me freak out.

and a special thing: getters delegating to other getters.

this is bad because it means the person who wrote that doesn't understand the basic of object-oriented, which is encapsulation, which means where the data is, the methods that act on that data should be.

delegation is for one method not all the getters. the principle is "tell, dont's ask"; tell one thing to an object to do, don't ask it for one thousand things and then do it yourself.

getters freak me out, cause it means other oop principles are going to be violated hard core.

Belun
  • 1,314
  • 8
  • 15
0

Missing type information.

Have a look at these method signatures:

  1. public List<Invoice> GetInvoices(Customer c, Date d1, Date d2)

  2. public GetInvoices(c, d1, d2)

In (1) there is clarity. You know exactly what parameters you need to call the function with and it is clear what the function returns.

In (2) there is only uncertainty. You have no idea what parameters to use and you don't know what the function returns if something at all. You are effectively forced to use an inefficient trial and error approach to programming.

Martijn Pieters
  • 14,499
  • 10
  • 57
  • 58
ThomasX
  • 19
  • 2