[Disclaimer: the opinions below are my own, they might get on your nerves, but I do try to back them up with facts]
Note: It ended up being much longer than anticipated, so here is a summary :p
- Use a Distributed Version Control System
- Implement Automated Testing
- Automate Automated Testing
- Test Deeper
- Test Review
- Code Review
- Design Review
- Coding Standards
- Consistent Formatting
- 3rd Party Code ?
- Task Tracking
- Automate Delivery
1. Use a Distributed Version Control System
Among good practices, you'll find the use of a VCS. Unfortunately it's insufficient. Trash CVS or SVN and get a modern Distributed VCS (preferably Git, or Mercurial otherwise).
DVCS have several advantages over traditional sever-centric VCS:
- clones instead of check-out: makes branching easy, makes sharing code easy, makes working offline possible, ...
- improved merge strategies
- no longer necessary to back-up the server since everyone get a copy (which means you cannot screw-up a restoration...)
2. Implement Automated Testing
Testing the same things over and over is really boring. Yet you cannot have any confidence as to the quality of your software without testing it!
That is why automated testing is a must-have, since it relieves the burden of re-testing while keeping its advantages.
3. Automate Automated Testing
Even with automated testing, you still need to run the tests. It takes time. I gets in the way. "And I haven't changed much anyway"
- Commits to the central repository should only be possible after passing a minimal set of tests (the full test suite might be too long), this means that you do not commit, you enqueue a commit request that a bot (Hudson, Buildbot) will eventually process for you.
- Nightly non-regressions tests should take over to run the full test-suite, it's everyone's top priority to get the nightly back up to 100% if they ever fail
4. Test Deeper
Functional testing is indispensable, but it's covered by the first point.
You can go deeper though.
- Statical Analysis software, aka Automated Bug Finding
- Runtime Analysis, aka Automated Bug Finding 2
Run analysis as part of the nightly non-regressions tests. Unfortunately it's difficult to be precise here because I only know some for C++ :/
5. Test Review
Each specification change and each bug resolution should be accompanied by a set of tests. These should be reviewed to try and avoid "forgetting" something. New code should not make it into the repository without being accompagnied by its set of tests.
6. Code Review
Each new feature or bug resolution should be review by at least one person. In my team we try to involve 2 persons: one that is knowledgeable in the area (to "validate") and one that is not (to get experience).
The code review should be technical and functional, but it's too late to question design strategies (unless it's a glaring mistake).
It's the moment to enforce Coding Standards / Naming Conventions.
7. Design Review
As mentionned, it's too late when at the code review stage to question design decisions. It's also difficult to design on one's own, because design requires insight, foresight, and so on.
Design decisions should be discussed, I once again recommend a 3 persons settings:
- the proposer: responsible for prototyping / checking the documentation etc... and coming up with a design
- the reviewer: someone with experience, with knowledge of the application, often times the team leader / project leader
- the student: someone either inexperienced in the craft or in the application
It's not a good idea to let inexperienced / less knowledgeable take design decisions unguided: it's so much easier to change a paper draft than a hundred source files.
8. Coding Standards
You need one, but you do not need any one: you need a good one.
There are many dubious advices laying around on the web: don't incorporate them blindly.
A good Coding Standard is:
- technical: that's how you get objectiveness
- light: no one can memorize hundreds of points
Taking the points backward: light ensures that you Don't sweat the small stuff (C++ Coding Standards, Herb Sutter and Andrei Alexandrescu).
technical ensures that it's objective, which gives it much more change to get accepted.
There probably isn't a Coding Standard adapted to your team, build you own by taking reknowed standards and adapting them to your specific projects. Discuss each point and make sure everyone agree on each of them, you need every team member to commit themselves on this.
9. Consistent formatting
Naming Convention, Indentation Style, Bracket Style, Tab vs Space... there are countless debates in the programming community on these subjective subjects.
One thing is sure though, you need a consistent formatting style in your code base, and preferably one that everyone is comfortable working with.
This calls for setting those things once and for all. There is no silver-style, there are dubious ones, but what really matters is consistency of the code and commitment of the programmers.
Tools can assist in this task.
10. 3rd Party Code ?
The Not Invented Here syndrom is bad, but incorporating blindly thousands of libraries is not much better.
- The decision of bringing in a library or re-developping something in-house is a Design decision, and thus should involve several people (comprising the project leader)
- Restrict yourself to open-source well-tested libraries if possible (not necessarily free mind), it makes it easier to investigate bugs if you can step into the libraries calls
- Encapsulate the libraries, you don't want to have an interface change ripple through your code base like a typhoon in an atoll
11. Task Tracking
I know bug tracking is all the rage, but there is much more than bugs to be tracked, features changes should be tracked too, and planified, and accounted for.
If you have an in-house system, well, use it.
If not, there are several systems existing out there, some free, some not. Examine them, pick one. You don't want to be recoding them I think, it would be a diversion from the real goal of your team :)
12. Automate Delivery
Even the latest addition to the team should be able to deliver the software into production.
It means that the process should be documented, streamlined, and automated as much as possible.
Delivering the software should be as simple as pushing a button. Bonus points if this actually checks the delivered archive as well ;)
Oh... and obviously, reverting the deployment should be possible and automated too... we've been extra careful but Murphy is always on the prowl :/
I am zero for overzealous documentation... but:
- It's easy to get Doxygen / Javadoc / whatever running (even if the code doesn't actually use their specific comment formatting, it still brings value)
- You need a central place to share procedures, archive meetings minutes and design decisions (with their rationale), etc...
I recommend a simple web server, preferably with a search engine. A wiki can be great. Anything easy to administrate / use, preferably light, once again it's not your primary task to administrate it, so it should not cost much.