This class focuses on the study of algorithms and data structures, exploring both their theoretical foundations and practical implementations. Equally as important, however, is the art of producing clean, understandable, and correct code.
The essence of high-quality code lies mostly in its clarity and readability. Readable and clear code is easier to debug (and less prone to bugs in the first place) and it is easier to work on in a team (and you will soon have to work on assignments in pairs).
With this in mind, we will share with you 4 broad, easily memorable principles that you should follow when you are writing your code.
When working on your assignments from now on you should apply these principles. Apply them while you are working on your assignment, don't write a really messy program and then try to make it better using these principles, that defeats the purpose of this. In all future assignments we will be grading for style and you will lose points if you break one of these principles (more on this at the end of the page).
Here are the four principles:
Descriptive naming involves choosing names for variables, functions, classes, and other entities that clearly reflect their purpose, usage, and scope. Good names make code more readable and understandable without needing additional comments to explain what an entity does. Consider the following when writing your programs:
nounToIdMap
, newCapacity
, numberOfElements
(you can guess what these are for with no context)
temp
, data
, n
resizeArray
, updateBestWeight
, validateNamesList
validate
, handleData
n
and N
, or list
and lists
usrPrf
instead of userProfile
)Modularity refers to the practice of structuring a program into distinct, independent modules that can be combined together to form a complete system. Reusability is a related concept where modules are designed to be reused in different parts of a program or in entirely separate ones. Consider the following when writing your programs:
convertCoordsToIndex(int row, int col)
for converting grid coordinates to an array index and validateCoordinates(int row, int col)
for checking boundaries
CONFIDENCE_INTERVAL
in Percolation when calculating degrees of confidence
1.96
Effective comments provide clarity and context to code, explaining why certain decisions were made, the purpose of complex sections, and how they fit into the larger picture. Writing good comments is an art and it is very easy to either write too many comments or not enough comments.
numberOfElements++; // Increments
number of elements
is completely useless since it is obvious by
looking at the code that it incrementing a variable.
// Takes char target and String text as parameters. Finds and returns the first index at which target appears in text
// Iterates through the second parameter using a for loop to find where the target appears
// Stores the total number of elements in the hashtable
// num elems
// Counts and stores number of replacements in inputText in textCounter
// While loop
In summary, comments should act as documentation that provides context, and not like a description of what the code is doing. Code should be self explanatory, and it will be if you follow good naming practices (P1).
Simple programming is about keeping the code as straightforward as possible and avoiding unnecessary complexity.
One common source of overly complicated code is programming before thinking. Before typing a single letter on your laptop, you should stop and think clearly about what you want to do. We have a tendency to want to start implementing something after developing a fuzzy idea of what the solution should be. As we write code we realize that something we did 5 lines ago isn't quite what we wanted, so we might backtrack 5 lines and fix that, and then keep going. But now the fix isn't compatible with this other part of the code that was written with the previous code in mind. And soon our code isn't a sequence of clearly connected lines, but yet a series of patches that are messy and hard to understand. This is especially relevant for implementing algorithms and data structures, since these programs are often very logically dense (i.e. a few lines of code have a lot of non-trivial conceptual ideas).
Note that these are principles and not rules. They are here to help you write better code, not to constraint how you program. So you might find that you might need to break one of them occasionally, and that's ok.
Mostly adhering to these principles as you compose your assignments is crucial. Rewriting messy code later defeats the purpose of us teaching you style. Furthermore, in all future assignments we will be grading the code style of your assignment submissions based on these 4 principles. On your code feedback you might see style warnings and style errors:
(Also, just to reiterate this point, you will not lose points on Percolation for style, but you might see warnings)
You probably have seen the checkstyle feedback the both IntelliJ (the yellow warning signs) and the autograder give you. Given these style principles, should you ignore it? Well yes and no. For context, checkstyle contains a long list of rules that the Java source code adheres to (you can read about them here). These are great rules, but they are often too strict, and they only care about the syntactic aspects of style (e.g. are you using the right number of space) and ignore the semantic aspects (e.g. are you naming your variables well).
So, contrary to what was done in the past, we won't grade the style of your programs according to the checkstyle output, we will instead use the process specified above. However, the checkstyle is your friend, you shouldn't ignore it. If you have 8 or more checkstyle errors, odds are you are doing something wrong and you will probably get a style error somewhere. Our advice is to carefully read the feedback of checkstyle and decide whether or not you want to integrate it. Don't ignore checkstyle!