Clean Code
Clean Code
1 / 24
Clean Code
2 / 24
Meaningful Names
Much better:
1 int elapsedTimeInDays;
2 int daysSinceCreation;
3 int daysSinceModification;
4 int fileAgeInDays;
3 / 24
Avoid Disinformative Names
Avoid names with baggage, unless you want the baggage.
I hpnot a good name for hypotenuse. hp could also be
Hewlett-Packard or horsepower.
Don’t hint at implementation details in a variable name.
I Prefer accounts to accountList.
I Note: certainly do want to indicate that a variable is a
collection by giving it a plural name.
Superbad: using O, 0, l, and 1.
1 int a = l;
2 if ( O == l )
3 a=O1;
4 else
5 l=01;
Don’t think you’ll never see code like this? Sadly, you will.
4 / 24
Avoid Encodings
5 / 24
Clean Fuctions
6 / 24
Writing Functions that Do One Thing
One level of abstraction per function.
I A function that implements a higher-level algorithm should call
helper functions to execute the steps of the algorithm.
Write code using the stepdown rule.
I Code should read like a narrative from top to bottom.
I Read a higher level function to get the big picture, the
functions below it to get the details.
Example of stepdown rule/newspaper metaphor:
1 private void createGui() {
2 add(createDataEntryPanel(), BorderLayout.NORTH);
3 add(createButtonPanel(), BorderLayout.SOUTH);
4 setJMenuBar(createMenuBar());
5 }
6 private JPanel createDataEntryPanel() { ... }
7 private JPanel createButtonPanel() { ... }
8 private JMenuBar createMenuBar() { ... }
7 / 24
Function Parameters
Common one parameter forms
I Predicate functions: boolean fileExists“(”MyFile)
I Transformations: InputStream fileOpen“(”MyFile)
I Events: void passwordAttemptFailedNtimes(int attempts)
9 / 24
Avoid Side Effects
10 / 24
Avoid Side Effects
Has the side effect of initializing the session. Might erase an existing
session, or might create temporal coupling: can only check password
for user that doesn’t have an existing session.
11 / 24
Command Query Separation
Consider:
1 public boolean set(String attribute, String value);
12 / 24
Prefer Exceptions to Error Codes
Error codes force mixing of error handling with main logic :
1 if (deletePage(page) == E_OK) {
2 if (registry.deleteReference(page.name) == E_OK) {
3 if (configKeys.deleteKey(page.name.makeKey()) == E_OK){
4 logger.log("page deleted");
5 } else {
6 logger.log("configKey not deleted");
7 }
8 } else {
9 logger.log("deleteReference from registry failed"); }
10 } else {
11 logger.log("delete failed"); return E_ERROR;
12 }
14 / 24
Clean Comments
15 / 24
Good Names Can Obviate Comments
16 / 24
Clean Formatting
17 / 24
Vertical Formatting
I Newspaper metaphor
I Vertical openness between concepts Vertical density
I Vertical distance
I Vertical ordering
18 / 24
Vertical Openness Between Concepts
Notice how vertical openness helps us locate concepts in the code
more quickly.
1 package fitnesse.wikitext.widgets;
2
3 import java.util.regex.*;
4
5 public class BoldWidget extends ParentWidget {
6
7 public static final String REGEXP = "”’”’.+?";
8
9 private static final Pattern pattern = Pattern.compile("”’(.+?)”’",
10 Pattern.MULTILINE + Pattern.DOTALL
11 );
12
13 public BoldWidget(ParentWidget parent, String text) throws Exception {
14 super(parent);
15 Matcher match = pattern.matcher(text);
16 match.find();
17 addChildWidgets(match.group(1));
18 }
19 }
19 / 24
Vertical Openness Between Concepts
If we leave out the blank lines:
1 package fitnesse.wikitext.widgets;
2 import java.util.regex.*;
3 public class BoldWidget extends ParentWidget {
4 public static final String REGEXP = "”’”’.+?";
5 private static final Pattern pattern = Pattern.compile("”’(.+?)”’",
6 Pattern.MULTILINE + Pattern.DOTALL
7 );
8 public BoldWidget(ParentWidget parent, String text) throws Exception {
9 super(parent);
10 Matcher match = pattern.matcher(text);
11 match.find();
12 addChildWidgets(match.group(1));
13 }
14 }
22 / 24
Horizontal Openness and Density
I Keep lines short. Uncle Bob says 120, but he’s wrong. Keep
your lines at 80 characters or fewer if possible (sometimes it is
impossible, but very rarely).
I Put spaces around = to accentuate the distinction between the
LHS and RHS.
I Don’t put spaces between method names and parens, or parens
and paramter lists - they’re closely related, so should be close.
I Use spaces to accentuate operator precedence, e.g., no space
between unary operators and their operands, space between
binary operators and their operands.
I Don’t try to horizontally align lists of assignments – it draws
attention to the wrong thing and can be misleading, e.g.,
encouraging the reader to read down a column.
I Always indent scopes (classes, methods, blocks).
23 / 24
Team Rules
24 / 24