33

Clean Code - A&BP CC

Embed Size (px)

Citation preview

Page 1: Clean Code - A&BP CC
Page 2: Clean Code - A&BP CC
Page 3: Clean Code - A&BP CC

Always leave the campgroundcleaner than you found it.

Page 4: Clean Code - A&BP CC
Page 5: Clean Code - A&BP CC

Service?

Processor?

Handler?Manager?

ClassesDriver?

 

Page 6: Clean Code - A&BP CC

1.    public static String testableHtml(PageData pageData, boolean includeSuiteSetup) throws Exception {2.           WikiPage wikiPage = pageData.getWikiPage();3.           StringBuffer buffer = new StringBuffer();4.           if (pageData.hasAttribute("Test")) {5.                   if (includeSuiteSetup) {6.                           WikiPage suiteSetup = PageCrawlerImpl.getInheritedPage(SuiteResponder.SUITE_SETUP_NAME, wikiPage);7.                           if (suiteSetup != null) {8.                               WikiPagePath pagePath = suiteSetup.getPageCrawler().getFullPath(suiteSetup);9.                               String pagePathName = PathParser.render(pagePath);10.                                  buffer.append("!include -setup .").append(pagePathName).append("\n");11.                        }12.                   }13.                   WikiPage setup = PageCrawlerImpl.getInheritedPage("SetUp", wikiPage);14.                   if (setup != null) {15.                           WikiPagePath setupPath = wikiPage.getPageCrawler().getFullPath(setup);16.                           String setupPathName = PathParser.render(setupPath);17.                           buffer.append("!include -setup .").append(setupPathName).append("\n");18.                   }19.           }20.           buffer.append(pageData.getContent());21.           if (pageData.hasAttribute("Test")) {22.                   WikiPage teardown = PageCrawlerImpl.getInheritedPage("TearDown", wikiPage);23.                   if (teardown != null) {24.                           WikiPagePath tearDownPath = wikiPage.getPageCrawler().getFullPath(teardown);25.                           String tearDownPathName = PathParser.render(tearDownPath);26.                           buffer.append("\n").append("!include -teardown .").append(tearDownPathName).append("\n");27.                   }28.                   if (includeSuiteSetup) {29.                           WikiPage suiteTeardown = PageCrawlerImpl.getInheritedPage(SuiteResponder.SUITE_TEARDOWN_NAME, wikiPage);30.                           if (suiteTeardown != null) {31.                               WikiPagePath pagePath = suiteTeardown.getPageCrawler().getFullPath(suiteTeardown);32.                               String pagePathName = PathParser.render(pagePath);33.                    buffer.append("!include -teardown .").append(pagePathName).append("\n");34.                }35.            }36.        }37.        pageData.setContent(buffer.toString());38.        return pageData.getHtml();39.    }

Page 7: Clean Code - A&BP CC

1.    public static String renderPageWithSetupsAndTeardowns(PageData pageData, boolean isSuite) throws Exception {2.         boolean isTestPage = pageData.hasAttribute("Test");3.         if (isTestPage) {4.          WikiPage testPage = pageData.getWikiPage();5.          StringBuffer newPageContent = new StringBuffer();6.          includeSetupPages(testPage, newPageContent, isSuite);7.          newPageContent.append(pageData.getContent());8.          includeTeardownPages(testPage, newPageContent, isSuite);9.          pageData.setContent(newPageContent.toString());10.        }11.        return pageData.getHtml();12.    }

Page 8: Clean Code - A&BP CC

1.    public static String renderPageWithSetupsAndTeardowns(PageData pageData, boolean isSuite) throws Exception {2.         if (isTestPage(pageData))3.                 includeSetupAndTeardownPages(pageData, isSuite);4.         return pageData.getHtml();5.    }

Page 9: Clean Code - A&BP CC

Small: Never more than 20 lines

Do one thing and one thing only

Only 1 or 2 levels deep

Page 10: Clean Code - A&BP CC

Descriptive names

Avoid 3 parameters

Have no side effects

Page 11: Clean Code - A&BP CC

private String readQwPinCode(String fyon, String item) throws TranslationException { try { FetchQwItemOnCar fetchQwItemOnCar = new FetchQwItemOnCar(); QwOnCarBuf qwOnCarBuf = fetchQwItemOnCar.fetchQwItemOnCar(fyon, item); if(fetchQwItemOnCar.getStatusCode() == FetchQwItemOnCarStatusCode.ATACQ$_SUCCESS && qwOnCarBuf != null) return qwOnCarBuf.getSerieNumber().trim(); else if(fetchQwItemOnCar.getStatusCode() == FetchQwItemOnCarStatusCode.ATACQ$_RNF) return "??????????????????????????????"; else throw new TranslationException("TranslateBuildingInfoItem",

String.valueOf(BuildingInfoConfigConstants.TRANSLATION_EXCEPTION)); } catch (VcomException e) { logger.error(e.getMessage(), e); throw new TranslationException("TranslateBuildingInfoItem",

String.valueOf(BuildingInfoConfigConstants.TRANSLATION_EXCEPTION_VCOM)); } catch (BufferException e) { logger.error(e.getMessage(), e); throw new TranslationException("TranslateBuildingInfoItem",

String.valueOf(BuildingInfoConfigConstants.TRANSLATION_EXCEPTION_VCOM)); }}

Page 12: Clean Code - A&BP CC

Avoid output arguments

Page 13: Clean Code - A&BP CC

Avoid output arguments

appendFooter(s);

public void appendFooter(StringBuffer report)

report.appendFooter();

“Principle of least astonishment”

Page 14: Clean Code - A&BP CC

Avoid output arguments

Throw unchecked exceptions

Page 15: Clean Code - A&BP CC

private String readQwPinCode(String fyon, String item) throws TranslationException { try { FetchQwItemOnCar fetchQwItemOnCar = new FetchQwItemOnCar(); QwOnCarBuf qwOnCarBuf = fetchQwItemOnCar.fetchQwItemOnCar(fyon, item); if(fetchQwItemOnCar.getStatusCode() == FetchQwItemOnCarStatusCode.ATACQ$_SUCCESS && qwOnCarBuf != null) return qwOnCarBuf.getSerieNumber().trim(); else if(fetchQwItemOnCar.getStatusCode() == FetchQwItemOnCarStatusCode.ATACQ$_RNF) return "??????????????????????????????"; else throw new TranslationException("TranslateBuildingInfoItem",

String.valueOf(BuildingInfoConfigConstants.TRANSLATION_EXCEPTION)); } catch (VcomException e) { logger.error(e.getMessage(), e); throw new TranslationException("TranslateBuildingInfoItem",

String.valueOf(BuildingInfoConfigConstants.TRANSLATION_EXCEPTION_VCOM)); } catch (BufferException e) { logger.error(e.getMessage(), e); throw new TranslationException("TranslateBuildingInfoItem",

String.valueOf(BuildingInfoConfigConstants.TRANSLATION_EXCEPTION_VCOM)); }}

Page 16: Clean Code - A&BP CC

Comments

Page 17: Clean Code - A&BP CC

Comments

Don’t write comments

Page 18: Clean Code - A&BP CC

Comments

Unless…– Javadocs in public APIs– “why” comments

Page 19: Clean Code - A&BP CC
Page 20: Clean Code - A&BP CC

public interface Vehicle {double getFuelTankCapacityInGallons();double getGallonsOfGasoline();

}

public interface Vehicle {double getPercentFuelRemaining();

}

Page 21: Clean Code - A&BP CC
Page 22: Clean Code - A&BP CC

final String outputDir =ctxt.getOptions().getScratchDir().getAbsolutePath();

Alternatives:• ctxt.getAbsolutePathOfScratchDirectoryOption();• ctx.getScratchDirectoryOption().getAbsolutePath();

Careful! Don’t cause an explosion of methods

Page 23: Clean Code - A&BP CC

How used?

String outFile = outputDir + "/" +

className.replace('.', '/') + ".class";

FileOutputStream fout = new FileOutputStream(outFile);

BufferedOutputStream bos = new BufferedOutputStream(fout);

Page 24: Clean Code - A&BP CC

How about this then?

BufferedOutputStream bos =

ctxt.createScratchFileStream(classFileName);

Page 25: Clean Code - A&BP CC

Error Handling

• Return codes are bad

• Unchecked exception are not!

• TDD: write your exception handling first• Nullpointers: Do not return or pass null.

Page 26: Clean Code - A&BP CC

Boundaries

Page 27: Clean Code - A&BP CC

Unit Tests

! Write clean test code !

1. Write failing unit test before production code

2. Only write enough test code to fail

3. Only write enough production code to pass the test

4. Repeat

Page 28: Clean Code - A&BP CC

AAA / GivenWhenThen• Arrange• Act• Assert

• Given• When• Then

or vs

Page 29: Clean Code - A&BP CC

F.I.R.S.T.

• Fast

• Independent

• Repeatable

• Self validation

• Timely

Page 30: Clean Code - A&BP CC

Classes should be small

• Avoid too many public methods (God class)

• Hint: class name should concisely describe the class

Page 31: Clean Code - A&BP CC

Single Responsibility Principle

Gather together the things that change for the same reasons

Separate those things that change for different reasonsThe reason we don't put SQL in JSPsThe reason we don't generate HTML in modules which compute resultsThe reason business rules shouldn't know about the database schema

Page 32: Clean Code - A&BP CC

Cohesion

Classes should have a small number of instance variables

Aim for high cohesion A class in which each variable is used by each method is maximally cohesive

When subset of methods depend on subset of instance variables → good sign for an extra class

Results in many small classes

Page 33: Clean Code - A&BP CC