Good programmers take pride in producing code that is well organized and easy for others to understand. In CS 117 your programming scores will be reduced, in some cases significantly, if your code is not easy to follow: this may take more effort than you expect, but we are serious about it. You are at a level where the work you do should always be at or near professional standards, and that means taking great care to produce beautiful source code.
The best coding standards are aimed at meeting the needs of those who will work with your code, and not every audience is the same. In 117 your code is intended for you and your partners, but especially for the CS 117 graders. Reading your code should not be a test of their C++ or networking expertise: if anything in your code is subtle, it should be explained. It should be easy to find which part of your code does what by skimming.
Because they are intended as learning tools, the CS 117 samples
are somewhat more heavily commented than I would typically do, but
the general style and attention to detail is typical of what I would
expect on the commercial projects I've helped build.
Take a look at some of the framework code (maybe
src/c150dgmsocket.cpp in the
/comp/117/files/c150Utils/ dir) and it may give you some ideas.
Specific coding requirementsThe following is always required:
- Code must be indendented properly and consistently (you can decide whether to use 2, 4 or 8 bytes indent for nested blocks). You must stick with a consistent convention for things like curly braces on if statements and functions.
- Variables should be named clearly: buffer_length or bufferLength is good; blen is not
- Likewise function, method and class names hould be well chosen
- Each class should be in a separate .cpp file with a separate .h file to match. We suggest class and structure names be capitalized, variable names lowercase, and constants and #defines in ALLCAPS.
- Usually, functions longer than 30 or so lines of code are a mistake (not counting comments); the exception is if the structure is very regular (e.g. a long switch statement)
That said, writing clear, consistent and beautiful code trumps any specific detailed rule.
Commenting and Source Code Layout
Commenting and layout of your source code is important! Use comments whenever they make your code easier to understand, and also to make it easy for new readers to immediately spot the parts of the code they're looking for. As you write your code consider: who is your audience? Who will be reading and maintaining your code?
For our sample code the the audience is you and the purpose
is to teach you as quickly as possible to use the framework.
Thus, as previously noted, the samples are commented somwhat more heavily than
would be typical for other purposes.
The framework files in
c150Utils are closer to what
I would do for commercial code (which I expect to maintained and used by
other programmers), but even those are somewhat over-commented
to help provide extra information for students using the framework.
Unlike some other very good
programmers, I do tend to err on the side of more commenting
and trying to make sure that the source is easy to skim. Thus, it's easy in the sample
to skim to the
checkAndPrintMessage routine without picking through code details.
That's because the starts of functions and their names are always set off
in a way that's easy to spot.
That sort of clean formatting is
a good thing to do, especially if code is more than a page or so long.
- Each function and method should be set off distinctly in the source, and unless its purpose and interface is completely obvious, comments should explain
- Each significant structure or class should have comments at the head and possibly inline explaining its purpose and use
- Comment individual sub-sections within runs of code only when necessary to make it easy for readers to find them, or to explain what's not obvious from the code itself. A comment that says "loop with i from 1 to 10" is usually redundant and risky; a comment that says "Loop through buffer slots 1 to 10: note that we don't start from zero, because that slot will be filled in later" may be very helpful.
- A comment on a variable or member declaration can often be useful since the
variable name is short and can only explain so much. For example,
struct timeval timeout_length; // When zero, then no timeout. // Otherwise max length of time // our socket operations can take. // NEEDSWORK: does this apply to writes? bool timeoutHasHappened; // Set false before each read // true after read if timedout unsigned short userport; // The port for this c150 user name // this is in local, not network // byte order!
Although the members have meaningful, carefully chosen names, the comments on the right will save someone a lot of trouble figuring out their intended use. When there's nothing to add, leave out the comment; when the comment is useful include it.
Some programmers worry that a comment like this can be out of sync with the code: true, but that's not all bad. Half the time the code is what's wrong, and the comment will alert you or whoever is debugging. The other times the mismatch will alert you that there was at least some vagueness in thinking about the code, and after sorting it out, you can fix the comment.
Again, you are not expected to comment nearly as generously as in the samples. You are expected to write clear, well organized code, and to use comments as needed to achieve that.
The sample above happens to show a trick I picked up 30 years ago while working on the LOCUS distributed system. If there's anything you're not sure about or that needs more work, leave a note with a very clear marker that's easy to find with a search. The keyword we used and that I still use is: NEEDSWORK.
Of course, if your NEEDSWORK says that your program is totally broken we can't give you a lot of credit, but mostly your grade will go up rather than down if we see that you understand the limitations of your code.
The real value is that before you submit you'll be able to search for all the things that weren't perfect and decide which to fix. For the ones you don't, definitely leave the NEEDSWORK marker (or whatever you choose). Weeks later, when you hit a bug, these things can save a huge amount of time. Your program crashes, you open the code, and right there is the comment that says: "NEEDSWORK: not handling buffers > 1000bytes". I only see this occasionally in commercial work, but I encourage it as key to the coding standards for any team that I lead.