Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
cs-236:style-guide [2017/01/19 14:58]
egm [Objects and Classes]
cs-236:style-guide [2017/07/11 14:59]
pdiddy [Summary]
Line 25: Line 25:
 #* Are test cases documented with justification and expected output? #* Are test cases documented with justification and expected output?
 # Variables and Constants # Variables and Constants
-#* Are the variables [https://​en.wikipedia.org/​wiki/​Camel_case camelCase] (with the first letter ​lower‐case) or with [https://​en.wikipedia.org/​wiki/​Naming_convention_(programming)#​Multiple-word_identifiers delimiter-separated words] that use lower case letters and underscores as delimiters?+#* Are the variables [https://​en.wikipedia.org/​wiki/​Camel_case camelCase] (with the first letter ​lowercase) or with [https://​en.wikipedia.org/​wiki/​Naming_convention_(programming)#​Multiple-word_identifiers delimiter-separated words] that use lowercase ​letters and underscores as delimiters?
 #* Are the constants all caps with underscores between words? #* Are the constants all caps with underscores between words?
 #* Are variables and constants initialized when they are declared? #* Are variables and constants initialized when they are declared?
Line 33: Line 33:
 #* Are all numbers in the code constants or fit reasonable exceptions? #* Are all numbers in the code constants or fit reasonable exceptions?
 # Functions and Methods # Functions and Methods
-#* Are the names [https://​en.wikipedia.org/​wiki/​Camel_case camelCase] (with the first letter ​lower‐case) or with [https://​en.wikipedia.org/​wiki/​Naming_convention_(programming)#​Multiple-word_identifiers delimiter-separated words] that use lower case letters and underscores as delimiters?+#* Are the names [https://​en.wikipedia.org/​wiki/​Camel_case camelCase] (with the first letter ​lowercase) or with [https://​en.wikipedia.org/​wiki/​Naming_convention_(programming)#​Multiple-word_identifiers delimiter-separated words] that use lowercase ​letters and underscores as delimiters?
 #* Are the parameter names descriptive?​ #* Are the parameter names descriptive?​
 #* Do the functions or methods only do task? #* Do the functions or methods only do task?
Line 40: Line 40:
 #* Are parameters declared as const-references where appropriate to avoid needless copying? #* Are parameters declared as const-references where appropriate to avoid needless copying?
 # Objects and Classes # Objects and Classes
-#* Are class names [https://​en.wikipedia.org/​wiki/​Camel_case camelCase] (with the first letter ​lower‐case)?+#* Are class names [https://​en.wikipedia.org/​wiki/​Camel_case camelCase] (with the first letter ​uppercase for class names)?
 #* Are the names descriptive?​ #* Are the names descriptive?​
 #* Does each class have a default constructor?​ #* Does each class have a default constructor?​
Line 187: Line 187:
 Group the code into common segments using newlines. For example, if a method consists of three distinct steps, then separate each step with a newline. Whitespace can be very effective in helping the code be readable. ​ Group the code into common segments using newlines. For example, if a method consists of three distinct steps, then separate each step with a newline. Whitespace can be very effective in helping the code be readable. ​
 = Test Cases = = Test Cases =
 +Test cases strive to ensure correctness in the code. Simple situations should be covered, but more importantly,​ obscure and less common cases need to be considered. For example, when testing a video game, testers do not simply play the game through; instead, they do obscure things such as walk into walls and corners, jump up trees, and cross invisible boundaries. Their goal is to '''​break the code'''​ : they want to find every possible error in the game, expose them, and then fix them. Tests should consider where your code could fail, and then test those areas. ​
  
 +Test cases should include the expected output, and where possible, assert that the program output matches the expected output. It is strongly encouraged, where possible, to write test cases first, with the expected output, before writing the program itself. Also, once the program is written, write additional test cases knowing how the program is written. In other words, use the understanding of the program to '''​break the program'''​ with unexpected inputs. ​
 +
 +Test cases should run automatically. A program should be able to compile or '''​run'''​ in test mode. Test mode runs all tests automatically and reports the test results. Failing tests can then be debugged using the test input. ​
 = Variables and Constants = = Variables and Constants =
 +
 +==== Use camelCase or underscore delimited names ====
 +Variable and parameter names must be written in [https://​en.wikipedia.org/​wiki/​Camel_case camelCase] with the first letter being lowercase or [https://​en.wikipedia.org/​wiki/​Naming_convention_(programming)#​Multiple-word_identifiers delimiter-separated words] that use lower case letters and underscores as delimiters. Which ever style is adopted, be consistent through all the code. 
 +'''​Do'''​
 +<code cpp>
 +//Always use camelCase
 +int numPeople;
 +</​code>​
 +or
 +<code cpp>
 +// Always use underscore delimited
 +int num_people;
 +</​code> ​
 +'''​And don'​t'''​
 +<code cpp>
 +int NumPeople;
 +</​code>​
 +or
 +<code cpp>
 +int numpeople;
 +</​code>​
 +or
 +<code cpp>
 +int numPeople;
 +int num_cars;
 +</​code>​
 +
 +==== Use descriptive names ====
 +Variable names should be descriptive and useful. For code with options, variable names such as “firstOption”,​ “first”,​ “seven”,​ or “optionA” are not useful; to make sense of these names other knowledge is required, which is not discernible from the name alone. Instead, give variables names meaning such as “averageClassSize” or “exitOption”. Furthermore,​ avoid using abbreviations and single‐letter variables; a good practice is to think, ''​Would a random person understand what this variable name represents?''​ Variable names are usually at least two words, except in exceptional cases like indexes (e.g. i, j, or k).
 +'''​Do'''​
 +<code cpp> ​
 +int numberOfBoxes;​
 +char userName;
 +</​code>​
 +'''​And don'​t'''​
 +<code cpp>
 +int boxes; ​
 +int b;
 +char k;
 +char usrKey;
 +</​code>​
 +
 +==== Use constants ====
 +Use const for any variable whose value will not be changing. Constants are written in upper case and underscore delimited (and are usually at least two words, except in a few obvious cases like PI, etc.).
 +'''​Do'''​
 +<code cpp>
 +const int MAXIMUM_WEIGHT = 300;
 +</​code>​
 +'''​And don'​t'''​
 +<code cpp>
 +const int MAXIUMUMWEIGHT = 300; 
 +const int maximumWeight = 300;
 +const int MAXIMUM = 300;
 +</​code>​
 +
 +==== Always initialize at declaration ====
 + ​Always initialize a variable or constant (meaning give it value) when it is first declared.
 +'''​Do'''​
 +<code cpp>
 +int numPizzas = 0; 
 +char userKey = ‘‐’;
 +</​code>​
 +'''​And don'​t'''​
 +<code cpp>
 +int numPizzas; ​
 +char userKey;
 +</​code>​
 +In some cases it will not seem necessary to initialize the variable; however, for example, by initializing numbers to 0 you can avoid potential difficult bugs when code is mistakenly using an uninitialized variable which contains an unpredictable value. Some types, like "​char",​ may not have a canonical agreed upon initial value, but by choosing a consistent initial value, such difficult bugs coming from unpredictable values are avoided. Some types, like strings, are automatically initialized;​ thus, these do not need initialization.
 +
 +====Declare variables at the beginning of their scope====
 +Variables are declared at the top of their enclosing scope (including main) except iterator variables in for loops; for example:
 +<​code>​
 +for (int i = 0; i < MAX_PIZZAS; ++i) {
 +   ...
 +}
 +</​code>​
 +Declare iterator variables in for-statements as shown above except in cases where the iterator variable is needed after the loop.
 +See the functions section below for variable and constant style when there are multiple functions.
 +
 +
  
 = Magic Numbers = = Magic Numbers =
 +Literals other than 0 and 1 should rarely occur in the body of code. Use constants or variables to replace such ''​magic numbers.''​ Using constants has two important advantages. First, they make the code easier to read. Your code should read more like English prose with numbers replaced by descriptively named constants. And second, in cases where the programmer wants to later change the value of a constant, it need only be changed in one place at the declaration,​ and it will be updated in all places throughout the program.
 +
 +For example, you would never have a line of code in you program like: 
 +<code cpp>
 +totalCost = numberOfLargePizzas * 14.88;
 +</​code>​
 +The literal 14.88 is a magic number and does into indicate the meaning of the value. Correct style declares and initiates a const variable at the top of the function and then later uses it in the code. 
 +<code cpp>
 +const double COST_OF_LARGE_PIZZA = 14.88;
 +totalCost = numberOfLargePizzas * COST_OF_LARGE_PIZZA;​
 +</​code>​
 +The end goal is to 1) make the code easier to read, and 2) make the code easier to maintain so if/when the pizza cost is updated, the only change is it at the declaration.
 +
 +As with anything, there are exceptions for using literals in the body of code. Common mathematical formulas are good examples: ​
 +<code cpp>
 +circumference = 2 * PI * radius
 +</​code>​
 +In this case there is not good name to replace the 2, and if the literal were replaced with a constant, it would probably make the formula less readable. Also, since it is a mathematical axiom, the value would not be changing in the future, so nothing is gained with a constants. Such situations occur rarely in general. When in doubt though, prefer using a constant.
 +
 +The literals 0 and 1 are also notable exceptions. Here are some guidelines for when to use such literals
 +* Initializing variables at declaration including index variable in loops
 +* Initializing or reinitialization indices or counts
 +* Incrementing or decrementing variables---though pre/​post-increment or pre/​post-decrement operators should be preferred
 +* Return values from methods or functions: return 0 or return 1
 +* Simple boundary and index adjustments of variables: i < str.size() - 1
 +
 +Note that just because a value is 0 and 1 does not mean it should never be a constant. In fact, in cases except for the above, a 0 and 1 should be a constant. For example, a specification may state that 1 large pizza feeds 7, a medium 3, and a small 1. 7 and 3 are obvious magic numbers. But so is 1, both because the meaning of 1 in the coding context may not be obvious, and because the number of people a small pizza feeds may change.
 +
 +It is important to note that constants can be abused. Two common abuses are
 +# ''​const int ZERO = 0;''​ This constant accomplishes nothing of use. It does not make the code more readable (0 and ZERO are equivalent) and it does not make things more adaptable--the value of ZERO will never be changed. ​
 +# ''​const int FIVE_YEAR_LOAN = 5;''​ The issues are the same as the previous example. A more appropriate name would be ''​TERM_OF_LOAN_IN_YEARS'',​ which is both descriptive and is obvious to change later if needed. ​
 +
 +Here are other example of where using a constant is expected and appropriate:​
 +* A constant to set the random seed for random number generators: ''​rand() % RAND_RANGE + RAND_OFFSET''​
 +* Calls to format cout: ''​setprecision'',​ ''​sets'',​ ''​iomanip''​ etc. 
 +* Floats usually are never compared directly for equality, so use a constant is appropriate:​ (x – y < FLOAT_EPSILON)
 +* Options for error codes or user input: ''​userOption == QUIT_OPTION''​
 +
 +As a final note, string literals are a little different than number literals so ''​magic strings''​ are treated differently than magic numbers. ​ If for example the code is ''​if (userOption = “quit”)'',​ “quit” is a magic string. In most of these situations the string is already readable, and just used in one place, so a constant is not required. ​
 +
  
 = Functions and Methods = = Functions and Methods =
-Use +Names should use [https://​en.wikipedia.org/​wiki/​Camel_case camelCase] (with the first letter lower‐case) or [https://​en.wikipedia.org/​wiki/​Naming_convention_(programming)#​Multiple-word_identifiers delimiter-separated words] that use lower case letters and underscores as delimiters.  
 +* Names should be descriptive,​ but not burdensome, and strive to avoid needing a comment header for further clarification.  
 +* The body of the function or method should typically less than 20 lines and at most 40 lines. 
 +* '''​Do one task.'''​ For example, a function should not '''​1)'''​ return the total number of words in a document '''​and'''​ '''​2)'''​ capitalize the first letters of all the words. Each of these should be in a separate function '''​unless'''​ there is a compelling reason to do otherwise which should be documented in the code.  
 +* [https://​en.wikipedia.org/​wiki/​Don'​t_repeat_yourself Don't repeat yourself] (DRY). There should not be duplicate snippets of code.  
 +* If passing a large data structure, prefer passing by reference, and if that structure is not intended to be updated, then prefer passing by const reference. Using standard variable naming conventions for const parameters (e.g., these are not constants in the code and should not be named in all caps).  
 +* Variables and constants should be declared at the beginning of the scope in which they are used.  
 +* Functions and methods should assert assumption on parameters. For example, if there is an assumption that a pointer is not null, such an assumption should be asserted: ''​assert (boxPointer != NULL);''​. Or as another example, if an integer parameters is assumed to be positive in the code, such an assumption should be asserted: ''​assert(numCars > 0);''​. Asserting assumptions is another form of self-documenting code and helps others use the code as it was intended by the original author.  
 + 
 +The size limit and one-task requirement affect the complexity of the code. Generally shorter code is simpler to write, easier to understand, and less likely to have defect than longer code. Like any guideline though, it is just a guideline. The ability to read and maintain the code is the high-order bit that overrides these guidelines. If something a bit longer or that does multiple things is easier to understand, maintain, and test, then do it. 
 = Objects and Classes = = Objects and Classes =
 * Class naming is CamelCase with uppercase first. Member functions follow the same naming rules as functions. * Class naming is CamelCase with uppercase first. Member functions follow the same naming rules as functions.
Line 201: Line 334:
 * Non-primitive parameters should be const-references when appropriate. * Non-primitive parameters should be const-references when appropriate.
 = Miscellaneous =  = Miscellaneous = 
 +* Write self documenting code.  Self‐Documenting means that a person reading your code can understand what it is doing without the need of extra comments; therefore, self-documenting code does not have many comments by definition. This mindset does not absolve the need for comments---they are still required---it implies that they only appear in the more esoteric or complex parts of the code. 
 +* There are time when a global variable is the right thing to do, but those times are rare. Be sure that if a global variable is being used, then it is both warranted and justified; warranted and justified means that doing it any other way degrades the readability,​ maintainability,​ or testability of the code.   
 +* There are times when a goto-statement is the right thing to do, but such times are near extinct. Be sure that if a goto-statement is employed, then it is more than obvious to why it is necessary. ​
 +* break-statements and continue-statements are powerful tools but not used often. Be sure, as with other discouraged statements, uses are merited and justified in terms of readability,​ maintainability,​ or testability. ​
 +* Use "​endl"​ rather than "​\n"​ --- it C++ after all. 
 +* Declare the '''​main'''​ function to return an integer, '''​int main()'''​. A 0 return value means everything ran without issue. A non-zero value indicates otherwise. Non-zero values can have meaning that should be documented somewhere. ​
  
cs-236/style-guide.txt · Last modified: 2017/07/11 14:59 by pdiddy
Back to top
CC Attribution-Share Alike 4.0 International
chimeric.de = chi`s home Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0