SlideShare uma empresa Scribd logo
1 de 25
Clean Code
Be a little more careful with the code you write!


Ana Cortés Corbalán
05.02.2013
What? Why? How?




05.02.2013          2          www.consol.com
The only valid measurement of code quality:
                             WTFs/minute




05.02.2013                       3            www.consol.com
What is Clean Code?

§    Simple                    §  Efficient
§    No duplications           §  Elegant
§    Direct                    §  Focused
§    With tests                §  Minimal dependencies
§    It was written by someone who cares
§    ...

§  Any fool can write code that a computer can
      understand. Good programmers write code that
      humans can understand. - Martin Fowler




05.02.2013                      4              www.consol.com
Why is clean code so important?

§  Easier to read
§  Easier to understand
§  Easier to change
     §  Add new features
     §  Find and fix bugs
§  Cheaper to maintain
§  Code quality is part of software quality




05.02.2013                      5              www.consol.com
Use Intention-Revealing Names



§    int    d;!
§    int    days;!
§    int    days; //days since creation!
§    int    daysSinceCreation;!




05.02.2013                 6          www.consol.com
Use Intention-Revealing Names

§  What is the purpose?

     public List<int[]> getValues() {!
        List<int[]> list1 = new ArrayList<int[]>();!
        for (int[] x : theList)!
           if (x[0] == 4) list1.add(x);!
        return list1;!
     }!




05.02.2013                        7               www.consol.com
Use Intention-Revealing Names

§  Better?
     !
     public List<Cell> getFlaggedCells() {!
        List<Cell> flaggedCells = new ArrayList<Cell>();!
        for (Cell cell : gameBoard) !
           if (cell.isFlagged()) flaggedCells.add(cell);!
        return flaggedCells;!
     }!
       !




05.02.2013                        8               www.consol.com
Don´t talk in code – Use Pronounceable Names

     class DtaRcrd102 {

         private Date genymdhms;

         private Date modymdhms;

         private final String pszqint = "102"; /* ... */ !
     }!

§  Better?
     class Customer {

         private Date generationTimestamp; !
         private Date modificationTimestamp; !
         private final String recordId = "102"; /* ... */ !
     }!




05.02.2013                        9               www.consol.com
More recommendations...
§  Class names
     Customer, Account, AddressParser, ...

§  Method names
     postPayment, deletePage, ....

§  When constructors are overloaded...
     new Complex(23.0);!
     Complex.fromRealNumber(23.0); !

§  Pick one word per concept
     get, fetch, retrieve...

§  Don´t be cute. Jokes out of the code.
     public void saveTheUniverse() {...}



05.02.2013                                   10   www.consol.com
Bad Comments

§  Redundant, noise, irrelevant, obsolet, „funny“ comments
     /**!
       * Returns the day of the month. *!
       * @return the day of the month. */!
     public int getDayOfMonth() {!
         return dayOfMonth;!
     }!
     !
     /** Always return true. **/!
     public boolean isAvailable() {!
         !return false;!
     }!
     !
     //Magic. Do not touch !

   /* Added by Ana Cortés (4-4-2008) */!


05.02.2013                        11         www.consol.com
Bad Comments

     /** !
      * Dear maintainer:!
      * !
      * Once you are done trying to 'optimize' this routine,!
      * and have realized what a terrible mistake that was,!
      * please increment the following counter as a warning!
      * to the next guy:!
      * !
      * total_hours_wasted_here = 42!
     **/!


§  Commented-Out Code
     InputStreamResponse response = new InputStreamResponse();!
     response.setBody(formatter.getResultStream(), ft.getByteCount()); !
     //  InputStream resultsStream = formatter.getResultStream(); !
     //  StreamReader reader = new StreamReader(resultsStream); !
     //  response.setContent(reader.read(formatter.getByteCount())); !

05.02.2013                        12               www.consol.com
Good Comments

§  Legal comments
     // Copyright (C) 2003 by Object Mentor, Inc. All rights reserved.

     // Released under the terms of the GNU General Public License version 2 or later. !



§  Informative, clarification comments
     // format matched kk:mm:ss EEE, MMM dd, yyyy !
     Pattern timeMatcher = Pattern.compile("d*:d*:d* w*, w* d*, d*"); !


§  Amplification comments
     String 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.


§  TODO comments

§  Javadocs in Public APIs
05.02.2013                               13                     www.consol.com
Functions - Small!!
public static String testableHtml( PageData pageData,boolean
includeSuiteSetup) throws Exception {

   WikiPage wikiPage = pageData.getWikiPage();!
   StringBuffer buffer = new StringBuffer();!
   if (pageData.hasAttribute("Test")) {!
          if (includeSuiteSetup) {!
                WikiPage suiteSetup =
PageCrawlerImpl.getInheritedPage( SuiteResponder. SETUP_NAME, wikiPage);

            !
                if (suiteSetup != null) {!
                    WikiPagePath pagePath =
suiteSetup.getPageCrawler().getFullPath(suiteSetup);!
                    String pagePathName = PathParser.render(pagePath); !
                    buffer.append("!include -
setup .").append(pagePathName).append("n");!
                } !
            }!
            WikiPage setup = PageCrawlerImpl.getInheritedPage("SetUp",
wikiPage);!
... 40 lines more!


05.02.2013                          14                 www.consol.com
Functions - Small!!
public static String renderPageWithSetupsAndTeardowns (PageData pageData,
boolean isSuite) throws Exception {

   boolean isTestPage = pageData.hasAttribute("Test"); !
   if (isTestPage) { !
       WikiPage testPage = pageData.getWikiPage(); !
       StringBuffer newPageContent = new StringBuffer();   !
       includeSetupPages(testPage, newPageContent, isSuite); !
       newPageContent.append(pageData.getContent()); !
       includeTeardownPages(testPage, newPageContent, isSuite); !
       pageData.setContent(newPageContent.toString()); !
   } !
   return pageData.getHtml(); !
}!
!
!
§  Better?
!
public static String renderPageWithSetupsAndTeardowns (PageData pageData,
boolean isSuite) throws Exception { !
     if (isTestPage(pageData)) !
         includeSetupAndTeardownPages(pageData, isSuite); !
     return pageData.getHtml(); !
} !
  !
05.02.2013                                                 www.consol.com
!                                       15
Command query separation

§  What does it mean?
    public boolean set(String attribute, String value);!
!
    if (set("username", "unclebob")) { ... } !


!
§  Better?
    if (attributeExists("username")) { !

          setAttribute("username", "unclebob"); !
    } !




05.02.2013                          16              www.consol.com
Don´t return null

§  Throw exceptions or return special case object
!
     List<Employee> employees = getEmployees(); !
     if (employees != null) { !
       for(Employee e : employees) { !
         totalPay += e.getPay(); !
       } !
     } !
!
§  How to remove != null in the code?
     public List<Employee> getEmployees() { !
       if( .. there are no employees .. ) !
         return Collections.emptyList(); !
     } !
!
!

05.02.2013                       17                  www.consol.com
Don´t return null

public void registerItem(Item item) { !
  if (item != null) { !
    ItemRegistry registry = persistentStore.getItemRegistry();!
    if (registry != null) { !
      Item existing = registry.getItem(item.getID());

      if (existing.getBillingPeriod().hasRetailOwner()) { !
        existing.register(item); !
      } !
    }   !
  } !
} !
!




05.02.2013                      18               www.consol.com
Have no side effects

§  Where is the side effect?
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; !
} !




05.02.2013                      19                www.consol.com
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; !
} !
!
!
public enum error {!
   OK, INVALID, NO_SUCH, LOCKED, OUT_OF_RESOURCES;!
}!
05.02.2013                      20               www.consol.com
Prefer exceptions to returning error codes

§  Better?
public void delete(Page page) { !
      try { !
            !deletePageAndAllReferences(page); !
      } !
      catch (Exception e) {!
            logError(e); !
      } !
} !
!
private void deletePageAndAllReferences(Page page) throws Exception {
                                                                    !
      deletePage(page);

      registry.deleteReference(page.getName());  !
      configKeys.deleteKey(page.getKey()); !
}!
!
private void logError(Exception e) {!
      logger.log(e.getMessage());!
}!05.02.2013                           21         www.consol.com
!
Keeping tests clean

public void testGetPageHierarchyAsXml() throws Exception { !
    crawler.addPage(root, PathParser.parse("PageOne")); !
    crawler.addPage(root, PathParser.parse("PageOne.ChildOne"));
    crawler.addPage(root, PathParser.parse("PageTwo")); !
    request.setResource("root"); !
    request.addInput("type", "pages");

    Responder responder = new SerializedPageResponder(); !
    SimpleResponse response = !
    (SimpleResponse) responder.makeResponse( new
    FitNesseContext(root), request); !
    String xml = response.getContent(); !
    assertEquals("text/xml", response.getContentType());
    assertSubString("<name>PageOne</name>", xml);
    assertSubString("<name>PageTwo</name>", xml);
    assertSubString("<name>ChildOne</name>", xml); !
} !
!


05.02.2013                      22               www.consol.com
Keeping tests clean

§  Better?
!
     public void testGetPageHierarchyAsXml() throws Exception { !
         makePages("PageOne", "PageOne.ChildOne", "PageTwo");!
           !
         submitRequest("root", "type:pages"); !
         !
         assertResponseIsXML(); !
         assertResponseContains( !
         "<name>PageOne</name>", "<name>PageTwo</name>",
         "<name>ChildOne</name>" ); !
     } !
!




05.02.2013                       23               www.consol.com
Summary

§  Read „Clean Code“ book.
§  Be a little more careful with the code you write
      §  Write with the „audience“ in mind
§  Follow the „Boy Scout Rule“
      §  Leave the campground cleaner than you found it
      §  Use tools that help you cleaning up
§  Write Clean Tests




05.02.2013                            24               www.consol.com
Thank you!
             Danke!
             Gracias!
             !

05.02.2013         25     www.consol.com

Mais conteúdo relacionado

Mais procurados

Introduction to mongodb for bioinformatics
Introduction to mongodb for bioinformaticsIntroduction to mongodb for bioinformatics
Introduction to mongodb for bioinformaticsPierre Lindenbaum
 
Building Persona: federated and privacy-sensitive identity for the Web (Open ...
Building Persona: federated and privacy-sensitive identity for the Web (Open ...Building Persona: federated and privacy-sensitive identity for the Web (Open ...
Building Persona: federated and privacy-sensitive identity for the Web (Open ...Francois Marier
 
NDC London 2013 - Mongo db for c# developers
NDC London 2013 - Mongo db for c# developersNDC London 2013 - Mongo db for c# developers
NDC London 2013 - Mongo db for c# developersSimon Elliston Ball
 
Building Persona: federated and privacy-sensitive identity for the Web (LCA 2...
Building Persona: federated and privacy-sensitive identity for the Web (LCA 2...Building Persona: federated and privacy-sensitive identity for the Web (LCA 2...
Building Persona: federated and privacy-sensitive identity for the Web (LCA 2...Francois Marier
 
OOCSS for Javascript pirates at jQueryPgh meetup
OOCSS for Javascript pirates at jQueryPgh meetupOOCSS for Javascript pirates at jQueryPgh meetup
OOCSS for Javascript pirates at jQueryPgh meetupBrian Cavalier
 
Organizing Code with JavascriptMVC
Organizing Code with JavascriptMVCOrganizing Code with JavascriptMVC
Organizing Code with JavascriptMVCThomas Reynolds
 
Presentasi Kelompok 25 PW A+B
Presentasi Kelompok 25 PW A+BPresentasi Kelompok 25 PW A+B
Presentasi Kelompok 25 PW A+BHapsoro Permana
 
Tugas pw [kelompok 25]
Tugas pw [kelompok 25]Tugas pw [kelompok 25]
Tugas pw [kelompok 25]guest0ad6a0
 
Maintainable JavaScript 2012
Maintainable JavaScript 2012Maintainable JavaScript 2012
Maintainable JavaScript 2012Nicholas Zakas
 
32373 uploading-php-shell-through-sql-injection
32373 uploading-php-shell-through-sql-injection32373 uploading-php-shell-through-sql-injection
32373 uploading-php-shell-through-sql-injectionAttaporn Ninsuwan
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxMichelangelo van Dam
 
Hacking Your Way To Better Security
Hacking Your Way To Better SecurityHacking Your Way To Better Security
Hacking Your Way To Better SecurityColin O'Dell
 
Hacking Your Way to Better Security - PHP South Africa 2016
Hacking Your Way to Better Security - PHP South Africa 2016Hacking Your Way to Better Security - PHP South Africa 2016
Hacking Your Way to Better Security - PHP South Africa 2016Colin O'Dell
 
jQuery from the very beginning
jQuery from the very beginningjQuery from the very beginning
jQuery from the very beginningAnis Ahmad
 
Javascript - The Good, the Bad and the Ugly
Javascript - The Good, the Bad and the UglyJavascript - The Good, the Bad and the Ugly
Javascript - The Good, the Bad and the UglyThorsten Suckow-Homberg
 

Mais procurados (20)

Advanced Django
Advanced DjangoAdvanced Django
Advanced Django
 
Introduction to mongodb for bioinformatics
Introduction to mongodb for bioinformaticsIntroduction to mongodb for bioinformatics
Introduction to mongodb for bioinformatics
 
Building Persona: federated and privacy-sensitive identity for the Web (Open ...
Building Persona: federated and privacy-sensitive identity for the Web (Open ...Building Persona: federated and privacy-sensitive identity for the Web (Open ...
Building Persona: federated and privacy-sensitive identity for the Web (Open ...
 
NDC London 2013 - Mongo db for c# developers
NDC London 2013 - Mongo db for c# developersNDC London 2013 - Mongo db for c# developers
NDC London 2013 - Mongo db for c# developers
 
Building Persona: federated and privacy-sensitive identity for the Web (LCA 2...
Building Persona: federated and privacy-sensitive identity for the Web (LCA 2...Building Persona: federated and privacy-sensitive identity for the Web (LCA 2...
Building Persona: federated and privacy-sensitive identity for the Web (LCA 2...
 
OOCSS for Javascript pirates at jQueryPgh meetup
OOCSS for Javascript pirates at jQueryPgh meetupOOCSS for Javascript pirates at jQueryPgh meetup
OOCSS for Javascript pirates at jQueryPgh meetup
 
Organizing Code with JavascriptMVC
Organizing Code with JavascriptMVCOrganizing Code with JavascriptMVC
Organizing Code with JavascriptMVC
 
Presentasi Kelompok 25 PW A+B
Presentasi Kelompok 25 PW A+BPresentasi Kelompok 25 PW A+B
Presentasi Kelompok 25 PW A+B
 
Tugas pw [kelompok 25]
Tugas pw [kelompok 25]Tugas pw [kelompok 25]
Tugas pw [kelompok 25]
 
Maintainable JavaScript 2012
Maintainable JavaScript 2012Maintainable JavaScript 2012
Maintainable JavaScript 2012
 
32373 uploading-php-shell-through-sql-injection
32373 uploading-php-shell-through-sql-injection32373 uploading-php-shell-through-sql-injection
32373 uploading-php-shell-through-sql-injection
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Dollar symbol
Dollar symbolDollar symbol
Dollar symbol
 
Hacking Your Way To Better Security
Hacking Your Way To Better SecurityHacking Your Way To Better Security
Hacking Your Way To Better Security
 
Hacking Your Way to Better Security - PHP South Africa 2016
Hacking Your Way to Better Security - PHP South Africa 2016Hacking Your Way to Better Security - PHP South Africa 2016
Hacking Your Way to Better Security - PHP South Africa 2016
 
jQuery from the very beginning
jQuery from the very beginningjQuery from the very beginning
jQuery from the very beginning
 
Web2py
Web2pyWeb2py
Web2py
 
php part 2
php part 2php part 2
php part 2
 
misspattern
misspatternmisspattern
misspattern
 
Javascript - The Good, the Bad and the Ugly
Javascript - The Good, the Bad and the UglyJavascript - The Good, the Bad and the Ugly
Javascript - The Good, the Bad and the Ugly
 

Semelhante a Clean code

How to actually use promises - Jakob Mattsson, FishBrain
How to actually use promises - Jakob Mattsson, FishBrainHow to actually use promises - Jakob Mattsson, FishBrain
How to actually use promises - Jakob Mattsson, FishBrainCodemotion Tel Aviv
 
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)David Gómez García
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gearsdion
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptVisual Engineering
 
Java best practices
Java best practicesJava best practices
Java best practicesRay Toal
 
Imagine a world without mocks
Imagine a world without mocksImagine a world without mocks
Imagine a world without mockskenbot
 
Questioning the status quo
Questioning the status quoQuestioning the status quo
Questioning the status quoIvano Pagano
 
Effecient javascript
Effecient javascriptEffecient javascript
Effecient javascriptmpnkhan
 
Keep your Wicket application in production
Keep your Wicket application in productionKeep your Wicket application in production
Keep your Wicket application in productionMartijn Dashorst
 
Beyond Cookies, Persistent Storage For Web Applications Web Directions North ...
Beyond Cookies, Persistent Storage For Web Applications Web Directions North ...Beyond Cookies, Persistent Storage For Web Applications Web Directions North ...
Beyond Cookies, Persistent Storage For Web Applications Web Directions North ...BradNeuberg
 
2013-06-15 - Software Craftsmanship mit JavaScript
2013-06-15 - Software Craftsmanship mit JavaScript2013-06-15 - Software Craftsmanship mit JavaScript
2013-06-15 - Software Craftsmanship mit JavaScriptJohannes Hoppe
 
2013-06-24 - Software Craftsmanship with JavaScript
2013-06-24 - Software Craftsmanship with JavaScript2013-06-24 - Software Craftsmanship with JavaScript
2013-06-24 - Software Craftsmanship with JavaScriptJohannes Hoppe
 
The Dojo Build System
The Dojo Build SystemThe Dojo Build System
The Dojo Build Systemklipstein
 
Efficient JavaScript Development
Efficient JavaScript DevelopmentEfficient JavaScript Development
Efficient JavaScript Developmentwolframkriesing
 
Introduction to ReasonML
Introduction to ReasonMLIntroduction to ReasonML
Introduction to ReasonMLRiza Fahmi
 

Semelhante a Clean code (20)

How to actually use promises - Jakob Mattsson, FishBrain
How to actually use promises - Jakob Mattsson, FishBrainHow to actually use promises - Jakob Mattsson, FishBrain
How to actually use promises - Jakob Mattsson, FishBrain
 
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
 
JavaScript ES6
JavaScript ES6JavaScript ES6
JavaScript ES6
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gears
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
 
Clean Code - A&BP CC
Clean Code - A&BP CCClean Code - A&BP CC
Clean Code - A&BP CC
 
Java best practices
Java best practicesJava best practices
Java best practices
 
dojo.Patterns
dojo.Patternsdojo.Patterns
dojo.Patterns
 
Imagine a world without mocks
Imagine a world without mocksImagine a world without mocks
Imagine a world without mocks
 
Questioning the status quo
Questioning the status quoQuestioning the status quo
Questioning the status quo
 
Effecient javascript
Effecient javascriptEffecient javascript
Effecient javascript
 
Keep your Wicket application in production
Keep your Wicket application in productionKeep your Wicket application in production
Keep your Wicket application in production
 
Beyond Cookies, Persistent Storage For Web Applications Web Directions North ...
Beyond Cookies, Persistent Storage For Web Applications Web Directions North ...Beyond Cookies, Persistent Storage For Web Applications Web Directions North ...
Beyond Cookies, Persistent Storage For Web Applications Web Directions North ...
 
Wtf per lineofcode
Wtf per lineofcodeWtf per lineofcode
Wtf per lineofcode
 
2013-06-15 - Software Craftsmanship mit JavaScript
2013-06-15 - Software Craftsmanship mit JavaScript2013-06-15 - Software Craftsmanship mit JavaScript
2013-06-15 - Software Craftsmanship mit JavaScript
 
2013-06-24 - Software Craftsmanship with JavaScript
2013-06-24 - Software Craftsmanship with JavaScript2013-06-24 - Software Craftsmanship with JavaScript
2013-06-24 - Software Craftsmanship with JavaScript
 
Nantes Jug - Java 7
Nantes Jug - Java 7Nantes Jug - Java 7
Nantes Jug - Java 7
 
The Dojo Build System
The Dojo Build SystemThe Dojo Build System
The Dojo Build System
 
Efficient JavaScript Development
Efficient JavaScript DevelopmentEfficient JavaScript Development
Efficient JavaScript Development
 
Introduction to ReasonML
Introduction to ReasonMLIntroduction to ReasonML
Introduction to ReasonML
 

Clean code

  • 1. Clean Code Be a little more careful with the code you write! Ana Cortés Corbalán 05.02.2013
  • 2. What? Why? How? 05.02.2013 2 www.consol.com
  • 3. The only valid measurement of code quality: WTFs/minute 05.02.2013 3 www.consol.com
  • 4. What is Clean Code? §  Simple §  Efficient §  No duplications §  Elegant §  Direct §  Focused §  With tests §  Minimal dependencies §  It was written by someone who cares §  ... §  Any fool can write code that a computer can understand. Good programmers write code that humans can understand. - Martin Fowler 05.02.2013 4 www.consol.com
  • 5. Why is clean code so important? §  Easier to read §  Easier to understand §  Easier to change §  Add new features §  Find and fix bugs §  Cheaper to maintain §  Code quality is part of software quality 05.02.2013 5 www.consol.com
  • 6. Use Intention-Revealing Names §  int d;! §  int days;! §  int days; //days since creation! §  int daysSinceCreation;! 05.02.2013 6 www.consol.com
  • 7. Use Intention-Revealing Names §  What is the purpose? public List<int[]> getValues() {! List<int[]> list1 = new ArrayList<int[]>();! for (int[] x : theList)! if (x[0] == 4) list1.add(x);! return list1;! }! 05.02.2013 7 www.consol.com
  • 8. Use Intention-Revealing Names §  Better? ! public List<Cell> getFlaggedCells() {! List<Cell> flaggedCells = new ArrayList<Cell>();! for (Cell cell : gameBoard) ! if (cell.isFlagged()) flaggedCells.add(cell);! return flaggedCells;! }! ! 05.02.2013 8 www.consol.com
  • 9. Don´t talk in code – Use Pronounceable Names class DtaRcrd102 {
 private Date genymdhms;
 private Date modymdhms;
 private final String pszqint = "102"; /* ... */ ! }! §  Better? class Customer {
 private Date generationTimestamp; ! private Date modificationTimestamp; ! private final String recordId = "102"; /* ... */ ! }! 05.02.2013 9 www.consol.com
  • 10. More recommendations... §  Class names Customer, Account, AddressParser, ... §  Method names postPayment, deletePage, .... §  When constructors are overloaded... new Complex(23.0);! Complex.fromRealNumber(23.0); ! §  Pick one word per concept get, fetch, retrieve... §  Don´t be cute. Jokes out of the code. public void saveTheUniverse() {...} 05.02.2013 10 www.consol.com
  • 11. Bad Comments §  Redundant, noise, irrelevant, obsolet, „funny“ comments /**! * Returns the day of the month. *! * @return the day of the month. */! public int getDayOfMonth() {! return dayOfMonth;! }! ! /** Always return true. **/! public boolean isAvailable() {! !return false;! }! ! //Magic. Do not touch ! /* Added by Ana Cortés (4-4-2008) */! 05.02.2013 11 www.consol.com
  • 12. Bad Comments /** ! * Dear maintainer:! * ! * Once you are done trying to 'optimize' this routine,! * and have realized what a terrible mistake that was,! * please increment the following counter as a warning! * to the next guy:! * ! * total_hours_wasted_here = 42! **/! §  Commented-Out Code InputStreamResponse response = new InputStreamResponse();! response.setBody(formatter.getResultStream(), ft.getByteCount()); ! //  InputStream resultsStream = formatter.getResultStream(); ! //  StreamReader reader = new StreamReader(resultsStream); ! //  response.setContent(reader.read(formatter.getByteCount())); ! 05.02.2013 12 www.consol.com
  • 13. Good Comments §  Legal comments // Copyright (C) 2003 by Object Mentor, Inc. All rights reserved.
 // Released under the terms of the GNU General Public License version 2 or later. ! §  Informative, clarification comments // format matched kk:mm:ss EEE, MMM dd, yyyy ! Pattern timeMatcher = Pattern.compile("d*:d*:d* w*, w* d*, d*"); ! §  Amplification comments String 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.
 §  TODO comments §  Javadocs in Public APIs 05.02.2013 13 www.consol.com
  • 14. Functions - Small!! public static String testableHtml( PageData pageData,boolean includeSuiteSetup) throws Exception {
 WikiPage wikiPage = pageData.getWikiPage();! StringBuffer buffer = new StringBuffer();! if (pageData.hasAttribute("Test")) {! if (includeSuiteSetup) {! WikiPage suiteSetup = PageCrawlerImpl.getInheritedPage( SuiteResponder. SETUP_NAME, wikiPage);
 ! if (suiteSetup != null) {! WikiPagePath pagePath = suiteSetup.getPageCrawler().getFullPath(suiteSetup);! String pagePathName = PathParser.render(pagePath); ! buffer.append("!include - setup .").append(pagePathName).append("n");! } ! }! WikiPage setup = PageCrawlerImpl.getInheritedPage("SetUp", wikiPage);! ... 40 lines more! 05.02.2013 14 www.consol.com
  • 15. Functions - Small!! public static String renderPageWithSetupsAndTeardowns (PageData pageData, boolean isSuite) throws Exception {
 boolean isTestPage = pageData.hasAttribute("Test"); ! if (isTestPage) { ! WikiPage testPage = pageData.getWikiPage(); ! StringBuffer newPageContent = new StringBuffer(); ! includeSetupPages(testPage, newPageContent, isSuite); ! newPageContent.append(pageData.getContent()); ! includeTeardownPages(testPage, newPageContent, isSuite); ! pageData.setContent(newPageContent.toString()); ! } ! return pageData.getHtml(); ! }! ! ! §  Better? ! public static String renderPageWithSetupsAndTeardowns (PageData pageData, boolean isSuite) throws Exception { ! if (isTestPage(pageData)) ! includeSetupAndTeardownPages(pageData, isSuite); ! return pageData.getHtml(); ! } ! ! 05.02.2013 www.consol.com ! 15
  • 16. Command query separation §  What does it mean? public boolean set(String attribute, String value);! ! if (set("username", "unclebob")) { ... } ! 
 ! §  Better? if (attributeExists("username")) { ! setAttribute("username", "unclebob"); ! } ! 05.02.2013 16 www.consol.com
  • 17. Don´t return null §  Throw exceptions or return special case object ! List<Employee> employees = getEmployees(); ! if (employees != null) { ! for(Employee e : employees) { ! totalPay += e.getPay(); ! } ! } ! ! §  How to remove != null in the code? public List<Employee> getEmployees() { ! if( .. there are no employees .. ) ! return Collections.emptyList(); ! } ! ! ! 05.02.2013 17 www.consol.com
  • 18. Don´t return null public void registerItem(Item item) { ! if (item != null) { ! ItemRegistry registry = persistentStore.getItemRegistry();! if (registry != null) { ! Item existing = registry.getItem(item.getID());
 if (existing.getBillingPeriod().hasRetailOwner()) { ! existing.register(item); ! } ! } ! } ! } ! ! 05.02.2013 18 www.consol.com
  • 19. Have no side effects §  Where is the side effect? 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; ! } ! 05.02.2013 19 www.consol.com
  • 20. 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; ! } ! ! ! public enum error {! OK, INVALID, NO_SUCH, LOCKED, OUT_OF_RESOURCES;! }! 05.02.2013 20 www.consol.com
  • 21. Prefer exceptions to returning error codes §  Better? public void delete(Page page) { ! try { ! !deletePageAndAllReferences(page); ! } ! catch (Exception e) {! logError(e); ! } ! } ! ! private void deletePageAndAllReferences(Page page) throws Exception { ! deletePage(page);
 registry.deleteReference(page.getName()); ! configKeys.deleteKey(page.getKey()); ! }! ! private void logError(Exception e) {! logger.log(e.getMessage());! }!05.02.2013 21 www.consol.com !
  • 22. Keeping tests clean public void testGetPageHierarchyAsXml() throws Exception { ! crawler.addPage(root, PathParser.parse("PageOne")); ! crawler.addPage(root, PathParser.parse("PageOne.ChildOne")); crawler.addPage(root, PathParser.parse("PageTwo")); ! request.setResource("root"); ! request.addInput("type", "pages");
 Responder responder = new SerializedPageResponder(); ! SimpleResponse response = ! (SimpleResponse) responder.makeResponse( new FitNesseContext(root), request); ! String xml = response.getContent(); ! assertEquals("text/xml", response.getContentType()); assertSubString("<name>PageOne</name>", xml); assertSubString("<name>PageTwo</name>", xml); assertSubString("<name>ChildOne</name>", xml); ! } ! ! 05.02.2013 22 www.consol.com
  • 23. Keeping tests clean §  Better? ! public void testGetPageHierarchyAsXml() throws Exception { ! makePages("PageOne", "PageOne.ChildOne", "PageTwo");! ! submitRequest("root", "type:pages"); ! ! assertResponseIsXML(); ! assertResponseContains( ! "<name>PageOne</name>", "<name>PageTwo</name>", "<name>ChildOne</name>" ); ! } ! ! 05.02.2013 23 www.consol.com
  • 24. Summary §  Read „Clean Code“ book. §  Be a little more careful with the code you write §  Write with the „audience“ in mind §  Follow the „Boy Scout Rule“ §  Leave the campground cleaner than you found it §  Use tools that help you cleaning up §  Write Clean Tests 05.02.2013 24 www.consol.com
  • 25. Thank you! Danke! Gracias! ! 05.02.2013 25 www.consol.com