Tuesday, August 20, 2013

Clean Code - Assessing Code Quality - Part 2

Clean Code starts with good names

Articulate names for your coding objects are the primary tool for creating clearly understandable code.

Do not add gratuitous context

Prefixing your code names with extra context like the business name, name space, or extra type information just add superfluous information that must be read. Give your object a good descriptive name, and leave off the code hierarchical context, you tooling can tell you how it participates in the hierarchy.

What is in a Name?

Objects and Functions

Objects should use Pascal Case, and start with a capital letter and Functions should be Camel Cased, and start with a lower case letter.  

Classes and Variables

Classes and variable names should be nouns, named after a problem domain actor, a system API or an artifact. Examples are Document, and User. Classes should use Pascal Case, and start with a capital letter.

Interface

An interface should be an adjective, or in some cases a descriptive noun.  Interfaces should be named as nouns, noun phrases, or adjectives that describe the behavior. Interfaces are prefixed with an “I” Examples are printable, and enumerable, don’t be afraid to make up your own adjectives.

Functions and Methods

Functions and methods should have names that are verbs, denoting the action they are going to take. Methods are Camel Case, and start with a lower case letter.  Examples are export, save, add, delete.

Methods Names

Method names often need to have more information to differentiate the method between implementations.  So often you will need to suffix your name with a Camel Case description of the operation details. For Example, saveToDisk, and printToClient.

Adding Method Scope Information

Often with a complex class, we can have multiple methods that perform similar actions but differ by the arguments that they take. Most often we tackle that problem with method overloading with the same name and different signature, but sometimes it is helpful to add an adverb explaining the “how” that happens to the verb.

Abbreviations

Most Abbreviations only obfuscate the meaning of the code, so in most cases use the full word. Notable cases are where the Comp-Sci Solution Domain standard abbreviations exist. Below is an example of standard names.

Abbreviation
Description
arg
argument (function parameter)
bin
binary
bool
boolean
char
character
doc
document
elm
element (dom node)
fn
function
hex
hexadecimal
id
identifier
int
Integer
max
maximum
min
minimum
num
number
obj
object
oct
octal
prop
property
seq
sequence
str
string
substr
sub-string

Adding Scope into a name

Sometimes it helps to add scope into the name of an object.  We can note an object as being internal to its parent by prefixing it with the underscore sigil, marking _tempName as private to the function. A not on JavaScript and closure, never mark a variable that you are going to be closing over as private, as this send that wrong signal.
For noting that an object is in the global scope, prefix the object with global, and for the object using camel casing. Like globalUserPrintQueue, note that we prefix with scope, include information from the problem domain, and then include information from the solution domain.

What the Name Describes

The name primarily should describe the behavior of the problem domain. If the solution domain will assist in the next programmer’s understanding then include that also in your name.  So if the item in the problem domain is the “User” and we want to make a standard assembly for creating the user. We can use the description from the solution domain. So we have userFactory.

Functions are Cohesive

A function should be both compact and cohesive.  The function body should be less than thirty lines of code, and should perform only one function without side effects. All the actions that the function should perform should form a coherent whole, and only perform one operation or just one set of coherent operations.

One Level of Abstraction

A function should contain only one level of abstraction. Like in the case of the solution, would be one level of abstraction and a separate level of abstraction, animal.  So we want our method to contain only one level of abstraction, of course polymorphism is excused from this.

Logically Organization

Your classes should be logically organized, and the flow should be from less-complex, at the top to more-complex, the implementation details, towards the bottom. Your code should progressively reveal complexity to the maintainer as your code is read, divulging intricacies like an onion.

You should group Classes that perform similar operations into Namespaces, establishing a code hierarchy.

Note on case and notations:

Pascal case: The first letter of all words is capitalized; no spaces, underscores or special characters are used. Example: BackgoundColor, Gray.
Camel case: Except for the very first letter, with is lower case, the first letter of all words is capitalized, no spaces, underscores or special characters are used. Example: backgoundColor, gray.
Uppercase: All the letters are capitalized, by common convention this is reserved for use on abbreviations of 4 letters or less.  Example:  System.IO, MSDN.Library
Hungarian notation:  The name will be prefixed with an abbreviation of the objects data type, and be in Camel case, meaning that the first letter (the abbreviated type) will not be capitalized, but the beginning of each word after will be capitalized.

So some rules from Clean Code

1.       Do not add gratuitous context.
2.       Use Names based on the solution domain first, and then names based on the problem domain.
3.       Use descriptive names.
4.       A method should be cohesive, and responsible for only one thing.
5.       Include only one level of abstraction in a method.

No comments: