1 ProgrammingStandards


Here are some coding tips, and details about grading programming assignments.

1.0.1 Coding Tips

Give me six hours to chop down a tree,
and I will spend the first four sharpening the ax.
- Abraham Lincoln

This is true in coding as in chopping.
Resist the urge to start coding right away.
Spend 90% of your time preparing, and 10% coding, and you will spend less net time!
Attempt to spend 10% preparing, and 90% coding,
then you may end up never understanding, and frustrating yourself, wasting your time
If I want to learn a new protocol, language, etc.,
then I spend 90% of the allotted time on learning (studying),
and 10% on producing the product (the assignment).
Time pressure can get to one’s head, encouraging the opposite,
trying to complete the product first, before learning.
Resist that urge!
The time to complete each of these typically takes 2-5 hours for a top-30% grade student,
about 10-25 minutes for myself, and maybe 30 min-1 hour for my TAs.
Spend time on preparation not production!
Spend time enjoying learning the material,
not anxiously getting through through the assignment!

After all, programming is mostly thinking:
https:/agileotter.blogspot.com/2014/09/programming-is-mostly-thinking.html

An apprentice carpenter may want only a hammer and saw,
but a master craftsman employs many precision tools.
Computer programming likewise requires sophisticated tools,
to cope with the complexity of real applications,
and only practice with these tools will build skill in their use.
~ Robert L. Kruse, Data Structures and Program Design

1.0.2 Basics

All of the functions in files we provide must be completed as directed by the comments.
Changes to function names or parameters may mean we cannot properly grade that function,
and you may not receive any points for it.
Do not edit any header files unless we say so explicitly!
If there is any doubt, do not edit the header files.
Carefully read the comments of each member function,
noting both return values and output statements (they are not the same!).
Develop your classes and/or functions one at a time, starting from the simplest modules.
Move to the next function only after the previous one has been tested.
Trying to code a whole class, and then remove the bugs afterwards,
will likely prove to be too big a task.
It may help to build your own simple test cases.
Print plenty of status messages to track the progress of your algorithm
(and remember to comment them out before submission).
Using Windows or online web-based compilers can come back to bite you,
so test on the desired platform (class container).
Stick to local IDEs that are Linux compatible, for example within the class VM.
Use the supported language and version (e.g., python3 not python2, gcc-c++ not MS-visual-studio C++)

1.0.3 Diff tools

Diff tools are helpful for comparing two folders of files,
or comparing two of your output files.
Compare your output to any given sample output to make sure they are the same,
including all newlines and spaces, via bash:

./yourcode.whatever <sample_input.txt >your_output.txt

# or for two-column format (easier to see):
diff -y --color sample_output.txt your_output.txt

# or using vim:
vim -d sample_output.txt your_output.txt

# or using git-delta
delta sample_output.txt your_output.txt

# or in a GUI:
meld sample_output.txt your_output.txt

1.0.4 Grading technical assignments

Points / scoring

Environment
It is expected that all of your work runs correctly,
in the specified Linux environment we are working with in class,
in the exact manner we specify in the assignment description.
If you were contracted to write code for a job, and it ran on your computer,
but not your employer’s as they needed, your work would be considered a failure.
In that light, you are also responsible for submitting all text and source files,
such that they are compatible with our specified environment,
e.g., encoded UTF-8, Unix delimited, etc.

Test cases
The test cases we will run for grading may be more extensive than any fixed sample input we give you,
for example by using a randomized unit test (which you can still see).
It is possible, even likely, that if your program seemingly works perfectly,
for example with an input file: sample_input.txt,
that it may not work perfectly with our grading scripts or random unit tests;
this is fair and reasonable challenge,
since we describe the bounds of performance required generally;
when coding in the real world for a job,
you will be expected to anticipate edge cases, weird behavior, larger than expected data-sets, etc.
Practicing this can help you train one of the more important skills of an industry programmer.
You should manually try some failing test cases yourself, that have input and output,
perhaps different or which exemplify some edge case.

Style
Good programmers don’t always have good comments,
but they almost always have clean, consistent, readable code style and formatting…
Take pride in your code!
If your assignment is in Python, Bash, C++/C, or Rust,
we grade your code using auto-formatters like:
black, shfmt, clang-format, or rustfmt respectively.

Normalization
After grading any given assignment,
if that assignment appeared to be too difficult for the class,
I may choose to normalize to the top student’s performance
(the student with the highest point rank will get a 100% / A).
This can, by definition, only help your grade, but not hurt it.
I won’t ever do the opposite (lower grades).

Precision unit testing
In the real world, and in industry, most of code is tested by code.
When a networked program, or an operating systems program, or a web program,,
does not have perfectly spaced output, it does not work, at all...
Computers are not flexible; they are rigid, and they need babying!
Code that is merely run-able (playable, produces output, etc.)
is NOT correct code!
Getting workable code is the first half of the assignment.
Getting your workable code to be correct in all the remaining needed details,
is the second half of the assignment.

Files should be in UTF-8, Unix/Linux delimited
(which if you used the class Linux environment,
without copy-pasting from your host OS, you should be fine).
Make sure to download and use the sample input and output text files we gave,
not the text copied into a new text file you made.
Your program compiles and runs in the specified Linux environment
Check that file names match requirements and/or have not been changed
Are you testing your execution with unchanged header files if specified
(by checking the file in an old commit),
in case you edited for debugging purposes?
You should almost never edit the header files!
Did you check the program with more input / output test cases than we gave you,
by generating your own?
Did you check that your functions all have the right inputs and outputs,
even if they also have outputs to the screen?
Did you push your latest commits, and check you can see them online,
in the Gitlab git-classes interface?

What is “correct code”?

1.0.5 Specific language standards

These are operationally enforced in grade.sh:
ClassroomCode.html

1.0.5.1 Execution of Bash programs

Bash is standard.
Some other shells like fish are nice, and those like nushell are innovative.
All bash code for my classes must be auto-formatted by shfmt with the following arguments.

Pre-check and fix warnings where needed:
$ shellcheck yourscript.sh

Pre-format
$ shfmt -i 4 yourscript.sh

Run code as:
$ bash yourscript.sh

without the need for a shebang, or
$ . yourscript.sh
or
$ ./yourscript.sh

where this is at the top of your file:

#!/bin/bash
actually specifies un-ambiguously the use of bash, and the binary location. This is the one you should use.

#!/usr/bin/env bash
specifies ambiguously the use of bash, but not the binary location, thus opening a security vulnerability; env was not intended for this purpose, and it’s use here comes with a number of concrete disadvantages.

#!/bin/sh
is the system’s default shell, and is ambiguous. This is like saying (by analogy), I scripted this, maybe in python2, maybe python3, or maybe even perl…and you’re supposed to guess blindly. It sometimes means a POSIX compatible shell, but not always.

Debug your code:
bash -x yourscript.sh args if any
or
bashdb yourscript.sh args if any

1.0.5.2 Execution of Python3 code

All code for my classes must by type-hinted (Python 3.6+); this is enforced by mypy (below).
All code for my classes must be auto-formatted by black.

Pre-check your code, and fix all warnings:
$ mypy --strict --disallow-any-explicit myscript.py

Pre-format your code:
$ black myscript.py

Run:
$ python3 myscript.py
or
$ ipython3 myscript.py

Put this at the top of your scripts:
#!/usr/bin/python3

not this:
#!/usr/bin/python
#!/usr/bin/env python3
etc…

I have also built a customized call-graph and control-flow-graph generator for python scripts. In the class VM, you can use it as follows:
$ py2cfg mycode.py

The ipython3 interpreter and python3 interpreter do some things differently:

Debug your code by stepping through it:
$ pudb3 mycode.py
or
$ pudb3 mycode.py arg1 arg2 argn

1.0.5.3 Execution of C++ code

We use C++ 11 and 14+ features.
If you are using an old computer (campus machines),
then you may need to specify a higher version: -std=c++14 or -std=c++11
If you are using the class VM or container, then you do not need to include version options at compile time.
All code for my classes must be auto-formatted by clang-format using the following arguments.

Pre-check with:
$ cppcheck yourcode.cpp
or more specifically:
$ cppcheck --enable=all --language=c++ ./*.cpp ./*.h ./*.hpp

Pre-format with:
$ clang-format.py -i --style=Microsoft ./*.cpp ./*.h ./*.hpp

Compile with debug flags:
$ g++ -g file1.cpp fileN.cpp -std=c++14

Compile with extra nagging (a good thing):
g++ -g -Wall -Wextra -Wpedantic -pedantic-errors *.cpp -o yourbinexe

To run:
./a.out

For example, run with:
$ ./a.out
or
$ ./a.out <"sample_input.txt"
or
$ ./a.out <"sample_input.txt" >"your_output.txt"

Check for memory leaks with:
$ valgrind ./a.out <"sample_input_if_exists.txt"
or, for example:
$ valgrind --leak-check=full ./a.out <"sample_input_if_exists.txt"

Debug your code:
using cgdb
$ cgdb ./a.out
(gdb) start
or
(gdb) start <stdinfile >stdoutfile
(gdb) start arg1 arg2 argn <stdinfile >stdoutfile
or use gdb
$ gdb ./a.out
(gdb) layout next to show code
(gdb) start
or
(gdb) start arg1 arg2 argn <stdinfile >stdoutfile

1.0.5.4 Execution of Rust code

A breath of fresh air:
cargo run