React Native vs Ionic - The Best Mobile App Framework
Clean code, Feb 2012
1. CLEAN CODE
The lecture is based on
“Clean Code”, A Handbook of Agile Software Craftsmanship by
Robert C. Martin
Software Craftsmanship in Israel group meetings.
Coby Sternlicht
Feb 2012
4. Why clean code
• Does what my customer needs
• Is error free
• Performs well
• Is easy to change
• Is as simple as possible
• Maintainable
• The psychological element
4
9. A “long” method - HtmlUtil.java /FitNesse
• Do you understand the function after three
minutes of study?
– Probably not
9
10. A “long” method - refactored
• What did I do?
– method extractions
– some renaming
– A little restructuring
• Can you understand what the code does?
10
12. 1. Smaller than a screenful
• Small, Small, Small
• Minimum lines of code
• Maximal nesting level of 2
12
13. 2. Do one thing - do it well, do it only.
• The original code is:
– Creating buffers
– Fetching pages
– Searching for inherited pages
– Rendering paths
– Appending arcane strings
– Generating HTML…
• The re-factored code is:
– including setups and teardowns into test pages
13
14. 3. Choose Good Names
• Use intention-revealing, pronounceable, searchable
names
– bad: int d; // elapsed time in days
– Good: int elapsedTimeInDays;
• Don’t use Hungarian Notation
– // name not changed when type changed!
– PhoneNumber stPhone;
• Don’t be afraid to make a name long
• Don’t be afraid to spend time choosing a name
• Remember, if you can’t choose a descriptive name
– Your function is probably too big
– And does more than ONE THING
14
15. 4. Minimize the use of arguments
• Which is easier to understand?
– includeSetupPage()
– includeSetupPageInto(newPageContent)
• Arguments are hard
– They take a lot of conceptual power.
– They are at a different level of abstraction than the
function name
– Output arguments are difficult to understand
– They are even harder from a testing point of view
15
16. 5. Avoid flag arguments
• Passing a boolean into a function is bad practice
– It complicates the signature of the method
– This function does more than one thing
• Example:
– render(true) is just plain confusing to a poor reader
• Your IDE tells you that it is render(boolean isSuite)
• Helps a little, but not that much
– We should have split the function into two:
• renderForSuite() and renderForSingleTest()
16
17. 6. No more than 3 arguments
• Zero arguments is ideal (niladic)
• Next comes one (monadic)
• Followed closely by two (dyadic)
• Three arguments (triadic) should be avoided where
possible
• More than three (polyadic) requires very special
justification
17
18. Dyadic functions
• A function with two arguments is harder to understand
• Example: Frequency.cs (GetNextDate)
• As a general rule, Dyadic aren’t that bad and sometimes
necessary:
– Point centerPosition = new Point(x, y);
18
19. Three arguments (Triads)
• Significantly harder to understand
– Argument ordering
– Pausing when reading
– Ignoring unimportant details
• Example - assertEquals:
– assertEquals(message, expected, actual)
– Is first argument message or expected?
– You do a double-take and then learn to ignore the message
19
20. 7. Side-effects are lies
• A function also does other hidden things
– to the variables of it’s own class
– to the parameters passed into the function
– to system globals
• Creates temporal couplings and order dependencies
• If you must have a temporal coupling, you should make it
clear in the name of the function
• Example:
– checkPasswordAndInitializeSession
– Obviously this does more than one thing
20
21. 7. Side-effects are lies
• Command and Query separation
• Example:
public boolean set(String attribute, String value);
• This leads to:
if (set("username", “unclebob"))...
• What does that mean?
– Is it asking whether the “username” attribute was
• previously set to “unclebob”?
• successfully set to “unclebob”?
– Is “set” a verb or an adjective
21
22. 7. Side-effects are lies – continued
• Renaming to checkIfAttributeExistsAndSet
– helps a bit
• The real solution is to separate the command from the query
if (attributeExists("username"))
{
setAttribute("username", "unclebob");
...
}
22
23. 8. Use exceptions and not error codes
• Error codes are a violation of command query
separation
• Create lots of if statements
– if (deletePage(page) == E_OK)
• Deeply nested structures
• The caller must deal with the error
immediately
23
24. 8. Use exceptions – Bad example
if (deletePage(page) == E_OK)
{
if (registry.deleteReference(page.name) == E_OK) {
if (configKeys.deleteKey(page.name.makeKey()) == E_OK){
logger.log("page deleted");
} else {
logger.log("configKey not deleted");
}
} else {
logger.log("deleteReference from registry failed");
}
} else {
logger.log("delete failed");
return E_ERROR;
}
24
25. 8. Use exceptions – Good example
try {
deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey());
}
catch (Exception e) {
logger.log(e.getMessage());
}
• Happy-path is easy to read
• Error processing code is separated
25
26. 9. Don’t comment bad code—rewrite it
• Failure to express ourselves in code
• Not maintained
• Don’t comment messy code, clean it!
• Don’t comment-out code – DELETE IT
• Example:
// Check to see if the employee is eligible for full benefits
if ((employee.flags & HOURLY_FLAG) &&
(employee.age > 65))
• Instead - descriptive Method Name
if (employee.isEligibleForFullBenefits())
26
28. 1. DRY – Don’t repeat yourself
• Clone and modify programming
– Creates Rogue Tile: bugs show up again and again
• When writing “DRY”:
– Modification of any single element of a system does
not change other logically-unrelated elements
– All elements that are logically related, change
predictably and uniformly
28
29. 2. YAGNI - You aint gonna need it
• Maybe in the future…
• Disadvantages:
– The time spent
– Must be debugged, documented, and supported
– May prevent implementing a necessary feature in the future due
to constraints
– Difficult to fully define when not needed
– Code bloat
– May not be known to programmers when they need it
– Snowball effect – “Featuritis Crawleritis”
• Must be balanced: upcoming vital features, team
expectations, part-time expert assistance, and logical
completeness
29
30. 3. KISS - keep it short and simple
• Simplicity should be a key goal in design
• Unnecessary complexity should be avoided
30