Journal Articles
Browse in : |
All
> Journals
> CVu
> 174
(12)
All > Journal Columns > Professionalism (40) Any of these categories - All of these categories |
Note: when you create a new publication type, the articles module will automatically use the templates user-display-[publicationtype].xt and user-summary-[publicationtype].xt. If those templates do not exist when you try to preview or display a new article, you'll get this warning :-) Please place your own templates in themes/yourtheme/modules/articles . The templates will get the extension .xt there.
Title: Professionalism in Programming #33
Author: Administrator
Date: 07 August 2005 05:00:00 +01:00 or Sun, 07 August 2005 05:00:00 +01:00
Summary:
Body:
A Review to a Kill
Reviewing has one advantage over suicide: in suicide you take it out on yourself; in reviewing you take it out on other people. (George Bernard Shaw)
Is it me, or does this look familiar? Astute readers (who are old-time ACCU members) might feel a sense of déjà vu here. Back in the mists of time, the fourth ever professionalism column discussed code reviews. I recently needed to evangelise reviews once again; it's always the same old battles we fight. Different job, same problems.
I dug back, revisited, and refreshed my look at the code review process. I reviewed the material, if you like. It seemed appropriate to present the fruit of my labours for a fresh audience. We'll start with some craftsman philosophy…
How do you learn to be a good carpenter? You become an apprentice to someone. You watch them work, help them daily, gradually take on more responsibility, and learn from their advice. You don't jump in feet first without any practical ability and expect to churn out quality woodwork straight away.
We don't have a real analogue of that in the coding world, even though programming is as much a craft as it is an engineering discipline (possibly more so). Code reviews, however, do give us a little taste of that in the discipline of an engineering process.
Code reviews (or inspections, or walk-throughs) have similar effects to the open source model of software release - providing a structured opportunity for others to eyeball your precious code. Reviews encourage you to take responsibility for your handiwork. When you know that it's not just for you to look at, but it will be viewed, used, maintained and criticised by others your approach tends to change. You're less likely to make the quick-and-dirty fix that you'll never have time to revise. The accountability brought on by code review brings a greater quality to coding.
Code reviews are employed in traditional software engineering processes. They are arguably less important when pair programming, or when more than one person is responsible for parts of the code. In these situations they are still useful nonetheless.
The code review seeks to analyse a section of source code at several levels:
-
the overall design (e.g. the choice of algorithms and external interfaces),
-
the expression of that design in the code (e.g. its breakdown into classes/functions),
-
the code in each semantic block (e.g. class, function, loop), and even
-
each individual code statement.
We look in great detail to ensure that the code is correct and of a suitably high quality. This process generates a huge list of 'must-fix' issues. Sometimes you will spot improvements that are not worth making now; we chalk these up for future experience.
A code review doesn't replace the code's functional specification review. The code is validated to conform with its specification, but the content of this specification is taken to be correct. If it wasn't then the task would be herculean! Sometimes code review comments might feed up to the specification (for example, where clarification is needed), but this is not our ultimate goal.
Code reviews can be:
-
Personal
The author carefully and methodically reviews their own work to make sure that it's good. Don't get this confused with casually reading your code after typing it; a 'personal' code review is a more detailed and involved task.
-
Open
Involving other programmers brings new expertise, more experience, and more eyeballs to the task. It's consequently harder to coordinate and requires greater overall effort, but is more likely to find problems. It's not easy to delve this deeply in a personal review; often the author is too close to the code and it's easy to overlook problems.
Bugs are our enemy, the nemesis of good software development. We need to be confident about the quality of our work, and need to find faults as early as possible in the development process. The earlier we try to find problems, the more we are likely to find and fix.
Code reviews are an excellent tool to achieve this goal. According to Humphrey: "Students and engineers typically inject 1 to 3 defects per hour during design and 5 to 8 defects when writing code. They only remove about 2 to 4 defects per hour in testing but find 6 to 12 per hour during code review" [Humphrey97].
But code reviews do more than identify bugs; they weed out all sorts of problems. We perform code reviews to improve code quality. This includes:
-
removing coding errors,
-
identifying design problems,
-
removing redundant code, and
-
ensuring efficient[1] algorithms are used
We also check the code against a number of yardsticks, which include:
-
its specification,
-
any project coding standards and best practices, and
-
the appropriate language idioms (e.g. ratify the use of design patterns)
Apart from the obvious benefits of correct code, reviews have other useful side-effects. The cross fertilisation that comes from looking at each other's code ensures that coding style is more uniform across a whole project. A review also spreads knowledge about the inner workings of core bits of code, so there is less risk of loosing information when people leave a project.
In an ideal world every bit of code is carefully reviewed prior to release. According to the Software Engineering Institute at the Carneige Mellon University, a thorough code review should take at least 50% or more of coding time (although they do include 'personal' code review in this statistic) [Humphrey98]. That would take longer than a Real World project is prepared to invest[2].
So as we write a system, we need to ask whether to review the code and, if so, exactly what code to review.
Bugs are inevitable, and you can be guaranteed your code contains some classic mistakes. There will be obvious flaws that you'll find quickly, and many more subtle problems that would only be spotted by a fresh pair of eyes approaching the code with no preconceptions. It's hard for the original author to see most inherent faults in their own work - they're too close to it, suffering the psychological cognitive dissonance described in [Weinberg71]. If your code is at all important (clue: it is, or you wouldn't have written it) and you care about its quality (clue: you do, or you're a disgrace) then you must code review.
Not reviewing code drastically increases the chance of faults slipping into your production software. That could spell your embarrassment, a lot of expensive rework and in-the-field upgrades - even your financial ruin. The effort of a code review pales in comparison with the consequences.
Often people make excuses to justify avoiding reviews. They say "the code's too large to review fully" or "it's too complex, no one person could ever understand it - there's no point even trying to review it". If a company can employ enough people to write a large program, they can employ enough people to review it. If the code is too complex then it desperately needs reviewing! In fact, it probably needs something a little more drastic. Well-written code is decomposed into sections that can undergo separate reviews.
Even the most modest project quickly produces a tonne of source code. For all but the most stringent development processes there simply isn't enough time to review every last scrap of code. So how do you decide which bits to review? That isn't easy.
You want to select the code that will benefit most from review. This is the code that is most likely to be bad, or that is most important to the correct functioning of your system. You could try these strategies:
-
select core bits of code in the 'central' components,
-
run a profiler to see where most CPU time is spent - review those parts of code,
-
run complexity analysis tools, and review the worst offending code,
-
target areas that have already exhibited a high bug-count, or
-
pick on code written by programmers you don't trust (a code review vendetta!).
The most practical approach is probably a hybrid of all of the above.
There are several ways to perform a code review:
-
in a code review meeting,
-
a 'virtual' review (run online, with no physical meeting),
-
as a 'gate' for code modifications to be included in the main source tree,
-
using code review tools, and
-
in a personal code review.
Any form of review places the source code under the microscope - really aiming to criticise and verify it. This is not to pillory or 'get at' the author, but to improve the quality of the software the team produces. Simply having a code review is not enough. In itself it's not going to solve all the problems. You also need to make sure that you review properly. The most common setting is the formal code review meeting. There is a fixed agenda (to ensure that no action is forgotten) and a defined ending (not necessarily a time limit, but a definition of exactly what code you are reviewing, and what you're not - it's very easy to be woolly about this).
An example code review meeting procedure is described below:
The best place to hold a code review is in a quiet meeting room. The reviewers should not be disturbed. There should be coffee.
A suite of networked laptops with code editors may be useful, as may a computer hooked up to a projector. Old-school programmers swear by printouts and pen-and-paper note taking - detaching from the computer screen can help to find new faults. This really depends on how much respect you have for trees and electricity consumption.
Obviously, at a mutually convenient time. Common sense tells us that Friday at 4 p.m. is not a good time. You need to devote serious time to this, so make sure that you won't be disturbed or distracted.
If the code is too large, split the review into a number of separate sessions. You can't sit people in an enclosed space for hours on end and expect the quality of their review to remain high.
One of the most important contributing factors to the success of a code review meeting is who attends. There are a number of distinct roles which people should be specifically assigned. One person can be both a reviewer and another role.
-
Author. Obviously the person who wrote the code should attend the review, to describe what they have done, argue against unfair or incorrect criticism, and to listen to (and subsequently act on) valid constructive feedback.
-
Reviewers. The reviewers should be carefully picked, the people with available time and skill to review. It helps if the code is in their area of expertise, or they are involved with it in some way. For instance: the writer of a library should be invited to review a program that uses the library, to diagnose incorrect API usage.
-
Test department. There should be an appropriate number of experienced software engineers present. There should possibly be a representative from the QA/testing department, so QA can be assured of the software's quality, and the quality of the development process.
-
Chairman. Any kind of meeting needs a chairman, or chaos will ensue. This person leads the review, and guides the discussion. They ensure that the conversation keeps to the point and that the meeting doesn't get side-tracked. Any minor issues that don't need to be discussed in the meeting should be quickly taken off-line by the chairman. Given half a chance, programmers will discuss a minute technical detail for hours at the expense of the rest of the code review.
-
Secretary. The secretary takes minutes. This means writing down all points that arise, to make sure that nothing is forgotten after the review. If there is a review checklist then they fill it in. The secretary role should not be fulfilled by the same person who acts as chair.
Before arrival, everyone is expected to have familiarised themselves with the code. Everyone must have read the supporting documentation (any relevant specifications etc)[3] and be aware of any project coding standards. Whoever organises the meeting should highlight these documents in the meeting announcement to prevent misunderstanding.
To organise the code review meeting:
-
The author signals that their code is ready for review.
-
The chairman arranges the meeting (booking an appropriate location, setting the time, and assembling the correct set of reviewers).
-
All required resources (computers, a projector, printouts, etc) are arranged.
-
The meeting must be called sufficiently ahead of time to allow the reviewers to prepare.
-
After the meeting announcement, the author cannot change their code - this is not fair on the reviewers.
The code review meeting is run as follows:
-
The chairman arranges for the room to be prepared beforehand, so the review can start on time.
-
The author takes a couple of minutes (no longer!) to explain the purpose of the code, and a little bit about its structure. This should be prior knowledge, but it's surprising what misunderstandings can be caught at this first stage.
-
Structural design comments are invited. These are comments relating to the structure of the implementation - not the actual code at statement-level. This could include the breakdown of functionality into classes, the split of code into files, and the style of function writing (are there invariants, and good test harnesses?)
-
General code comments are invited. These may relate to a consistent incorrect coding style, bad application of design patterns, or incorrect language idioms.
-
The code is carefully stepped through in detail, a line or block at a time, to prove that it is correct. The things to look out for are described later.
-
A number of example scenarios of code usage are considered, and the flow of control is investigated. This helps the reviewers to understand the code and cover all execution paths.
-
The secretary notes all changes required (recording the filename and line number).
-
Any issue that might percolate out to the wider codebase is recorded for further investigation.
-
When the review has finished a follow-up step should be agreed. The possible scenarios are:
-
OK - the code is fine, no further work is necessary.
-
Rework and re-review -the code needs a lot of rework, and another code review is deemed necessary.
-
Rework and verify - the code needs some rework, but another code review meeting is unnecessary. The chairman nominates someone to act as verifier. When the rework is complete, the verifier checks it against the recorded minutes of the code review meeting.
-
A reasonable deadline should be imposed for any rework, so that the detail of and reasons for actions stay fresh in people's minds.
Remember: the aim here is to identify problems, not to fix them in the meeting. Some problems require considerable thought to fix, and this is a job for the author (or modifier) after the review has finished.
Code review meetings are a high-ceremony review method. They're hard work, but they undoubtedly find many problems that would otherwise go undetected.
Other less intense review procedures exist, providing most of the benefits of code review meetings but packaged in an easier to swallow pill. Perhaps the most effective is the integration review, performed whenever new code is integrated onto a mainline code branch. This could be when:
-
a new piece of code is about to be checked into source control,
-
a new piece of code has been checked into source control, or
-
a code package is merged from a feature development branch onto the main release branch.
At such a point, the code in question is marked for review, and a suitable reviewer is picked: either someone responsible for that module (the code integrator or maintainer[4]) or a shadow (or code buddy) who is assigned to verify that author's work.
These 'gated' code check-ins are often implemented with a software tool that is integrated with the source control system. They're quite hard to arrange manually, and are usually left as a check-in discipline: you are not supposed to check any code in unless it has already been peer reviewed. This approach is quite hard to police; errors slip past in hurried last minute check-ins.
The actual review step here is usually a lot less formal than the meetings described earlier. The reviewer scans the code to check that it's not obviously broken, tests it (perhaps reviewing the available unit tests to ensure they're valid), and then authorises it for inclusion in the mainline. Only then will the code integrator migrate the verified code into the release tree. For more serious projects, or at more sensitive times (just before a major release milestone, for example) this review step may become much more stringent - requiring more eyeballs and more effort.
Since the reviewer and author needn't actually meet face to face (although it is preferable to do so) this can be considered a form of 'virtual' review process.
Code reviews require a constructive attitude - you need to approach a review with the correct mindset or it will be unsuccessful. This works two ways, for the author, and the reviewer:
Many people shy away from a code review for fear it will expose their inadequacies. Don't do this. Having your code reviewed is a good way to learn new techniques. You must be humble enough to admit that you're not perfect, and willing to accept criticism from others. Your coding style will improve as you learn from the changes made to your work.
As an author, do not be defensive about your code. There is a natural tendency to take all criticism personally and assume it's an assault on your abilities. To cope with a code review, you need to reduce ego and personal pride. Understand that no one writes perfect code: even the most awesome programmer's code will be criticised for tedious little problems in a code review.
When you're in the hotseat, try not to waste other people's time. Before you present your code for review, run a dummy review by yourself first. Imagine you're presenting your work to the others. You'll be surprised how many little flaws you'll filter out, and it will help you to be more confident in the real review. Don't rush out half-baked code and expect others to review the flaws out for you.
When reviewing code and making criticism, you must be sensitive. Comments must always be constructive, and not intended to lay blame. Do not launch personal attacks (you always do this…) on the author. Diplomacy is important here.
Code review is a peer process: every reviewer is considered equal. Seniority doesn't matter, and all views are considered. It is interesting that even the least experienced programmer will have something worth mentioning in a code review. And just as the author learns from the review, so may a reviewer.
Over time you will perform many, many reviews (especially if you perform integration reviews). Be careful that your review process doesn't become a mundane chore; it'll soon be an ineffective waste of everyone's time. Maintain a positive approach to your code reviewing. As a reviewer, always try to have something useful to say at each review. Sometimes this is easy, sometimes its very difficult to say anything interesting. But by forcing yourself to make comments you won't fall into the easy review rut, becoming a check-in 'yes man' who adds nothing to the process.
We haven't yet considered what type of code will 'pass' review, and what code will 'fail'. It's beyond the scope of this article to describe what 'good code' looks like. As we look for bad code design and hunt software bugs, there are a few specific themes we can draw out. The reviewed code needs to be:
The code must meet all relevant standards and its requirements. Ensure that all variables are of the correct type (e.g. there is no chance of numeric overflow). Comments must be completely accurate. The code must meet any memory size or performance requirements (especially important for embedded platforms). Check that there is appropriate use of libraries, and that all function parameters are correct.
The code must implement the entire functional specification. It must have been integrated and debugged satisfactorily, and pass all test suites.
Check that the implementation's design is sound, that the code is easy to understand, and that there is no duplication or redundant code. Look for any obvious cut-and-paste programming, for example.
There must be no unnecessary complexity, and no unexpected surprises. The code should not be self-modifying, must not rely on 'magic' default values, and not contain the subtle chance of infinite loops or recursion.
The code is defensive. Wherever possible the code should protect against detectable run time errors (divide by zero, number out of range errors, etc). Input should be checked (both function parameters and program input). The code handles all error conditions, and is exception safe. All appropriate signals are caught.
Bounds checking is performed on C-style array access. Other similarly insidious data access errors are avoided. Multithreaded code has correct use of mutexes. The return values of all system/library calls are checked.
A review process is key to the production of any high quality item, and so is not solely useful for source code development. A similar review process is used for specification documents, lists of requirements, etc.
Code reviews are an essential part of the software development process. Just as an apprentice learns their trade from knowledge passed on, code reviews spread knowledge and teach coding capability. As more of a peer-to-peer than master-apprentice activity, they provide a learning opportunity for author and reviewer alike, and result in higher quality code.
Write your code to be reviewed; bear in mind that it's never just for you to read. Other people must be able to maintain it as well. The author is always accountable for the quality of their code.
[Humphry97] Introduction to the Personal Software Process. Watts S Humphrey. Addison-Wesley, 1997. ISBN: 0201548097
[Humphry98] The Software Quality Profile. Watts S Humphrey. In: Software Quality Professional, December 1998. Available from: http://www.sei.cmu.edu/publications/articles/quality-profile/
[1] For an efficient definition of 'efficient' in the code's context.
[2] The fact that they're rarely prepared to invest any time in code review is a more damning problem.
[3] Naturally, all supporting documentation will have been thoroughly reviewed beforehand.
[4] Compare this with an open source project's maintainer, who collates patches submitted by other hackers and integrates them into the main source tree, performing periodic software update releases.
Notes:
More fields may be available via dynamicdata ..