80% of all communication, it is often said, is nonverbal. The actual percentage is disputed – with experts quoting figures that range from 50% all the way up to 93% – but what is not in dispute is the fact that what is left unspoken is often as important as what is said.
An almost direct parallel can be drawn with comments in code. Annotations aimed at the programmer but ignored by the compiler can be as important as actual functional code and should be treated with a comparable level of seriousness.
Should be treated with seriousness; however, unfortunately, they almost never are. Most programmers will confess that their commenting is, at best, patchy and often non-existent. The excuses run from the threadbare to the clichéd; from “I do not have enough time to comment” to “Good code is self-explanatory”.
Fewer programmers will admit to this, but a lack of knowledge of the many uses – and the power – of commenting is widespread. That is what this article intends to address.
Types of Comments
Prefacing: This is the practice of starting each programming unit with a block comment that briefly describes it. Ideally, the preface should not be overly long, and it should summarize the purpose of its programming unit. The advantages of prefacing are twofold: it is a useful tool for any maintainers who may need to understand the code in the future; but it can also be beneficial for the developer writing the code, helping to concretize his purposes in his mind. In addition, best practices have always stipulated that programming units should be single-purpose, and in writing the prefacing comments, the developer will catch himself if he is about to flout this rule.
Comment-Driven Development (CDD): This is a programming methodology that encourages the developer to start out complex projects by building a wireframe of their procedures using little more than comments – and basic pseudocode – to describe each step of the algorithm. CDD helps the developer encounter and work out problems before they write a line of actual code; it also has the advantage of helping clearly delineate the routes between the high-level problem and the many small-picture fractals it is composed of. The comments created using CDD may survive the process of actual coding and development as line comments throughout the programming unit; however, it will sometimes make sense to delete them after their purpose has been served.
Below is an example of a CDD wireframe, illustrating the way it can assist the developer in ironing out kinks as he encounters them.
Create or replace function Matching_algorithm (pId number) returns varchar2 is /* This function accepts an order id and attempts to match the details of that order ** to an existing order in created using the old system. This should help get details ** like customer info and order history. */ Begin -- Get the defining details of this order. -- Is it a bulk or a single order? We'll need to treat them differently. If bulk_order then -- remember to create bulk_order and single_order Boolean variables. -- get additional details from the bulk order tables. Else -- single order -- No additional details are needed for single orders. No need for this else? End if; … End matching_algorithm;
Revision History: It can be useful to maintain a history of revisions that a programming unit has gone through. Typically, this revision history will be part of the comment preface block, and will note the name of the developer who has made a change, the date and a short description of the change, including the factors that necessitated it.
Tagging: Comments can be used to insert placeholders within code to serve as beacons for whoever maintains the code. Some commonly-used tags, such as FIXME and TODO, are frowned upon: if there is an issue that requires fixing or a task that requires completing, many argue, then that issue should be fixed immediately, that task completed. By tagging, the developer runs the risk of neglecting problems.
How to Comment
Commenting styles should be governed by a company’s development guidelines and, even within these guidelines, there is often enough wriggle room for individual style and subjectivity. Having said that, the following are a few rules and practices that I believe should be followed when commenting code.
Always include a preface: Always. It need not be a long essay – in fact, it should not be long – however, it is important to include one. Apart from focussing the developer’s mind around the task and assisting any maintainers that may come along in the future, prefaces can serve an important, additional function. Some languages – most notably Java, but also PHP – include API-generating functionality: Javadoc and PHPdoc, respectively. PL/SQL presents us with no such nicety, but if all programming units contain prefacing comment blocks, then we can write one of our own quite easily.
The end result will be a document (in my organisation, we have written a small, searchable Oracle Forms application) that exposes the various procedures and functions in a schema and includes a brief description of each one. This brief description will be the text of our prefacing comment block.
create or replace function plsqldoc (pName varchar2, pType varchar2) return varchar2 is /* ** This function will attempt to extract the prefacing comments ** for the parameterised programming unit. It assumes that these ** comments will be the first block comments that come after the ** the name of the procedure and extend over more than 1 line. ** It does not cater for overloaded procedures. ** ** pType will be either FUNCTION, PROCEDURE or PACKAGE BODY. It should match the types used in USER_SOURCE. */ vComment VARCHAR2(32767); vStart USER_SOURCE.LINE%TYPE; vEnd USER_SOURCE.LINE%TYPE; begin -- What line does the procedure start at? for i in (select min(line) line from user_source where name = pName and type = pType and (upper(text) like '%PROCEDURE %'||pName||'%' or upper(text) like '%FUNCTION %'||pName||'%')) loop vStart := i.line; end loop; -- Now look for the end of the first comment block that comes after this. for i in (select min(line) line from user_source where name = pName and type = pType and line > vStart and text like '%*/%') loop vEnd := i.line; end loop; -- Now we know where our text starts and ends all we need do is string it all together. for i in (select text from user_source where name = pName and type = pType and line between vStart and vEnd order by line) loop if vComment is null then vComment := i.text; else vComment := vComment||chr(10)||i.text; end if; end loop; return vComment; end plsqldoc;
Include a revision history: Anyone maintaining your code in the future will thank you for including a revision history. The identity of the developer who has made a particular change is not so important, however, it may one day be vital to know when a change was made and why.
Use line comments: A good rule of thumb is to use include a single line comment at the start of each logical block describing what it does. If, in the future, someone needs to maintain your code, they should not need to read every line of code to pinpoint the section they intend to edit; in fact, they should be able to navigate your whole procedure or package without reading a single line of code outside the actual section they are looking for. A good developer, unlike a good novelist, is one whose best work is never read in full.
Never depend on your memory: Everything is obvious while you are writing it; very little is that clear later. Writing something complicated? Comment it. Code, algorithms and assumptions that are perfectly clear at the time of writing, can quickly fester in a morass of spaghetti code with time.
Comment while maintaining code: If you are forced to wade through old poorly-commented or uncommented code that you or another developer has written, do not leave it as you found it. Comment it. While you may not be responsible for the way you find code, you are responsible for the way you leave it.
Keep it simple: Comments should be easily readable. Keep them as short as possible, and as plain as possible. Unless absolutely necessary, do not include any code in your comments.
How NOT to Comment
Do not underestimate your audience. Whoever reads your comment will also be a developer, hopefully a competent one. There is no need for comments along the lines of “This is a variable.”
Do not over-comment. Beyond describing your program unit and summarising logical blocks within it, restrict your commenting to explaining complicated sections and highlighting important facts that may otherwise be missed.
Do not use commenting as a means to leave in old, unused code. If a line of code is no longer needed, delete it. Do not just comment it out, or your packages will soon be littered with the corpses of redundant code.
Outside of the revision history section, do not date or sign your comments. They are comments; they are not great works of art and you are not Michelangelo.
Do not swear in your comments. Or be rude about your colleagues. Or your customers. Or your boss. Definitely not your boss. In the heat of the moment, the temptation to use comments as a pressure valve can be great. If you wish to keep your job, you will resist.
When interviewing prospective new staff, I give them a complicated problem to solve and leave them alone in a room for half an hour – an impossibly short time. When the time is up, I return and ask them to talk me through the code they have written. However, I only pay cursory attention to the code they have written – instead I study their comments. Their comments will reveal if they are the type of developer who understands a problem beforehand or one who dives in and hopes for the best. Their comments will reveal their mental processes, reveal if the way they break down problems makes them a good fit for my organisation. Their comments will reveal if they are methodical, how they handle pressure. They may even reveal if they have a sense of humour. Their comments will reveal how good they are.
Good developers write good code; great ones also write good comments.