What Workplace Coding Practices Do You Use?
Agent_9191 asks: "Recently I've been promoted to what essentially amounts to a project lead role for every project we do, in house. Since my company has run for the past 35+ years with no form of central IT department, there has been no standards put into place for developers to abide by. One of my tasks is to set up standards in how projects will be implemented and produced. Right now I'm more concerned about trying to set up coding standards, so that any developer can jump into any part of a project and be able to figure out what's going on, without wasting a couple hours just to figure out the code. I've come across some documents in this area from a few sources (of course can't remember them off the top of my head). What practices/standards do you use in your workplace?"
Has several excellent articles on the subject This is about as good of a starting place as any.
SJW: a person who perceives an injustice, and while correcting it, commits a greater injustice.
If you haven't been doing these things, pick up "Pragmatic Project Automation". It may not specifically address coding standards, but it definately will help you get some standards around processes.
And make sure they update comments if changes necessitate it. There's nothing worse than reading through a function's description, complete with well-documented inputs/outputs/conditions/etc. and finding out that those things no longer apply because somebody changed a 1 to a 2.
I work for one of Activision's subsidiaries and this is what we use:
int* gpiGlobalInt;
int FunClass::GetSize(int _iArg1, bool _bArg2)
{
bool bBool;
float* pfFloat;
static int siStaticInt;
for(;;)
{
}
}
Seems to work out well enough.
You seem to be asking more about the basics of Project Management than specific tools. For a fair overview of the subject try this in Wikipedia. The grand-daddy of Project Management for software development is SEI-CMM.
The smartest man in the whole, wide world really don't know that much. - Mose Allison
on this particular subject. i believe code complete 2 came out "reasonably recently". that said, were this my task, i'd say the following:
1) document things thoroughly using a tool like doxygen. there is no excuse for interfaces not to be thoroughly documented
2) adopt a standard naming convention. in java, this is easy -- just use the default. in other languages, you'll probably have to make your own up.
3) pick an indentation style. it really doesn't matter which since tools like indent can convert between them almost painlessly. all code that goes into the repository is run through indent to put it into a standard format
4) require that code compile cleanly with no warnings at the most anal retentive compiler settings before it can be checked in unless there are good reasons to ignore the compiler warnings
5) average devs are only able to commit to the "head" fork (or equivalent in your sccs). the code is not committed to the "real" fork until it passes whatever tests you have
6) incorporate tools like valgrind into your testing cycle --- they should come back largely clean. if they don't, things need to be fixed unless there's a really good reason not to.
7) people who check in code which breaks cvs or, upon a code review, are found to not sufficiently adhere to your guidelines owe their dev group donuts.
One word.. doxygen. I had been working on a program by myself for a few years and was really the only one who knew the guts of it. We got a new person on it so I could move on to other things, and rather than spending a week or two showing her what she needed to know, I spent a few days adding doxygen comments to the project, and she was able to read the generated documentation for herself and picked it up in no time. It plugs in to Visual Studio very nicely if you use that, and if not, you can easily write a batch file to update your documentation. I just can't say enough good things about this tool. If you can get your developers in the habit of documenting in the doxygen format, your documentation will basically write itself.
Segfault
A few other details that I'd like to add. K&R braces were invented, not by K&R but by the guys who typeset their book. It is a severe roadbump to try and read code where the braces are at the end of an if statement instead of vertically alligned.
Try spinal alignment for variables. Most people align their variables like this:
int something;
void somethingelse;
longobjectname theThirdThing;
Those with more of a clue align them so that you can find the variable name easily in a mess of them:
int something;
void *somethingelse;
longobjectname theThirdThing;
This puts some major space in some cases between names and short type declarations. Try aligning them like this:
The problem with this technique is that, if you ever post your code on Slashdot, you'll have to replace spaces with dots and spend fifteen minutes trying to get it to render correctly because SD doesn't support a simple PRE tag.
Other tidbits that have helped. camelNotation rules. Don't use hungarian notation, it doesn't work in a severely object oriented enviornment. Instead, preceed your variables with a single letter that tells you where it's declared. l for local, m for member (of a class or struct), g for global, that kind of thing. I've seen "my" used for member and "the" used for static very effectively, also, but stick to one.
Most of all, good luck. Remember that a lot of people's beliefs in this matter have no foundation except for what they've been doing for years. I have faith in my standards simply because I've seen what happens when you don't follow them, and that's mostly confusion.
Wake up - the future is arriving faster than you think.
Is this supposed to be a joke??! Both of them are worst comments, because they only formulate in english what the code already says by itself. Everyone can see that this is an if-statement, everyone is able to identify the condition, and everyone knows the semantics of an if-statement.
A good comment is not describing what is done (since everybody can see that from the code itself), a good comment describes why something is done, or what the overall objective of the statement is.
For example:
This is ways more useful. Even more useful would be to already use self-describing symbol names in the code itself, like
Windows is like decaf - it tastes like the real thing, but it won't get you through the day.
enum is your friend!
...
;-(
enum {LOAD_DATA, SAVE_DATA, DESTROY_DATA}
Paul B.
P.S. And of course my all-caps enum values were considered too lame by lameness filter...
without wasting a couple hours just to figure out the code.
A couple hours???
Look, no offense, but you either only deal in "toy" code, or you have such high expectation that you will fail, and quite spectacularly.
A new coder, even an experienced one, takes days or even weeks after coming into an existing project before he can contribute anything but the most trivial of changes. For a truly massive project, or one that requires intimate domain-specific knowledge in a niche industry, extend that to months.
If you can find a way to get an unfamiliar newcomer up to speed on any "real" project in a matter of hours, consider your talents wasted in your current position.
Amen to that.
In addition to the original comments being redundant, there's also the issue of the code and the comments getting out of sync...
The company I work for just wrote up a formal coding standard, which includes everything from a guide to our internal hungarian notation, indentation guidelines, and even which C++ features/paradigms are supported, frowned upon, or not allowed. All the coders got a chance to send in feedback before it was finalized, and we even ended up with a list of recommended reading on the subject, including:
The idea is to keep the code readable and maintainable with the least amount of re-invention of the wheel. With good coding practices, it's easier to avoid bugs in your own code and spot them in others (reviews are also a big plus on both counts). And it gets any religious battles out of the way up front, so you don't have to waste time bickering later on.
I know what you mean about coding standards. I have worked in so many places and have been asked "Do you have any coding standards that we can use". So instead of carrying around stacks of documents, I have placed them all on one site. Go to Delphi Coding Standards this is a Delphi coding standard I follow, but I'm sure you can apply it to all languages as required.
C# - The C# Coding Style Guide, Mike Krueger(SharpDevelop). This is probably the most widely used one (Novell). It largely agrees with Microsoft's internal coding standards, with a few exceptions. .Net Coding Standards, part of the SDK. This is not comprehensive though, like the C# doc mentioned above.
VB -
Version Control -
Server: Subversion + Apache
Client: Tortoise SVN (Excellent) [We also use Perforce, CVS, VSS(Commercial apps)]
Continuous Integration - Cruise Control.Net
Intranet, Knowledge Management - DotNetNuke (www.dotnetnuke.com)
Project Management - dotProject (PHP) (www.dotproject.com), MS Project
Unit Testing - NUnit (www.nunit.org)
Life is just a conviction.
In C++ we use Doxygen. Basically as you write comments inline you use a few shorthand markers (kinda like HTML tags, sorta, not really) to tell Doxygen what to pick up. Generates pretty good documentation and graphical class charts, etc. Works pretty slick, Doxygen is then pure HTML + png documentation of your code.
-everphilski-
I have recently aquired the book "C++ Coding Standards - 101 Rules, Guidelines, and Best Practices." ISBN 0321113586 or http://www.amazon.com/gp/product/0321113586/103-00 42056-9954216?v=glance&n=283155/
Steve McConnell's Code Complete is an excellent source for coding standards and a good read for any developer. I don't agree with everything in the book but it is comprehensive. Ignore that it's published by Microsoft Press, it's a good one.
You should also worry about development practices. Just having good coding pratices will not gain you much in the way of robust and easily changed systems. Having good development pratices will.
Specifically, I'm referring to having a complete system of specifying the requirements for any system. Too many coders these days start a project by hacking up the first thing they think is necessary, then the second, then the third, etc. While this ends up working out for most small projects, big projects can quickly become unweildy. Not to mention, if you bring in a new developer after years of working like this, the learning curve for that developer is very steep.
Enter Hatley & Pirbhai's Strategies for Real-Time System Specification. In this book, the authors outline a set of strategies for developing complicated systems and making them as robust as possible. Now, you may be thingking "Who are these guys and why should I care what they have to say?" Well, they used to work at Boeing and they developed their strategies while working on designing a plane. (I think it was the 777, but I could me wrong.)
You should definately read the book, but the strategies they present basically boil down to defining the whole system from the perspective of what, how and when--separately. Here's how it works:
This may seem like overkill, but it's not. I've been working like this for a few years at college now and it has huge advantages. Development tends to go faster, problems can be fixed faster and--most importantly I think--new developers can sit down with the specifications and get up to speed very quickly.
Overall, I think using strategies like Hatley and Pirhbai have developed is far more important than all the coding practices and code commenting in the world.
Of course, YMMV, etc.
--JamesSnowden and Manning are heroes.
Read and apply the Pragmatic Programmer.
Most standards are relatively meaningless. Indentation, Spaces not Tabs, "All class names must be descriptive", "Comments are required" - really this is all hand waving. Let individual groups figure out what's best for them. And stop thinking like a boss, or you'll find yourself with no one to manage pretty quick.
------ Tim O'Brien
If you want code that can be readily understood you need something other than coding conventions. Coding conventions only make the code all look the same. You can get almost all of the benefit (without most of the arguments) by saying only that each file must be written with the same coding convention throughout. The code will get prettier and prettier with tighter conventions and developers will waste less time reformatting each others code. But it won't do a thing to make your project more understandable.
For that you need an understandable design and the best advice I've ever seen for that is in Eric Evens' "Domain Driven Design" http://domaindrivendesign.org/. The advice there will work for both Agile and non-Agile projects and its core themes are pretty much unavoidable truths about how to write code for a project that is also written about the project: use language that comes from the projects domain, insulate code from each domain or sub-domain from the rest of the world, keep each method at the same level of abstraction (that's big) and make implicit concepts explicit, to name a few. The key is for your developers to consider themselves to be authors and to strive to keep each little piece of code they write on-topic. Not only will it be easier for new developers to come up to speed but the code will work a heck of a lot better too.
But the generated document is only as good as the comment itself, isn't it? Correct me if I am wrong, I don't think any of the tools that you mentioned can generate any intelligent comment. What good is the comment "The openSocket method throws a SocketException"?
Which is why we would say :
.else . . end structure and the bodies of all the elements are large then each should be a procedure/method itself.
1) Don't use variable names like x, use something that indicates the meaning of the variable - so maybe in this case lErrorStatus
2) Don't hardcode magic values, use a meaningful constant - which also means only one point in code needs to be changed if we switch CPU and find there is a different on-fire code
Then we get
if lErrorStatus == CPU_ON_FIRE then
Which I think is pretty self-explanatory.
One thing that isn't clear yet is whether this bit of code is sitting in a little function or part of a big block - i.e. what it's going to do on the 'then'.
Now at some future point we might find ourselves needing to check CPU_GETTING_QUITE_HOT. So we will still have to impact all occurrences of
lErrorStatus == CPU_ON_FIRE to add an extra test.
This leads to
3) Encapsulate tests in meaningfully named BOOLEAN functions.
I'd say it is swings and roundabouts as to whether (3) is worth the effort.
If the _cpu_on_fire(ErrorStatus) test is just done once, then we've had to go to a lot of effort to encapsulate a single line of code (as the expression is already boolean). If it is used >1 times it is definitely worth wrapping, ditto if the expression is complex - just to make sure developers get into the habit, as much as to protect against any change. (I think it's better to get into a slightly more time-consuming habit of doing the right thing and break it occasionally, than into the habit of doing the quickest thing and having to think to do the right thing).
The other principle that points to (3) is the one that blocks of code should be 'readable' and if possible a block should fit on one page - i.e. when you have an
if . . then . .
Again, _cpu_on_fire(ErrorStatus) isn't a good example as we'd be replacing one line with one line.
However, if you have a standard logging mechanism (say log4j), and template code for functions/methods, you can use this encapsulation to record the fact that the test occurred, input and output values, rather than leaving it to the individual developer to remember to add logging before their 'if' and on each conditional path.
'Capitalists of the world, unite! Oh
Here's what I like:
:) The team lead can then decide on a policy, e.g. "there will be no discussion on this point, everybody can do it how he/she pleases", "everybody will do it *this* way", something like that.
1. As for code comments, rely on "Use The Source, Luke" as much as possible. Force people to write readable code, so that this actually works. Logical variable names, no unnamed magic numbers, no cryptic constructs. No loop bodies consisting of only a semicolon, e.g. "for(...;...;...);". Comment only on the things that aren't obvious. Any extraneous comments are bound to be outdated by the code, and will confuse more than help.
2. Write down the design in comments in the source files, as a readable piece of prose containing all of the design considerations and decisions. Design of an algorithm goes in the function body, design of a class goes above the class definition. Programmers are aware that designs are often outdated, so when they read them this is not a problem. Having the design in the code has the advantage that you can actually *find* the design for the code you're looking at. There have been too many times where I've been looking for a design document that was "somewhere on the network". Or that I've been looking at a design document on the network that had been superseded three years ago. Having your design under source control fixes that.
3. Build at least every day, or even better: continuously.
4. Automated testing. Run automated tests on every build, if possible.
5. Code reviews. Sit together once a week with one other team member who then reviews all your code for the last week (all of it, based on reports from source control). That shouldn't cost more than an hour or something, it's a good way of keeping the knowledge going around, it works as a very good "desensitization therapy" for those programmers who can't handle criticism, it increases communication within the team because people get to understand each other's work better. The only downside is that there is usually a lot of opposition against this -- I know a *lot* of programmers who don't like to have their code criticized. And there's a very clear risk that people will get into endless discussions about very small details of style ("should there be a space between the if and the parenthesis?") or other inconsequential things. To prevent these issues hogging the review, there should be a formal "escalation procedure", where the issue is passed on to an arbiter (team lead) with arguments from both parties. If a disucssion on an issue seems to go in this direction, either party *or* somebody else in the room whom the discussion irritates the hell out of should be able to cut off the discussion and "escalate" it.
Note that I'm currently working in an environment where we have (1) to (4) implemented. I'd like to have (5), because there is too many crap code being committed, and there's no check on that. It's been all too often that we've had to replace the *entire* work of a team member after he/she left, because the team member had been able to commit crap code without check during all the time (s)he was on the team.
I make sure that every new technical hire to our company reads this book by Kerninghan and Pike. Then, I give them a copy of our coding standards which really just outline the syntatic sugar. If the person was bright enough to get hired, they are more than capable of understanding and applying the concepts presented to them through these two sources.
The GNU Coding Standards were written by Richard Stallman and other GNU Project volunteers. Their purpose is to make the GNU system clean, consistent, and easy to install. This document can also be read as a guide to writing portable, robust and reliable programs. It focuses on programs written in C, but many of the rules and principles are useful even if you write in another programming language. The rules often state reasons for writing in a certain way. Best, url80
Best,
url80, The Bounty Network
Read this thoroughly, and try to do the opposite.
"I once came across a ~1400 line function"
This is so fucking wrong and wicked the programmer who did it should go straight to hell. I'm sure there's no functional coesion in there: most likely there are many disparate tasks that should be each in its own function and called from there. I'm sure there is a lot of cut-n-paste in there that should be each in its own function and called from there.
I'm sure you can guess where i'm willing to get to... more important than hungarian notation, comments or documentation in PDF format is abiding for these 2 simple rules: KISS -- keep it simple, stupid -- and DRY -- don't repeat yourself. Once you do it, coding and reading code is a lot easier.
So, my advice:
* Give meaningful names to important, global, business rules variables ( local variables like i or c are ok, since they are mostly irrelevant ) or functions/methods/procedures/subroutines
* Write short, highly coesive functions/methods/procedures/subroutines
* Stop the cut-n-paste madness! If you do it a lot, it's obvious the copied code if begging to be parametrized and be given a name. Programmers altering your original code will be thankful
* Write modular code, not a plain, huge, stupid monolithic wall of letters. Even in languages with no namespace support ( C/PHP etc ) a good naming convention for functions of a certain module/header can do wonders...
* and please: meaningful names don't mean phrase-like names like thisLocalVariableIsCool. Conciseness go a long way towards good readability...
I don't feel like it...