Clean Code: Chapter 3 Function

kentwelcome1 5,550 views 25 slides Sep 06, 2015
Slide 1
Slide 1 of 25
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25

About This Presentation

Clean Code: Chapter 3 Function


Slide Content

Clean Code Chapter 3: Function Kent Huang

Outline Case Study: HtmlUnit.java Small Switch Argument Error handle Structured Programming Conclusion

Case Studying Sample Code Listing 3-1 Sample Code Listing 3-2

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?

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 (); }

Do One Thing Functions should do one thing. They should do it well. They should to it only. Listing 3-3 do three things Determining whether the page is a test page. If so, including setups and teardowns. Rendering the page in HTML.

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

One Level of Abstraction per Function In Listing3-1 High level: getHtml (), PathParser.render ( pagePath ) Low level: .append(“\n”) Broken windows O nce details are mixed with essential concepts, more and more details tend to accrete within the function

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

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 ); } } It’s large, and when new employee type are added, it will grow. Does more than one thing. Violates the Single Responsibility Principle V iolates the Open Closed Principle There are an unlimited number of other functions will have same structure .

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 ); } } }

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

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.

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 ) 

Flag Arguments Flag arguments are ugly r ander (true)  renderForSuite ()  r enderForSingleTest ( ) 

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)

Triads Don’t use!!! assertEquals (message, expected, actual)  Argument Objects Circle makeCircle (double x, double y, double radius); Circle makeCircle (Point center, double radius);

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) A sertExpectedQqualsActual ( expected,actual )

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; } }

Output Arguments appendFooter (s); ??? public void appendFooter ( StringBuffer report) report.appendFooter ();

Command Query Separation if (set("username", " unclebob "))... public boolean set(String attribute, String value); if ( attributeExists ("username")) { setAttribute ("username", " unclebob "); ... }

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 ()); }

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

Conclusion Every system is built from a domain-specific language Functions are the verbs of that language C lasses 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

The End