c lean code predrag Čičić @ danulabs, 2014. o verview introduction meaningful names functions...
TRANSCRIPT
CLEAN CODEPredrag Čičić @ Danulabs, 2014
OVERVIEW
Introduction Meaningful Names Functions Comments Formatting C# Standards and Conventions
INTRODUCTION
You are here for two reasons: You are programmers You want to be better programmers
INTRODUCTION
Learning craftsmanship: Knowledge and work
Learning to write clean code requires: Knowledge of principles and patterns Practice yourself Watch yourself fail Watch others practice it and fail See them stumble and retrace their steps
MEANINGFUL NAMES
Use Intention-Revealing Names Take care with your names and change them
when you find better ones The names should answer all the big questions.
It should tell you why it exists, what it does, and how it is used.
If a name requires a comment, then the name does not reveal its intent.
MEANINGFUL NAMESExample 1:
public List<int[]> getThem() {
List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList)
if (x[0] == 4)
list1.add(x);
return list1;
}
Questions:
1. What kinds of things are in theList?
2. What is the significance of the zeroth subscript of an item in theList?
3. What is the significance of the value 4?
4. How would I use the list being returned?
Example 2:
public List<int[]> getFlaggedCells() {
List<int[]> flaggedCells = new ArrayList<int[]>();
for (int[] cell : gameBoard)
if (cell[STATUS_VALUE] == FLAGGED)
flaggedCells.add(cell);
return flaggedCells;
}
MEANINGFUL NAMES
Avoid Disinformation Avoid words whose entrenched meanings vary
from our intended meaning Do not refer to a grouping of accounts as an
accountList unless it’s actually a List. Use (accountGroup or accounts)
Beware of using names which vary in small ways XYZControllerForEfficientHandlingOfStrings XYZControllerForEfficientStorageOfStrings
MEANINGFUL NAMES
Make Meaningful Distinctions Number-series naming (a1, a2, .. aN) is the
opposite of intentional naming Noise words are another meaningless distinction
Product, ProductInfo, ProductData
Use Pronounceable Namesprivate Date genymdhms;
private Date modymdhms;
or
private Date generationTimestamp;
private Date modificationTimestamp;
MEANINGFUL NAMES
Use Searchable Names Avoid:
single letter names numeric constants
Example:for (int j=0; j<34; j++) {
s += (t[j]*4)/5;}orint realDaysPerIdealDay = 4;const int WORK_DAYS_PER_WEEK = 5;for (int j=0; j < NUMBER_OF_TASKS; j++) {
int realTaskDays = taskEstimate[j] * realDaysPerIdealDay;int realTaskWeeks = (realdays / WORK_DAYS_PER_WEEK);sum += realTaskWeeks;
}
MEANINGFUL NAMES
Hungarian notationPhoneNumber phoneString; // name not changed when type changed!
Class Names noun
Method Names verb
Pick One Word per Concept fetch, retreive, get
Use Solution Domain Names People who read your code will be programmers.
So go ahead and use computer science (CS) terms
MEANINGFUL NAMES
Avoid Mental Mapping
“One difference between a smart programmer and a professional programmer is that the professional understands that clarity is king. Professionals use their powers for good and write code that others can understand.”
MEANINGFUL NAMES
Add Meaningful Context Context: firstname, lastname, street, city, state Context: state Solution:
Class Address adrState
Don’t Add Gratuitous Context GSDAccountAddress (“Gas Station Deluxe”)
FUNCTIONS
Size They should be small They should be smaller than that
History 80s – one screen ( 24(-4) lines 80 columns) 2010s – one screen (100 lines 150 characters)
Functions should hardly ever been 20 lines long
FUNCTIONS
SizeBlocks and indenting
If, else, while should be one line long Probably function call with descriptive name
Do one thing “FUNCTIONS SHOULD DO ONE THING. THEY SHOULD
DO IT WELL. THEY SHOULD DO IT ONLY.”
FUNCTIONS
What is one thing?public static String renderPageWithSetupsAndTeardowns(
PageData pageData, boolean isSuite) throws Exception {if (isTestPage(pageData))
includeSetupAndTeardownPages(pageData, isSuite);return pageData.getHtml();
}
1. Determining whether the page is a test page.
2. If so, including setups and teardowns.
3. Rendering the page in HTML.
Three steps of the function are one level of abstraction below the stated name of the function
Describing “To” paragraph:“TO RenderPageWithSetupsAndTeardowns, we check to see whether the page is a test pageand if so, we include the setups and teardowns. In either case we render the page inHTML. “
FUNCTIONS
Reading Code from Top to Bottom The Stepdown Rule
Switch Statementspublic Money calculatePay(Employee e)
throws InvalidEmployeeType {switch (e.type) {
case COMMISSIONED:return calculateCommissionedPay(e);
case HOURLY:return calculateHourlyPay(e);
case SALARIED:return calculateSalariedPay(e);
default:throw new InvalidEmployeeType(e.type);
}}
FUNCTIONS
Switch Statements Problems
Large It will grow when new type is added Does more than one thing Violates Single Responsibility Principle Unlimited number of other functions with same
structure Use AbstractFactory
FUNCTIONS Switch Statements
Employee and Factorypublic abstract class Employee {public abstract boolean isPayday();public abstract Money calculatePay();public abstract void deliverPay(Money pay);
}
public interface EmployeeFactory {public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType;
}-----------------public class EmployeeFactoryImpl implements EmployeeFactory {
public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType {switch (r.type) {
case COMMISSIONED:return new CommissionedEmployee(r) ;
case HOURLY:return new HourlyEmployee(r);
case SALARIED:return new SalariedEmploye(r);
default:throw new InvalidEmployeeType(r.type);
}}
}
FUNCTIONS
Use Descriptive Names “You know you are working on clean code when
each routine turns out to be pretty much what you expected.”
The smaller and more focused a function is, the easier it is to choose a descriptive name
A long descriptive name is better than a short enigmatic name.
A long descriptive name is better than a long descriptive comment
FUNCTIONS
Function Arguments Ideal is 0 (niladic), then 1 (monadic), then 2 (dyadic), then 3 (triadic). More is unacceptable (create new class)
Flag Arguments Avoid (function do 2 things, avoid mouse over) Make two functions with meaningful names
FUNCTIONS
Have No Side Effectspublic boolean checkPassword(String userName, String password) {
User user = UserGateway.findByName(userName);if (user != User.NULL) {
String codedPhrase = user.getPhraseEncodedByPassword();String phrase = cryptographer.decrypt(codedPhrase, password);if ("Valid Password".equals(phrase)) {
Session.initialize();return true;
}}return false;
} checkPasswordAndInitializeSession ?
Output arguments public void appendFooter(StringBuffer report) report.appendFooter();
FUNCTIONS
Command Query Separation Functions should:
do something or answer something don’t both
Example: public boolean set(String attribute, String value); if (set("username", "unclebob"))
Prefer Exceptions to Returning Error Codes Error Handling Is One Thing (one function)
Don’t Repeat Yourself
FUNCTIONS
Structured Programming Dijkstra said, ”Every function, and every block,
should have one entry and one exit”. This means that there should only be one return
statement in a function, no break or continue statements in a loop, and never, ever, any goto statements.
If you keep your functions small, then there is no problem to break this rule
FUNCTIONS
Conclusion Writing software is like any other kind of writing.
You wordsmith it and restructure it and refine it until it reads the way you want it to read.
So then refine that code, splitting out functions, changing names, eliminating duplication. Shrink the methods and reorder them. Sometimes break out whole classes, all the while keeping the tests passing.
Never forget that your real goal is to tell the story of the system, and that the functions you write need to fit cleanly together into a clear and precise language to help you with that telling.
COMMENTS
“Don’t comment bad code—rewrite it.”
Nothing can be quite so helpful as a well-placed comment.
Nothing can clutter up a module more than frivolous dogmatic comments.
Nothing can be quite so damaging as an old crufty comment that propagates lies and misinformation
COMMENTS
Comments compensates our failure to express ourself in code.
When you find yourself in a position where you need to write a comment, think it through and see whether there isn’t some way to express yourself in code
Truth can only be found in one place: the code
// Check to see if the employee is eligible for full benefitsif ((employee.flags & HOURLY_FLAG) &&(employee.age > 65))
Or
if (employee.isEligibleForFullBenefits())
GOOD COMMENTS
Legal Comments// Copyright (C) 2003,2004,2005 by Object Mentor, Inc. All rights reserved.
Informative Comments// format matched kk:mm:ss EEE, MMM dd, yyyyPattern timeMatcher = Pattern.compile("\\d*:\\d*:\\d* \\w*, \\w* \\d*, \\d*");
Explanation of Intent Comparison function
ClarificationassertTrue(a.compareTo(a) == 0); // a == aassertTrue(a.compareTo(b) != 0); // a != bassertTrue(ab.compareTo(ab) == 0); // ab == ab
GOOD COMMENTS
Warning of Consequences// Don't run unless you// have some time to kill.public void _testWithReallyBigFile()
TODO Comments
AmplificationString listItemContent = match.group(3).trim();// the trim is real important. It removes the starting// spaces that could cause the item to be recognized// as another list.
BAD COMMENTS
Mumblingcatch(IOException e){
// No properties files means all defaults are loaded}
Redundant Comments// Utility method that returns when this.closed is true. Throws an exception// if the timeout is reached.public synchronized void waitForClose(final long timeoutMillis) throws Exception{
if(!closed){
wait(timeoutMillis);if(!closed)
throw new Exception("MockResponseSender could not be closed");
}}
BAD COMMENTS
Misleading Comments
Mandated Comments Rule that says that every function must have a
javadoc, or every variable must have a comment
Journal Comments Log of a repository?
Noise Comments/*** Default constructor.*/protected AnnualDateRule() {
BAD COMMENTS
Position Markers // Actions //////////////////////////////////
Closing Brace Comments Functions are to long
Commented-Out Code Just don’t do this!!!
Too Much Information
FORMATING
First rule: Let’s be clear
“Code formatting is about communication, and communication is the professional developer’s first order of business.”
FORMATING
Vertical Formatting The Newspaper Metaphor
Write code like newspaper article (General description on the top and detailed on the bottom)
Vertical Openness Between Concepts Each blank line is a visual cue that identifies a new and
separate concept. As you scan down the listing, your eye is drawn to the first line that follows a blank line.
Vertical Density vertical density implies close association don’t break it with unimportant blank lines and
comments
FORMATING
Vertical formatting Vertical Distance
Concepts that are closely related should be kept vertically close to each other
Variable Declarations close to their usage top of the function before loops or blocks
Instance variables Well known place (top or bottom)
Dependent Functions Conceptual Affinity
FORMATING
Horizontal formatting you should never have to scroll to the right average limit is ~120
Horizontal Openness and Density Horizontal Alignment Indentation
Team Rules
OTHER CONCEPTS
Object and Data Structures Error Handling Concurrency Unit tests ….
C# STANDARDS