Feedback on Programming Assignments
Random comments
- Grading is largely subjective. In general a grade of >90 means that I found the assignment to be very well done with perhaps only a few minor flaws. Grades of around 80-89 were given to assignments that were largely fine functionally but had ugly aspects, such as printing an exception trail, overly ugly output, or minor mistakes in dealing with the protocols or data. grades in the 70s typically represent more major functional problems but core network interactions should be present. Grades from 50-69 represent more serious problems with networking and crippling functionality. Grades below 50 indicate that the assignment was largely non-functional for all practical purposes.
-
Is it that hard to create a file called
idwith two lines of text in it? I get lots ofid.txtand even anIDINFO. It's just a simple two-letter filename! Runcat idand make sure that you have a newline at the end of the last line. -
I asked for an
idfile so I can easily identify the author. If you decide not to supply one, at the least be sure to put your name as a comment in your code. -
Check your command-line parameters! It's the easiest, most mindless thing to program. It's also your first line of defense against dumb users. If there are too few or too many, print a usage message. If the wrong flags are used, print a usage message. If parameters are incorrect, such as a port number not being a number, then say so.
-
Print useful diagnostics and a usage message. Tell the user what went wrong and how to use the command. There are good and bad examples out there. Follow the good ones. Think of what you, as a user, would like to see. Here's one example of a Unix command producing an error message:
$ dd -? dd: unknown operand -?The error is helpful if you know exacly what you're doing but your fingers slipped and you mis-typed but otherwise it doesn't help you if you sort of know what you're doing but you forgot something. Here's another example of a Unix command producing an error message:
$ mv -? mv: illegal option -- ? usage: mv [-f | -i | -n] [-v] source target mv [-f | -i | -n] [-v] source ... directoryVintage 1970's Unix commands favored the former. The goal was to optimize the experience for the user who knows what he/she is doing, not the n00b. In the 1980s and 1990s, Unix (and derivatives) typically produced more useful messages - still terse and still assuming that the user essentially had a clue but may have forgotten some details.
Having the command name present in the error message is extremely useful when the command is used in scripts so you know what command caused a problem. You can get the command name from the first argument that is passed to the main function:
argv[0]. -
Never let me see a java exception dump! You should catch expected exceptions and print a human-friendly error related to what you're catching (such as an invalid port number). The exception dump should be reserved for bizarre situations that you never expect to occur - not because of something as simple as bad user input.
- If you submit a makefile, make sure it works!
-
In C, declaring:
char blah[] = "blah";is the same as declaring:
char blah[] = { 'b', 'l', 'a', 'h', 0 };The former is easier to read. If you're defining a string, use that form.
-
Remove debugging information or make it optional and very clear. For example, one program shows:
ok Opening file for writing... true Transfer .-1At some point, these messages were useful to the programmer. For a user, they're cryptic and meaningless and should not be there. In fact, the messages will probably be meaningless to the author within a month. If you want debugging info to be visible after your assignment is complete, try to make the messages sensible and also use a command-line option to trigger it (such as
-d). For example, something like:connecting to localhost on port 12345 connected! sending "get testfile" received 14 bytes closing connectionFor pure debugging (not something you want to expose to the user), you may find the symbols
__FILE__and__LINE__handy (that's two underscores before and after the names). They expand to the filename and the line number in your code. For example, you may write:fprintf(stderr, "%s: %s: line %d: connecting to \"%s\" on port %d\n", cmd, __FILE__, __LINE__, host, port);When run, you'll get a message that looks like:
get: get.c: line 171: connecting to "rosebud" on port 12345 cmd, __FILE__, __LINE__, host, port);I put quotes around the host name to make it easier to discern if the name is corrupted by something like a stray space. If I see
connecting to "rosebud "then I know something's wrong. -
Don't bother sending me Windows BAT files! They're beyond useless to me.
-
IF you do something extra or if something doesn't work quite right, be sure to note it in a
READMEfile (it doesn't have to beREADME.txt). This is especially crucial if you added something extra to your assignment or if it's really in an inadequate state. - The reason I ask you to not mix leading tabs and spaces is that your indentations end up looking inconsistent when I open your file. That can make even good code look like crap. I'll use vi to open your files and will not fiddle with tab setting. I don't care if it looked great in your IDE.
- If you use malloc, be sure to free the data with free when you no longer need it. For most programming tasks, you hardly ever need to use malloc – or you need to use it a lot less than you think. For assignment 2, for example, you simply don't need it. A static buffer for the incoming command and a static buffer for chunks of the file are all you need.