clean code: chapter 3 function
TRANSCRIPT
![Page 1: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/1.jpg)
Clean CodeChapter 3: Function
Kent Huang
![Page 2: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/2.jpg)
Outline
• Case Study: HtmlUnit.java• Small• Switch• Argument• Error handle• Structured Programming • Conclusion
![Page 3: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/3.jpg)
Case Studying
Sample CodeListing 3-1
Sample CodeListing 3-2
listing3-1.java listing3-2.java
![Page 4: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/4.jpg)
What’s different??
• What is it makes a function like Listing3-2 easy to read and understand?
• How can we make a function communicate it intent?
• What attribute can we give our functions allow a casual reader to intuit the kind of program they live inside?
![Page 5: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/5.jpg)
Small
• Rules of functions:– Should be small– Should be smaller than that
• < 150 character per line• < 20 lines
public static String renderPageWithSetupsAndTeardowns( PageData pageData, boolean isSuite) throws Exception { if (isTestPage(pageData))
includeSetupAndTeardownPages(pageData, isSuite); return pageData.getHtml();
}
![Page 6: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/6.jpg)
Do One Thing
• Functions should do one thing. They should do it well. They should to it only.
• Listing 3-3 do three things1. Determining whether the page is a test page. 2. If so, including setups and teardowns. 3. Rendering the page in HTML.
![Page 7: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/7.jpg)
Is It?
• If a function does only those steps that are one level below the stated name of the function, then the function is doing one thing
• If you can extract another function from it with a name that is not merely a restatement of its implementation
![Page 8: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/8.jpg)
One Level of Abstraction per Function
• In Listing3-1– High level: getHtml(),PathParser.render(pagePath) – Low level: .append(“\n”)
• Broken windows– Once details are mixed with essential concepts,
more and more details tend to accrete within the function
![Page 9: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/9.jpg)
Reading Code from Top to Bottom
• The Stepdown Rule:– We can read the program, descending one level of
abstraction at a time as we read down the list of functions
![Page 10: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/10.jpg)
Switch Statements public 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); }}
1. It’s large, and when new employee type are added, it will grow.2. Does more than one thing.3. Violates the Single Responsibility Principle 4. Violates the Open Closed Principle5. There are an unlimited number of other functions will have same
structure.
![Page 11: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/11.jpg)
public 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); } }}
![Page 12: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/12.jpg)
Use Descriptive Names
• Don’t be afraid to make a name long• A long descriptive name is better than a long
descriptive comment • Use the same phrases, nouns, and verbs in the
function names – Ex: includeSetupAndTeardownPages, includeSetupPages,
includeSuiteSetupPage, includeSetupPage
![Page 13: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/13.jpg)
Function Arguments
• The ideal number of arguments for a function is zero (niladic).
0 > 1 > 2 > 3 >> 4• Arguments are even harder from a testing
point of view.
![Page 14: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/14.jpg)
Common Monadic Forms
• If a function is going to transform its input argument, the transformation should appear the return value
• StringBuffer transform(StringBuffer in)
• Void transform(StringBuffer out)
![Page 15: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/15.jpg)
Flag Arguments
• Flag arguments are ugly
rander(true)
renderForSuite()
renderForSingleTest()
![Page 16: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/16.jpg)
Dyadic Functions
• Function with two arguments is harder to understand than one– writeField(name) v.s writeField(outputStream, name)
• Some times, two arguments are appropriate. – Point p = new Point(0,0);
• Still have problem– assertEquals(expected, actual)
![Page 17: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/17.jpg)
Triads
• Don’t use!!!– assertEquals(message, expected, actual)
• Argument Objects– Circle makeCircle(double x, double y, double radius); – Circle makeCircle(Point center, double radius);
![Page 18: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/18.jpg)
Verbs and Keywords
• Choosing good names for a function can go a long way toward explaining the intent of the function and the order and intent of the arguments. – Write(name)– WriteField(name)– AssertEquals(expected, actual)– AsertExpectedQqualsActual(expected,actual)
![Page 19: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/19.jpg)
Have No Side Effects public class UserValidator { private Cryptographer cryptographer; public 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; }}
![Page 20: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/20.jpg)
Output Arguments
• appendFooter(s); ???– public void appendFooter(StringBuffer report)
• report.appendFooter();
![Page 21: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/21.jpg)
Command Query Separation
• if (set("username", "unclebob"))... – public boolean set(String attribute, String value);
if (attributeExists("username")) { setAttribute("username", "unclebob"); ...
}
![Page 22: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/22.jpg)
Prefer Exceptions to Returning Error Codes
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;}
try { deletePage(page); registry.deleteReference(page.name); configKeys.deleteKey(page.name.makeKey());}catch (Exception e) { logger.log(e.getMessage()); }
![Page 23: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/23.jpg)
• Don’t Repeat Yourself – Duplication may be the root of all evil in software
• Structured Programming – Edsger Dijkstra’s rules• One entry, one exist• Never, ever, ant goto
– When function is small• Multiple return, break, continue are ok• Goto only makes sense in large functions
![Page 24: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/24.jpg)
Conclusion
• Every system is built from a domain-specific language – Functions are the verbs of that language – Classes are the nouns
• Master programmer do:– Functions are short, well named and nicely
organized– Never forget, your real goal is to tell the story of
the system
![Page 25: Clean Code: Chapter 3 Function](https://reader035.vdocuments.us/reader035/viewer/2022062316/58ed82471a28ab1f1f8b4581/html5/thumbnails/25.jpg)
The End