×

Welcome to the Slashdot Beta site -- learn more here. Use the link in the footer or click here to return to the Classic version of Slashdot.

Thank you!

Before you choose to head back to the Classic look of the site, we'd appreciate it if you share your thoughts on the Beta; your feedback is what drives our ongoing development.

Beta is different and we value you taking the time to try it out. Please take a look at the changes we've made in Beta and  learn more about it. Thanks for reading, and for making the site better!

How to Keep Your Code From Destroying You

ScuttleMonkey posted more than 6 years ago | from the i-have-been-sent-here-to-destroy-you dept.

Programming 486

An anonymous reader writes "IBM DeveloperWorks has a few quick tips on how to write maintainable code that won't leech your most valuable resource — time. These six tips on how to write maintainable code are guaranteed to save you time and frustration: one minute spent writing comments can save you an hour of anguish. Bad code gets written all the time. But it doesn't have to be that way. Its time to ask yourself if its time for you to convert to the clean code religion."

cancel ×
This is a preview of your comment

No Comment Title Entered

Anonymous Coward 1 minute ago

No Comment Entered

486 comments

Who wrote that article? (2, Funny)

Anonymous Coward | more than 6 years ago | (#19325729)

Captain Obvious?

Re:Who wrote that article? (1, Insightful)

endianx (1006895) | more than 6 years ago | (#19325889)

I agree. This is very basic stuff you would learn in Intro to Programming, or in any other article on the subject. Nothing new here.
I highly recommend a book called Code Complete. It is kinda pricey and, yes, it is by Microsoft, but I found it to be both helpful and thought provoking.

Re:Who wrote that article? (3, Informative)

jjrockman (802957) | more than 6 years ago | (#19326291)

Not to nitpick, but it's not "by Microsoft". It's published by Microsoft, but written by Steve McConnell of Construx.

Re:Who wrote that article? (5, Informative)

KingSkippus (799657) | more than 6 years ago | (#19326117)

Maybe it was the note at the top of the article that says, "Level: Introductory."

Maybe it was the author's comment at the end that said, "At this point, you may be thinking, 'Wow. That was a big waste of time. All of this stuff is obvious and everyone knows it. Why did anyone write all of this?' I hope this is what you're thinking. Then you're already smart. Good for you."

But somewhere along the course of reading the article, I got the impression that he wasn't writing it for professional developers (at least, smart ones), but for people relatively new to programming.

But then, maybe I'm just stating the obvious, Cap'n...

Re:Who wrote that article? (3, Insightful)

seaturnip (1068078) | more than 6 years ago | (#19326399)

Somewhere along the course of reading the article, I also got the impression that he wasn't a professional developer himself (at least, a smart one).

Re:Who wrote that article? (1)

efence (927813) | more than 6 years ago | (#19326119)

Right at the end of the article:

At this point, you may be thinking, "Wow. That was a big waste of time. All of this stuff is obvious and everyone knows it. Why did anyone write all of this?" I hope this is what you're thinking. Then you're already smart. Good for you.
You can pat yourself on the back now.

Re:Who wrote that article? (4, Interesting)

Enselic (933809) | more than 6 years ago | (#19326121)

I wonder what mushrooms he were on when he came up with that coding style... (yes, this is the actual indentation he used):

Void change_score(short num_points)
{
    if (num_points < 0)
{
// maybe some error message
        return;
}

    score += num_points;

    if (num_points > 0)
make_sparkles_on_score();
}

Re:Who wrote that article? (2, Insightful)

Swizec (978239) | more than 6 years ago | (#19326383)

You'd be surprised by how many programmers who have gone to actual rpogramming classes fail at anything as simple as indentation. Peopel jsut aren't taught this at school so either they are wise and learn it themselves or they read somewhere about how to code like a human being and not a thousand monkeys on typewriters.

The article may be redundant to many, but I can name at least twenty people off the top of my head taht should give this a long hard read and then read it again.

Re:Who wrote that article? (1, Interesting)

Anonymous Coward | more than 6 years ago | (#19326409)

About the author Jeff Vogel Since 1994, Jeff Vogel has run Spiderweb Software. He has written a dozen or so fantasy role-playing games for Windows and Macintosh, including the award-winning Exile, Avernum, and Geneforge series. He is the author of The Poo Bomb: True Tales of Parental Terror and other humorous writing. He lives in Seattle.
sorry i can't get information about any special power

fp (-1, Offtopic)

Anonymous Coward | more than 6 years ago | (#19325775)

/.ers are gay as usual.

the self proclaimed clerisy.

eadad (if you remember that acronym)

still trollin 4 profits.

someone bite. :`(

do you color your hair with rainbow colors? (0)

Anonymous Coward | more than 6 years ago | (#19326265)


  ??????????? [flickr.com]

Reason: Your comment looks too much like ascii art.

Reason: Your comment looks too much like ascii art.

Reason: Your comment looks too much like ascii art.

The whole article is -1 redundant. (2, Insightful)

rah1420 (234198) | more than 6 years ago | (#19325781)

Comments, clarity, constants. If you're not doing this in your daily coding exertions, you deserve to have to maintain your own stuff 10 years from now.

I have. It ain't fun. Not that I'm bragging on myself, but I've now had people from the support group stop me in the hall and compliment me on the quality of the code I've written and deployed.

Re:The whole article is -1 redundant. (1)

bluephone (200451) | more than 6 years ago | (#19325865)

I agree. It's the old concept of investment. Investing a little now is worth a lot more later. Investing one more minute now in commenting your code saves hours of puzzling later when you need to edit it.

Re:The whole article is -1 redundant. (4, Funny)

jstretch78 (1102633) | more than 6 years ago | (#19326299)

I agree, but could all those hours of puzzling actually improve your ability to understand poorly written code? I've been using comments sparsely for years and have spent much time fustrated. But I've found that I can 'See the Code' like on the Matrix and bend spoons and shit.

Re:The whole article is -1 redundant. (0)

Anonymous Coward | more than 6 years ago | (#19326465)

I for one, bend peoples MIND with my SPOON.

Re:The whole article is -1 redundant. (3, Informative)

Anonymous Coward | more than 6 years ago | (#19325989)

I am trying to maintain code written by a senior designer (logic code). This developer did not believe these rules. It is hell. This is not redundant.

Basics (2, Insightful)

Joaz Banbeck (1105839) | more than 6 years ago | (#19326115)

Ok, yeah, it's redundant. But is there anything wrong with going back to the basics? Look at sports figures ( and I chose sports for an analogy because most pro sports are very good at filtering out all but the best, and the very best get to the top by proving that they are better than the second best in head to heah competition, something that programmers almost never do. ) The best often are known for continually going back to basics.

Lombardi was known for his comment that if you block and tackle better than the other guy you win.

Magic Johnson was known for being on the court an hour earlier than the other pros and practicing shot after shot.

And Bobby Fisher's guide for beginners is still the best because he knew the basics like nobody else.

Re:The whole article is -1 redundant. (1)

mstahl (701501) | more than 6 years ago | (#19326471)

The whole article is -1 redundant.

You'd think so, but I think there are enough examples [worsethanfailure.com] out there to show that there are a lot of people out there writing sub-standard code and thinking there's nothing at all wrong with it. There have been a lot of times when I was tutoring computer science in college where I'd ask a student, "Just what in the hell were you doing here?" and point to some ridiculous incantation in their code.

In particular I think people ignore that last two when they're in school, because everybody wants to look impressive and figure out the "best" way to approach the problem at hand. What takes maturity and experience to realize, though, is that elegant simplicity will always win above arcane obfuscation.

I'm not defending bad code here. I'm just saying it happens so often it's hard to really hard to criticize so much.

That was just terrible... (5, Insightful)

FortKnox (169099) | more than 6 years ago | (#19325801)

That has to be the worst written article on cleaning up your code I've ever read.
This looks like it was written for (and BY) freshmen CS majors.

Comment your code smartly? No shit?
Use #defines everywhere? Honestly, I find that having a config file (or DB table) is a lot better, as I can change global variables without even a recompile...

I'm not saying its BAD advice, its just advice that anyone in the real world already knows.
How about something new?
1.) Use test driven development
2.) Write complete unit tests, including bad input
3.) If any piece of code is complex enough to require a comment, make it its own function and comment the function. I believe the only thing that REQUIRES comments are classes and methods. Not pieces of code...

I code go on, but I'm not a writer...
And neither is the author of that pile of trash...

It was fine... (5, Insightful)

Erasmus (32516) | more than 6 years ago | (#19325981)

People who are just starting their careers as programmers are allowed to read articles too. Just because something is aimed at a population less experienced than you doesn't mean that it's crap!

I'm not sure if it really called for a Slashdot entry, but I've been on a few projects with new coders where a quick read of something like this on their parts would have saved everyone a lot of grief.

Re:That was just terrible... (0)

Anonymous Coward | more than 6 years ago | (#19325995)

That has to be the worst written article on cleaning up your code I've ever read.
This looks like it was written for (and BY) freshmen CS majors.
Well the guy has been around in the Mac world forever, without about the worst looking games you'll ever see on that platform (even back in the 90s, they were utter garbage.)

I don't believe he's published anything in years-

He's probably not the best guy to give advice on coding.

Re:That was just terrible... (4, Interesting)

Sax Maniac (88550) | more than 6 years ago | (#19326029)

Right, I laughed at that #define remark, it's so green.

The real thing is to used named constants where it makes sense. #define is the crudest approximation of that, C can use enums, C++ can use "const" for compile-time values, etc.

In a real project, you have to scope your constants otherwise you'll have a billion of them in "everything.h" and every time you touch it, the world will rebuild. So nix the "centrally located" file theory.

In a real project, your constants will often have interdepedencies on other bits of code, so changing one will frequently affect the others. Heck, maybe changing one will cause it not to compile. This example makes them all trivial to the point of uselessness. Shuttling it off miles away in an #include file, can frequently give the impression this than can be changed with no effect on anything else.

Re:That was just terrible... (5, Insightful)

AuMatar (183847) | more than 6 years ago | (#19326041)

Not every program uses a db. In fact the majority of programs don't. And unless a constant is going to change frequently, or needs to be configured per client, putting it in a configuration file or db table is a bad idea. It makes it fairly likely it will be changed by accident. The only things that should be in configuration files are things you actually expect the user to configure per install.

As for your advice

1)Thinking about testing early- good. Writing unit tests-good. The test driven development mentality (write tests instead of design, write unit tests before coding)- bad. It leads to a lot of wasted time, completely rewritten test suites, and throw away work. Thinking about testing early is useful, it may cause you to think about corner cases. But writing them first causes 2 problems- you end up writing the code to solve the tests (rather than solving the problem) and/or you end up throwing away half the test suite in the middle when you refactor the design.

3)Disagree. The purpose of comments is to make sure that maintainers know what the code is trying to do. Anything block of code thats more than 5 or 6 lines deserves a comment. Breaking all of those into independent functions leaves you with hundreds of 5 or 6 line functions, which is even harder to understand how they interact. Frequently the correct thing to do is not break it into a function and just write a 1 line comment.

Re:That was just terrible... (1)

FortKnox (169099) | more than 6 years ago | (#19326283)

I accept most of your arguments, except for TDD, which I have used to success...

...The test driven development mentality (write tests instead of design, write unit tests before coding)- bad. It leads to a lot of wasted time, completely rewritten test suites, and throw away work. Thinking about testing early is useful, it may cause you to think about corner cases. But writing them first causes 2 problems- you end up writing the code to solve the tests (rather than solving the problem) and/or you end up throwing away half the test suite in the middle when you refactor the design.

TDD (for me, at least) helps with the design. You can't just start writing test cases, it forces you to 'stub out' your entire design. In this process, I can immediately start seeing problems and reworking it. Its only after I have a good design that I start writing test cases. And refactoring of the design may kill some test cases, but it keeps a good portion alive, which can be almost a 'regression' test of the refactored code, so it all still passes the tests that are still valid...

Re:That was just terrible... (0)

Anonymous Coward | more than 6 years ago | (#19326427)

Anything block of code thats more than 5 or 6 lines deserves a comment. Breaking all of those into independent functions leaves you with hundreds of 5 or 6 line functions, which is even harder to understand how they interact.
That style of programming is common in Smalltalk. I think it works well when you get used to it: the text reads like simple prose, just method invocation after method invocation. Each method is small enough that you can understand it directly, and it has an expressive name. You don't want hundreds of methods in a single class, of course; that's a sign that you need a better class hierarchy.

It helps that in a Smalltalk environment, you commonly have

1. Simple uncluttered syntax involving only composition of methods
2. Expressive descriptors ('view plotX:10 Y:10 color:#RED' instead of 'view.plot(10,20,RED)')
3. A refactoring multipane code browser to easily browse and reorganize your code (not that you can't get that for other languages)

"Self-documenting code" is a myth, but this style comes closer than many others I've seen, when done right. The C3 project had an average method length of 3.8 lines ...

Re:That was just terrible... (0)

Dancindan84 (1056246) | more than 6 years ago | (#19326181)

Agreed. This is year one CS stuff. If you haven't learned this you shouldn't be coding in the first place.

What's next, a ground breaking article on how QA testing is important?

shouldn't be coding... (1)

Kalzus (86795) | more than 6 years ago | (#19326279)

Probably shouldn't. But possibly will be. And this hypothetical person won't be alone :(

Re:That was just terrible... (3, Interesting)

Coryoth (254751) | more than 6 years ago | (#19326251)

1.) Use test driven development
I'll go you one better. Use specification driven development. That is, use a combination of contracts an unit tests. If your method has general constraints, or your object has an invariant, write it into the code using contracts (and ideally use a system that will let your subclasses inherit contracts, and allow contracts to be sucked up and included in the API documentation); if your methods specification is only easily expressed as a set of mappings from input to expected output, write a unit test instead. When you run your unit tests the contracts will automatically get tested too. Better yet, by using contracts you can help yourself on:

2.) Write complete unit tests, including bad input
by using the contracts as a test oracle and passing in randomly generated data to really flesh out the corner cases. In some cases you can do this in a purely automated fashion [inf.ethz.ch] at the push of a button. Contracts also have the benefit of: (1) not requiring the biolerplate code of unit tests, so they're faster to write; (2) respecting inheritance which can save you a lot of extra test writing. You can't always easily write contracts for methods, and in those cases unit tests make sense, but you may as well take full advantage of contracts for the parts that can be handled in that manner.

Re:That was just terrible... (1)

DigitalCrackPipe (626884) | more than 6 years ago | (#19326433)

I'd suggest that commenting the function calls may also be needed at times, such as when calling a legacy function that has tricky (or just plain inappropriate) calling conventions or side effects. I see plenty of places where a comment is useful for 2-3 lines of code, and it would not be appropriate to make a function out of all of those instances.

Re:That was just terrible... (1)

seaturnip (1068078) | more than 6 years ago | (#19326459)

Not to mention, the "never optimize prematurely" advice can be very dangerous if applied blindly. By all means wait until later to optimize inner loops, but don't commit yourself to an architectural decision that implies performance can never be improved. You'd think a game developer of all people would understand this.

Use a language that checks I/O errors by default (4, Insightful)

mkcmkc (197982) | more than 6 years ago | (#19325809)

It's amazing how much simpler life is if your language will check errors (esp I/O errors) by default. That is, if you do a write and if fails (e.g., because the disk is full), an exception gets thrown, and even if you haven't written any error handling code at all, you get a nice explanatory error message.

C, C++, and Perl are not "safe" in this sense. Python is. Not sure about other common languages.

Re:Use a language that checks I/O errors by defaul (3, Insightful)

LiquidCoooled (634315) | more than 6 years ago | (#19326039)

Relying on the environment to do all cleanup leads to bad code.
Every time you create something, destroy it afterwards.
Assume every action will fail and handle it appropriately.

I have seen 'developers' assume everything will be taken care of, then when the software gets into the users system their usage patterns make it explode.

Simple management needn't make a development time longer or harder and allows you to migrate things to other applications/systems with ease.

Re:Use a language that checks I/O errors by defaul (1)

LiquidCoooled (634315) | more than 6 years ago | (#19326177)

Additional to this, if the 'nice' language features give the user an error message and bails, what happens to the intermediate steps you were performing?
Not everything fits inside a nice transaction and sometimes things need cleaning up.
It might be the final step in a long list of sequential actions, or it might just be a few easy steps but you can be sure of one thing:

If your program keeps kicking them totally out of the system (no matter how 'nice' the message) for a stupid simple handleable errors they will be pissed off.

Hey, kids! Test your Wikipedia street smarts! (-1, Offtopic)

Anonymous Coward | more than 6 years ago | (#19326165)

Which of the three passages below is the authentic excerpt from Wikipedia?

  1. Conan Christopher O'Brien, 44, is the comedian and the host of The Tonight Show With Jay Leno. He is Scottish, as were his parents, as well as his three brothers and two siblings. He has no relation to CNN anchor Soledad O'Brien.

    O'Brien, who is 43, is commonly thought by television audiences to be of diminutive stature, though some journalists and alternative biographers dispute this claim.

    As of 2007, O'Brien has been confirmed dead of tuberculosis. His hair color was red. He was 45.

  2. {This page is currently protected from editing until disputes have been resolved.}

    [Image:KarlMarx.jpg]
    United States President Abraham Lincoln was President of the United States during the Revolutionary War, and a well-known Libertarian.[1] Though some historians see Objectivist tendencies in his greatness.[2][3] Many of his most generous qualities can be traced back to the philosophy of Ayn Rand.[4]

    Lincoln is now known to have suffered a mild form of Autism known as Asperger's Syndrome.[5][6][7]

    Assassinated at 54 by a vandal known as Jon Harvey Booth,[8] or some say by political crony Edwin Stanton, Lincoln would have been 187 years old today (as of 2005)[original research?] had he not been assassinated in the prime of his life at the age of 45 by unemployed actor Juliette Lewis Botch.[9]

  3. The Pokédex (Pokemon Zukan[?], lit. "Pokémon Encyclopedia") is an electronic device designed to catalogue and provide information regarding the various species of Pokémon featured in the Pokémon video game and anime series. The name Pokédex is a neologism including Pokémon (which itself is a portmanteau of pocket and monster) and index. The Japanese name is simply "Pokémon Encyclopedia" in Japanese.

    In the video games, whenever a Pokémon is first captured, its data will be added to a player's Pokédex. In the anime the Pokédex is a comprehensive electronic reference encyclopedia, usually referred to in order to deliver exposition. There are four differently numbered Pokédex modes to date: the Kanto Pokedex, introduced in Pokémon Red and Blue; the Johto Pokédex, introduced in Pokémon Gold and Silver; the Hoenn Pokédex, introduced in Pokémon Ruby and Sapphire and expanded upon in Pokémon FireRed and LeafGreen; and the Sinnoh Pokédex, introduced in Pokémon Diamond and Pearl.

Please check your errors. (1)

bill_mcgonigle (4333) | more than 6 years ago | (#19326307)

C, C++, and Perl are not "safe" in this sense. Python is. Not sure about other common languages.

Please check your errors. I see far too many projects coded in Python that just barf stacktraces to the console if anything unexpected happens.

Java has the advantage that it *makes* you handle your errors, even if you choose to do so poorly.

Re:Use a language that checks I/O errors by defaul (0)

Anonymous Coward | more than 6 years ago | (#19326369)

Its amazing how many people buy into this nonsense. I bet you think java stack traces are in any way useful to the end user as well? They must be a heck of a lot smarter than me cause I can't make heads or tails about what I should do as an end-user to address exceptions that are simply punted to the top.

In reality just the opposite is true. By buying into exception handling and just expecting things to be handled by passing responsibility up the stack what you are really doing is loosing control and ownership the system along with the ability to systematically verify that *ALL* possible conditions are handled acceptably well.

Its very easy to audit code and find all cases where return codes are not checked. Can you say the same for exceptions? How do you systematically know weather its ok for a particular exception to be punted or even what exceptions can possibly be generated by black boxes under you?

In some areas this may very well be an acceptable response. However trading off programmer laziness for lower levels of reliability especially in server codes is a rediculous tradeoff.

Using a language that ensures reasonable "islands of sanity" can be maintained (sections of code that can't fail unless the CPU does) is absolutly essential. Interpreted languages that do everything for you scare me sometimes however they are very useful for a wide range of purposes.

Re:Use a language that checks I/O errors by defaul (1)

CastrTroy (595695) | more than 6 years ago | (#19326407)

This relates to my biggest gripe about VB.Net. Any function can throw any exception, and you have no way of knowing, apart from looking at source code or documentation what kind of errors any specific function might throw. So basically all errors become runtime errors. This is one place where I wish VB.Net would copy from Java. If the function is going to throw an exception, it should be an compilation error if you aren't catching it. Also, related to this, when using ASP.Net, the debugger never breaks on uncaught exceptions, because effectively they are all caught at some level by the web server, so you have to break on all errors which causes a lot of wasted time as it breaks on internal errors in the .Net framework that are caught internally.

What about legacy code? (1)

peopleAreTheProblem (1106781) | more than 6 years ago | (#19325821)

The article has some good pointers. But what if you not the one who wrote the code (Developer hired to finish another developers work)? What can I do to minimize the nightmare of work required to deal with tightly coupled, non documented, and hard to read code? It would be nice if there was an article that could help with that.

Re:What about legacy code? (1)

Applekid (993327) | more than 6 years ago | (#19325969)

I throw in comments as I see them. If I just spent hours tracing dragon code, I'm sure as hell going to put a comment in there so I don't have to do it again.

Re:What about legacy code? (1)

SomeWhiteGuy (920943) | more than 6 years ago | (#19326313)

I'm having to deal with that right now. There is no real way to deal with it. Comment what you put in and move on. The legacy will just have to live on. We currently have a variable that is never used but declared in our main application called ken_is_a_jackass. This boolean is set to true but never mentioned again in code. Good and bad comments/code will stay with a system long after you're gone. Ken has apparently been a jackass for over 12 years and nobody seems to want to get rid of it.

Re:What about legacy code? (1)

CastrTroy (595695) | more than 6 years ago | (#19326449)

Before add any new features or fix old bugs go through the code and comment everything you can. It may not be feasible for a large project, but at least go through and comment the stuff you're going to work on before you change anything. Don't be afraid to write down comments stating that you have no idea what's going on, and some kind of easily searchable tag so that you can go back later to figure out what's going on. Also, don't be afraid to rewrite large sections of code if you really think it will make it a lot cleaner and easier to understand. Oh, and always use source control so you can go back and see what the original code was doing.

Summary: Beginners need tips too. (5, Informative)

Palmyst (1065142) | more than 6 years ago | (#19325883)

The article is suited for beginning programmers, I guess. Here is the summary of the tips.

1. Comment smartly.
2. Name your constants ("use #defines").
3. Descriptive variable names, but not too long.
4. Handle errors.
5. Avoid premature optimization.
6. Clarity is better than cleverness.

The author may not be a beginning programmer, but it appears that he might be a beginning writer on programming.

Steps for Job Security (2, Funny)

Mr Pippin (659094) | more than 6 years ago | (#19326163)

Yep, no you need to include the "Back To School" basic programming techniques, like Rodney Dangerfield might include.

1. Use comment syntax to obfuscate the actual running code
2. Don't indent or "pretty format" your code
3. Use the same variable name over and over, capitalizing different letters to make them unique throughout the program
4. Use variable names that are incredibly offensive in hindu, so any common "outsource" programmer will refuse to work on the code.
You get the point.

Re:Summary: Beginners need tips too. (1)

P3NIS_CLEAVER (860022) | more than 6 years ago | (#19326515)

For the rest of us I recommend "The Pragmatic Programmer" by Andrew Hunt and David Thomas.

Expected Value (5, Funny)

dcollins (135727) | more than 6 years ago | (#19325901)

"One minute spent writing comments can save you an hour of anguish."

However, what's the probability that the savings actually goes to *you* and not a coworker competing with you for a promotion, or someone who replaced you in a later year? If you work in an office with 100 staff, let's say 1%. So expected savings to you is EV = 1% x 60 minutes = 0.6 minute, less than the minute it takes to write the comment. (Even assuming the payoff is correct, and then helping competing coworkers doesn't do any damage to you.)

This is what I consider to be the "tragedy of the commons" for software engineering jobs. When I was a programmer, the people who did the least documentation were the fastest, and often the only folks who could approach certain parts of code, and so held in the highest esteem by the executives. Now I only write code for my own projects.

Re:Expected Value (2, Insightful)

jfengel (409917) | more than 6 years ago | (#19326429)

This is also one of those "Check mark: $1 Knowing where to put it: $49,999" problems. It takes you a minute to comment a function... times 50 methods a day... times the 1% of comments you ever actually need to go back and read.

Suddenly that "one minute" is a lot of hours spent writing comments that you'll never read, cluttering up your code and getting wronger as you don't maintain them.

If I knew which comment to write, sure, I'd write it. And I do, when I think it's appropriate. There are plenty of times I wish I'd commented something, but they're way outweighed by times I didn't bother. Good function and variables names are more important to me.

If you can't come up with a good name, refactor until you can. A unit of code should do something coherent and easily describable, preferably until you don't need a comment.

Yeah, you'll have to document dependencies, but you should keep them as few as possible. A good language decreases dependencies. I don't have to write "I expect you to free the space for this string" or "This string is stored in a static; do not reuse" because I write in Java.

Re:Expected Value (1)

Palmyst (1065142) | more than 6 years ago | (#19326505)

Good point. In my very long experience in this industry, the star programmers cobble something together as fast as possible without worrying about maintenance or documentation. What documentation there is is just the minimum that is needed for various members of the team to work together to make release 1.0, not something that will help future maintainers of the code very much. After release 1.0, they cash in their chips and move on to The New New Thing (yes, I am specifically referring to certain people in that book), and leave the system to be maintained by someone else with less cachet.

Mostly agreed (5, Insightful)

ZorbaTHut (126196) | more than 6 years ago | (#19325913)

I thought I'd make two comments on things that I think he got a bit wrong.

Tip 2: Don't use #define. Avoid it as best as you can. Use const int. That's what it's for. It will be typechecked by the compiler, it's much harder to produce bizarre errors, and 99% of the time it's better.

const int NUM_ALIENS_TO_KILL_TO_END_WAVE = 20;

Tip 4: Warning messages don't work. Don't bother with them. Use assert() - if it triggers, your program will crash with a useful error message. Now that's an incentive to make things work!

In my current project, out of 25,000 lines of code, I have almost 1100 asserts. And the first number counts whitespace. Any bugs I have get found and squashed pretty much instantly.

Re:Mostly agreed (1)

EvanED (569694) | more than 6 years ago | (#19326069)

Don't use #define. Avoid it as best as you can. Use const int. That's what it's for. It will be typechecked by the compiler, it's much harder to produce bizarre errors, and 99% of the time it's better.

With the caveat that you're not working in C. Unfortunately, even in C99 consts are broken in that they can't be used as array bounds:

const int S = 10;
int i[S];
 
Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for ONLINE_EVALUATION_BETA1
Copyright 1988-2007 Comeau Computing. All rights reserved.
MODE:strict errors C99 noC++0x_extensions
 
"ComeauTest.c", line 2: error: expression must have a constant value
  int i[S];
        ^
Anyone have an explanation for this?

Re:Mostly agreed (2, Informative)

ZorbaTHut (126196) | more than 6 years ago | (#19326131)

Fair enough. His post was talking about C++, and I'm a C++ coder myself, so I wasn't aware of the weird C problem.

I guess if you're forced to use pure C, it could be an issue, but I would personally just compile it as C++ (remember, you don't have to use all the C++ features if you don't want to.)

Re:Mostly agreed (1)

EvanED (569694) | more than 6 years ago | (#19326207)

...I would personally just compile it as C++ (remember, you don't have to use all the C++ features if you don't want to.)

This doesn't work if you're working on legacy code that must be compiled as C.

Re:Mostly agreed (1)

EvanED (569694) | more than 6 years ago | (#19326275)

I should say that I'm not trying to be argumentative, just that overall "use this" rules (both use #define a lot and never use #define) are dumb.

CPP macros are very useful even in C++ as a code generation technique for instance. Using them as constants or inline functions is bad practice, but there are uses.

And in both languages, keep them distinct from names people might use independently. For instance, don't name a macro "current" [linux.no], lest you cause a newbie 15 minutes of frustration and swearing at GCC for nonsensical error messages. (I have to work that gripe into any discussion of CPP macros. ;-) )

Re:Mostly agreed (2, Insightful)

ZorbaTHut (126196) | more than 6 years ago | (#19326325)

Why "must"? Almost all C code compiles fine as C++ code, and the few things that won't (generally involving implicit casts to void*, as I understand it) aren't too hard to fix.

I mean, unless you're using K&R C, in which case I feel very sorry for you.

Re:Mostly agreed (0)

Anonymous Coward | more than 6 years ago | (#19326489)

Struct_t *ptr = malloc(sizeof *ptr);  -- This is the correct way in C, but it is invalid C++
Struct_t *ptr = (Struct_t *)malloc(sizeof *ptr); -- Needed for C++

In C the return value of malloc will always be correct for the pointer, casting the return value
just hides bugs.

Re:Mostly agreed (0)

Anonymous Coward | more than 6 years ago | (#19326139)

Easy: C doesn't have constants. Only readonly variables.

Re:Mostly agreed (1)

Sciros (986030) | more than 6 years ago | (#19326225)

I'm a bit rusty on my C++, but assert() statements in Java are discouraged in anything besides testing, since invoking them is a runtime config and is off by default in some environments. So, production code shouldn't have asserts() if it's Java.

Re:Mostly agreed (2, Informative)

ZorbaTHut (126196) | more than 6 years ago | (#19326371)

In fairness, I don't actually use assert() - I have my own macro that I use that is turned on in both debug and release mode. But in effect it's an assert() that always runs.

You're right, though - that's one of the more annoying "features" of assert. Luckily assert() is not a particularly hard thing to rewrite.

Re:Mostly agreed (1)

ookabooka (731013) | more than 6 years ago | (#19326335)

Don't use #define. Avoid it as best as you can. Use const int.

Wouldn't that be slightly less efficient? Wouldn't that allocate memory to hold the value rather than having a literal in the program code? Would be disaserterous if it caused a cache-miss too, you coul lose a lot of efficency there. Anyone know how various compilers handle const ints?

Re:Mostly agreed (2, Informative)

ZorbaTHut (126196) | more than 6 years ago | (#19326439)

Since the compiler knows that the int can't ever change, the compiler can easily inline it, giving you exactly the same performance as #define. I believe that most compilers only bother allocating space for the int if you try to take the address of it in some way.

I suspect they only do this in release mode, of course.

const x #define (1)

marcosdumay (620877) | more than 6 years ago | (#19326527)

"Wouldn't that be slightly less efficient?"

No.

"Wouldn't that allocate memory to hold the value rather than having a literal in the program code?"

No.

"Would be disaserterous if it caused a cache-miss too, you coul lose a lot of efficency there. Anyone know how various compilers handle const ints?"

No, and you can't really know whre a cache miss will happen unless you know exactly what computer will run that code.

Your compiler knows that a const is constant, and won't throw memory (and lookup time) away with it. Unless, of course, you want to debug. And you shouldn't be thinking about cache size while targeting the (quite heterogeneous) PC.

Re:Mostly agreed (1)

nonsequitor (893813) | more than 6 years ago | (#19326507)

Does the use of const int vs #define compile any differently? I work mostly with small embedded projects where every byte counts, though I've always trusted the compilers to handle the optimization and the standard seems to be #defines rather than const int across several companies I've worked at. Though IIRC #defines are resolved by the precompiler rather than the compiler which may result in smaller executable size since there would be less overall symbols in the symbol table. Since it may be that all constants with a value of 5 are resolved to the same one byte symbol, while if you have several constant int's with a value of 5 they each get their own word in the symbol table, depending on how smart your compiler is. That could be a legacy habit carried forward from older compilers though.

The fact you can even use assert()'s means you work in a vastly different arena than myself, I'm lucky if I get more than 3 breakpoints at a time. So I do input sanitization similar to described in the article.

Updating comments... (1)

Etherwalk (681268) | more than 6 years ago | (#19325921)

Um... well, duh.

But aside from simply commenting, *updating* comments is also important, and possibly more so. Looking at the history of the TCP/IP source in OSX, for example, you see wonderful instances of complex code that's been updated as new operating systems have been built on top of it, but comments reflect the old behavior rather than the new.

It's very simple (0)

Anonymous Coward | more than 6 years ago | (#19325931)

A good programmer writes code to be executed efficiently by a machine.

A master writes code to be read efficiently by human beings.

That is all.

I thought #defines were deprecated in C++ (4, Insightful)

dpbsmith (263124) | more than 6 years ago | (#19325937)

Not that I don't use them a lot myself, but I thought that in C++ you were supposed to try to avoid the use of macros altogether, and in particular were supposed to use consts for, well, defining constants.

I.e. not

#define PIXEL_WIDTH_OF_PLAY_AREA 800
#define PIXEL_HEIGHT_OF_PLAY_AREA 600

but

const int PIXEL_WIDTH_OF_PLAY_AREA=800;
const int PIXEL_HEIGHT_OF_PLAY_AREA=600;

Re:I thought #defines were deprecated in C++ (1)

AP2k (991160) | more than 6 years ago | (#19326049)

That is bad in a way because the const ints are being stored in memory instead of hardcoded at compile time. Its not such a bad thing these days with monsterous hardware, but it is a habit that needs to be broken. Neither offer any advantage over the other since changing either will only affect the program after its been recompiled, its just that slight disadvantage for a distinct data type.

Re:I thought #defines were deprecated in C++ (2, Informative)

Phisbut (761268) | more than 6 years ago | (#19326229)

Neither offer any advantage over the other since changing either will only affect the program after its been recompiled, its just that slight disadvantage for a distinct data type.

Using const int instead of define can save you a whole lot of time when it comes to debugging. When something has gone wrong and you need to step into your code with a debugger, const int will have created a symbol that your debugger can use and inform you of, while define will make the debugger tell you the value of the constant, but not where it comes from or what it's called.

Re:I thought #defines were deprecated in C++ (2, Informative)

EvanED (569694) | more than 6 years ago | (#19326461)

That is bad in a way because the const ints are being stored in memory instead of hardcoded at compile time.

Not necessarily. That's implementation dependent, and as long as you're compiling with optimization, you're probably wrong most of the time.

Neither offer any advantage over the other since changing either will only affect the program after its been recompiled

#defines have a number of well-known drawbacks that consts don't.

1. CPP macros stomp all over your namespace. For instance, Linux defines a macro "current". At one point I tried to make a local variable in a function named "current". I spent the next 15 minutes swearing at GCC for not compiling my code and giving error messages that made no sense. You can reduce this problem by naming conventions (for instance all caps), but consts don't have this problem at all.

2. consts don't suffer from order of operation issues, so you can define them without regards to those thoughts. The classic example is

#define SIX 1 + 5
  #define NINE 8 + 1
  printf("%d", SIX * NINE)
Which helpfully prints "42" instead of 54. Again, there are ways to work around this (put parens around the expressions), but you don't NEED to work around it if you use consts.

3. consts are typesafe

Of course, you can't always use 'const' in C. For instance, you can't use a const int as an array bound. But if you don't have to worry about C compatibility, I can't think of a reason to use #define instead of const for defining constant expressions.

The code should be the comments (1)

Normal Dan (1053064) | more than 6 years ago | (#19325949)

In his "player_bullet::move_it()" example he should have moved all of his "[Small chunk of code.]" sections into a new function. Then, he could have called a function named "Calculate_bullets_new_position". This way, he is using the code to comment. It is much cleaner and easier to understand. Functions should rarely, if ever, have comments in them.

Invariants (2, Insightful)

ljw1004 (764174) | more than 6 years ago | (#19325951)

The comments I like best are correctness invariants or induction hypotheses. Like the ones you'd use to prove that your algorithm is correct. For example:

// Invariant: if an object is ReadOnly, then everything that points to it is ReadOnly
// Invariant: if an object is writeable, then everything it points to is writeable
// Invariant: when you call CopyOnWrite(), you get back a writeable object
// Invariant: The ReadOnly flag starts false, and will change to true during the object's lifetime, but can never change back to false.

The correctness invariants for a data structure can also be embodied in a "sanity_check()" function for that data structure, and also in test cases. But the correctness invariants for an algorithm are rarely embodied in any code anywhere. But they're the ones that give you the programmer an assurance that your code is correct. That's why they're so important.

Too basic, and then not far enough (1)

Mycroft_514 (701676) | more than 6 years ago | (#19325955)

What about structured coding? I mean really, this stuff is so obvious, and then to not even mention structured coding?

At this point I am thinking (4, Funny)

dfuhry (973158) | more than 6 years ago | (#19325959)

Wow. That was a big waste of time. All of this stuff is obvious and everyone knows it. Why did anyone write all of this?

"Comment like a smart person." says article... (1)

aabxx (1108623) | more than 6 years ago | (#19325977)

which, for me at least, takes more time away from trying to figure out what the goddamn code actually says.

Actually (4, Funny)

Dachannien (617929) | more than 6 years ago | (#19325979)

Actually, it's not necessarily a bad thing for your code to destroy you. Just make sure you don't dereference any old pointers to you afterwards.

Re:Actually (1)

bill_mcgonigle (4333) | more than 6 years ago | (#19326415)

Actually, it's not necessarily a bad thing for your code to destroy you. Just make sure you don't dereference any old pointers to you afterwards.

Geez, and I thought Skynet was just doing garbage collection.

Bringing things together (1)

Coryoth (254751) | more than 6 years ago | (#19325997)

It is notable that Tip 1, "Comment like a smart person", and Tip 2, "Do error checking. You make errors. Yes, you" can be sensibly combined into "Use contracts". Sure, you'll still need some extra comments to describe the function, but any comments about the parameters a function recieves and what it returns can be usefully written as contracts which provide both documentation and error checking. It also helps you to think about exactly what you intend a function to do, and assists greatly down the line when re-using code by providing clear testable constraints on what a function can and cannot do so you don't accidentally go misusing it.

Self documenting code? (1)

mattoo (909891) | more than 6 years ago | (#19326031)

I'll take:

// returns TRUE if the bullet is to be erased (because it hit a target or the top of the screen)
Boolean player_bullet::move_bullet_upward()
{
Boolean is_destroyed = FALSE;

Pos new_pos = calculate_new_position();

if (contains_enemy(new_pos) {
destruct_enemy(new_pos);
is_destroyed = TRUE;
}

[..]

Return is_destroyed;
}
over:

// This procedure moves the bullet upwards. It's called
//NUM_BULLET_MOVES_PER_SECOND times per second. It returns TRUE if the
//bullet is to be erased (because it hit a target or the top of the screen) and FALSE
//otherwise.
Boolean player_bullet::move_it()
{
Boolean is_destroyed = FALSE;

// Calculate the bullet's new position.

[Small chunk of code.]

// See if an enemy is in the new position. If so, call enemy destruction call and
// set is_destroyed to TRUE

[small chunk of code]

[..]

Return is_destroyed;
}
any day of the week.

If I understand correctly (4, Funny)

Ambitwistor (1041236) | more than 6 years ago | (#19326055)

To keep my code from destroying me, I shouldn't #define MAX_ALIENS_ON_SCREEN_AT_ONCE to equal 100. That's way too many aliens to survive.

Obvious and Wrong in One (4, Insightful)

19thNervousBreakdown (768619) | more than 6 years ago | (#19326071)

... if your C code requires you to know the difference between i++ and ++i, it is too complicated.

Advice on good comments--great--but really, it's just obvious. Anyone that doesn't get how to comment well doesn't want to comment well. And the above quote made me want to wring his neck. If you don't know the difference between those two operators, you should stick to VB.

Felt I should point out (5, Insightful)

loqi (754476) | more than 6 years ago | (#19326271)

... if your C code requires you to know the difference between i++ and ++i, it is too complicated

It's not a matter of knowing the difference, it's a matter of the code depending on the difference. If you need to increment beforehand, do it on the previous line. Afterward, do it on the next line. Expressions are like sex: they're better without side-effects.

Was Jeff Vogel the "anonymous reader?" (0)

Anonymous Coward | more than 6 years ago | (#19326097)

Just wondering... because, offhand, I can't think of any other obvious reason to remain anonymous.

Just as I always wonder whether the people who find those amazing Easter eggs in programs were able to find them because they put them there themselves...

I remember when (1)

Dunbal (464142) | more than 6 years ago | (#19326247)

the foremost concern of any programmer used to be time. CPU time. How many cycles for this operation, versus how many cycles for that one. Now it seems like we have shifted our time concerns to programming time - the programmers' salary, the time to market, etc. Funny though how this tends to result in bloated, sluggish, bug-ridden programs that need at LEAST a patch or two before they even reasonably deliver what was promised on the box.

      I guess we are lucky that the software "consumer" (and I use that word with the greatest contempt) has been "educated" to EXPECT a certain amount of crashes and bugs, and even DEMAND that the latest software come on 3 or 4 CDs instead of just one. I mean WOW, more is better, right? I wonder, however, which other industry (apart from maybe Hollywood) can get away with this? But sheep are sheep, and they will continue to eat what we feed them.

Re:I remember when (1, Insightful)

Anonymous Coward | more than 6 years ago | (#19326341)

Funny, because I also remembered when programmers, so concerned with CPU time, would cut out checks, mess with code until it worked 'right' and would generally tweak it until it worked, to their mind, perfectly. But in fact would crash on unusual conditions or outright produce incorrect output. But it was fast. Fast and wrong. And often times the 'optimizations' they were doing were not anything that really affected performance. First rule of optimization, don't until it's proven needed.

We end up with so much bloated, broken code because people don't worry about right before 'performance' or 'reusuablity'. Get it right and you'll find a lot of the rest of it comes from that. Including maintainability. The best maintainable code package I worked on also happened to be the fastest(faster by an order of magnitude) over the original. The new code was also object oriented, extensible, clean and actually correct(original didn't accurately calculate a value right).

So I don't think that developers are any different than they used to be. They just write more code that's wrong, bloated and crappy. It just has a prettier interface, more colors when it explodes and more features that never get tested or used.

Some more redundancy, care of Brian Kernighan (4, Insightful)

Kalzus (86795) | more than 6 years ago | (#19326305)

"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." - Brian W. Kernighan

Some more tips (1)

PaneerParantha (713034) | more than 6 years ago | (#19326353)

Several other tips may be added to those in the article. Some off the top of my head:
1. Each parameter to a function on a different line, for example
void foo(parm1,
                  parm2)
{
      bar(parm1,
              parm2,
              parm3);
}

2. Put {} in an if stmt even if there's only one stmt. That is
if(condition)
{
      action();
}
instead of
if(condition)
      action();

3. Decouple
Avoid (note the word is avoid, not don't at all)
(stolen from a book, probably Writing Solid Code)
if (pizza type is this)
{
    bake this kind of pizza
}
else if(pizza type is that)
{
    bake that kind of pizza
}
else if(pizza type is the other)
{
    bake the other kind of pizza
}

Instead do this:
if (pizza type is this)
{
    create a pizza object of type this
}
else if(pizza type is that)
{
    create a pizza object of type that
}
else if(pizza type is the other)
{
    create a pizza object of type the other
}

pizzaObject.Bake();

4. If you want to use stmts like
if(5 == z)
{
}
think whether you also want to carry them all the way to
if(5 less than z) instead of if(z greater than 5) for the sake of consistency.

IOW, decide what you want: consistency or ease of understanding in your code. Sometimes they aren't compatible.

5. Always check boundary conditions.
6. Always check arguments to functions for valid values.

please, check the code (1)

eneville (745111) | more than 6 years ago | (#19326365)

Why does the author use code that won't compile in the documentation?

Void change_score(short num_points)

I totally agree with TIP #2 though, #define should not have been dropped from some modern C derivatives though.

I've actually seen his code . . . (0)

Anonymous Coward | more than 6 years ago | (#19326447)

Trust me, you don't want to see what it was like before he realized this (say ten years ago). We're talking numerical constants galore. Pages and pages with no comments, just string constants peppered here and there. Lotsa externs. At the same time, he made great games which I loved to play. There were some bugs, but it was pretty good overall, so who cares, right? It's debatable as to whether I'd have done any better at the time. :-) Ultimately it's a headache for him more than us, and I'm glad to see he's improved his practices. I hope he develops even more over time. Buy his games, they're fun and have a good storyline.
Load More Comments
Slashdot Account

Need an Account?

Forgot your password?

Don't worry, we never post anything without your permission.

Submission Text Formatting Tips

We support a small subset of HTML, namely these tags:

  • b
  • i
  • p
  • br
  • a
  • ol
  • ul
  • li
  • dl
  • dt
  • dd
  • em
  • strong
  • tt
  • blockquote
  • div
  • quote
  • ecode

"ecode" can be used for code snippets, for example:

<ecode>    while(1) { do_something(); } </ecode>
Sign up for Slashdot Newsletters
Create a Slashdot Account

Loading...