Bad Programming Habits We Secretly Love (infoworld.com)
snydeq writes: Breaking the rules can bring a little thrill — and sometimes produce better, more efficient code. From the article: 'The rules are more often guidelines or stylistic suggestions, not hard-and-fast rules that must be obeyed or code death will follow. Sure, your code might be ridiculed, possibly even publicly, but the fact that you're bucking conventions adds a little bit of the thrill to subverting, even inadvertently, what amounts more often than not to the social mores of pleasant code. To make matters more complex, sometimes it's better to break the rules. (Shhhh!) The code comes out cleaner. It may even be faster and simpler.' What bad programming habits can't you (or won't you) break?
If you think it's nice to break habits or do unconventional code just for the thrill of it, remember how fun it is when you need to work on someone else's code.
If the code comes out cleaner, you didn't break any of my rules. The rule "make the code as clean as possible" trumps all other rules.
Sure, you can trade maintainability for efficiency and reliability. People do it all the time. You just have to understand the costs involved. If the efficient code gains you a million dollars in performance, maybe you can afford for it to be crappy code. Or maybe you'll be running the code for 10 years, and if it costs you $250,000 to keep a crusty old engineer on staff who can maintain it, suddenly that million dollars in performance may not be worth it.
<disclaimer>I am a crusty old engineer.</disclaimer>
John
long methods - someone thought it a good idea to limit every method to no more than 20 lines. I think this is a terrible idea, and can make code unreadable, which leads to:
coupling - it's often best to tightly couple things for ease of debugging and development. How often are you going to change the database you're using? Is it worth going through another abstraction for every database call? Too much abstraction makes code unwieldy.
I'd rather have a bunch of 200 line methods that represent logical units of work than a call stack 20 layers deep.
In short, I suggest that the programmer should continue to understand what he is doing, that his growing product remains firmly within his intellectual grip. It is my sad experience that this suggestion is repulsive to the average experienced programmer, who clearly derives a major part of his professional excitement from not quite understanding what he is doing. In this streamlined age, one of our most undernourished psychological needs is the craving for Black Magic and apparently the automatic computer can satisfy this need for the professional software engineer, who is secretly enthralled by the gigantic risks he takes in his daring irresponsibility. For his frustrations I have no remedy......
--Edsger W. Dijkstra
Adding another variant, when you have an existing function that you never expected to reuse part of, suddenly interested in a twist on it. The 'proper' answer is to refactor so that it is shared code, but the code being reused is something that's not changed in 3 years and never had an issue under impressive load. So I could either refactor including changing working code, or duplicate. I'll duplicate. Now my duplicate may break out the relevant code so that if such a circumstance arise later, that the duplication won't happen twice, but I would rather a duplicate exist than risk any change to proven code.
XML is like violence. If it doesn't solve the problem, use more.
Also agreed about too many classes. People think they make nice modular things by having short classes, but I just went through an exercise of pouring through about a dozen mind numbingly tedious files to find the single line of code that actually did something rather than just do a few pointlessly segregated checks or providing an alternative function for what '+=' already did or coercion into some datatype only to have it coerced back 'just in case' that middle layer might one day have another developer that would naturally think of it another way...
XML is like violence. If it doesn't solve the problem, use more.
For any rule you can come up with, you can probably find a valid case where breaking the rule would result in better code. Even GoTo can be useful in certain circumstances. Most of the good uses of GoTo have been codified using other key words. .C# has the continue keyword. It's basically exactly the same as using a GoTo to skip processing the current item. GoTo would have accomplished the exact same task, but people have such a dislike of GoTo that they had to create a whole other keyword that does exactly the same thing.
Anthropic principle: We see the universe the way it is because if it were different we would not be here to see it.
Wow. WAY too much code for what it actually needs to be. Furthermore the fix functions have now leaked scope all the way to main().
The boss or the developer?
Yes.
"Our two-party system is like a bowl of shit looking at itself in a mirror." - Lewis Black
We are hired to write new programs/new ways of solving a problem. Rules are made to solve common problems.
If we only follow these rules we are limited to writing programs that have already been written, in that case we are just useless.
If we know when to bend or break the rules, then we can create things that solve problems differently and is new and unique.
When I work with programmers so are hard fixed on the right way to do things, I often get a response that x cannot be done. I break the rule and I have done it in a couple of days work, then they will go but you didn't follow the right form.
The end user doesn't care about form, they care if it Works well, It can be maintained, and it is secure.
If something is so important that you feel the need to post it on the internet... It probably isn't that important.
He's still trotting out "rules" that were in vogue 15 years ago. Break, continue and early return are clean and inserted into every programming language eventually.
Peter predicted that you would "deliberately forget" creation 2000 years ago...
It seems that many in the field these days are afraid to code something themselves for fear that someone will find fault. So, they do things "the established" way, which is generally frameworks or anything that can be called "reusable", even if this generation's "reusable" is always less reusable than last, because it keeps getting needlessly more complex to the point that nobody *can* reuse it.
Used to be programmers had a fault we called "not invented here", in that they'd insist on re-writing things that already existed, because it was easier to understand their own code than to use someone else's. These days it's reversed. For fear of criticism, they *must* use someone else's code rather than write their own. I call it "afraid to invent it here."
So far we have 3 comments with the "right" way to do it that do nothing but add complexity and loss of readability for strict adherence to dogmatism imparted by our CS professors (few of whom had real-world programming experience).
This is a straightforward problem. The suggested use of goto is a straightforward solution, and cleaner by far than the suggested alternatives. But most importantly, no one can demonstrate how it is wrong.
I've been programming for quite awhile and honestly I'm in the verbose commenting camp.
Not because I'm worried about code reviews, handing the code off to anyone else or even following some company's arbitrary rules on how things should be documented.
I use verbose comments so I don't have to remember what was done and why it was done that way. Frankly I've got too many other things that I'd rather remember.
Granted verbose comments will make my code seem pretty old school, but I have yet to hear any questions from someone who picked up my code after I've left it.
And I can go back to code and know what I was doing even if it was 5 years ago. Now I may laugh at myself and be amazed at just how much I didn't know even then, but I will totally understand what's in the code without having to guess.
Unit tests are no match for years of reliable service because for useful programs there is no such thing as a comprehensive unit test. One of the reasons computers are so useful is they can handle so many different input values - so many that you can't possibly test them all. Want to test a '+' operator for integers? Unless you run all MAX_INT * MAX_INT (oh way, I mean MAX_INT - MIN_INT+1 * MAX_INT-MIN_INT +1) possible inputs, how can you be sure you got everything? Well, let's just pick a representative test. Oh wait, we need to make sure we try with a negative number. Oh yeah, we need to a negative+negative, a positive+positive, a positive+negative, and a negative+positive. That it? Oh yeah we need to try negatives positives with zeros too. NOW we're done. What? OOHHH overflow! We need to write a test for two very large positive numbers and another for two very large negative numbers!
That's just for simple integer addition. When you start writing real-life code the combinations of inputs grow very quickly. You do your best, but it simply isn't practical to test for every possible thing that could cause a problem.
I often don't like the choices people make, but I like the fact that people make choices. That's why I'm a conservative.