“A Handbook of Agile Software Craftsmanship”
Meaningful Names
Meaningful Names
 “Variables should be named with the
  same level of care given to naming a
  newborn child”
 Use pronounceable names
     genymdhms
   Use searchable names
     Length of a name should correspond to the
     size of its scope
   Avoid disinformation
     Inconsistent spellings
Meaningful Names
   Make meaningful distinctions
     Writing code solely to appease the compiler
     Noise words
     Product/ProductInfo/ProductData
   Use intention-revealing names
     Why does it exist?
     What does it do?
     How is it used?
 One word per concept...but don’t pun
 Don’t add gratuitous context
Functions
Functions
   Small
     Smaller
      ○   Smaller than that

 if/else/while: 1 line blocks
 Do One Thing
     Problem: What is “one thing”?
      ○ “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”
      ○ “A function is doing more than one thing if you can
        extract another function from it with a name that is
        not merely a restatement of its implementation”
     Sections within functions – obviously doing
      more than one thing
Functions
   The stepdown rule
     Top-down narrative
   switch statements – always do N things
     Should appear only once to create polymorphic
      objects, hidden from rest of system
   Function arguments
     Ideal # of arguments: 0
     includeSetupPage() easier to understand
      than
      includeSetupPageInto(newPagecontent)
     If the input’s going to be transformed, it should
      be returned
Functions
   Flag arguments
     Immediately imply that the function does
     more than one thing!
   Command query separation
     Either change the state of an object, or
     return some information about that object
   Extract try/catch blocks
     Allows you to understand, then ignore, error
      processing
     Error handling is one thing!
Comments
Comments
   “Comments are always failures”
     Compensate for failure to express in code
 They lie – we can’t realistically maintain
  them
 Explain yourself in code
     // Check to see if the employee is eligible for
      full benefits
      if ((employee.flags & HOURLY_FLAG) &&
          (employee.age > 65))
    vs.
       if (employee.isEligibleForFullBenefits())
Comments
   Good comments
       Informative
       Explain of intent
       Clarification – when it’s code you can’t alter
       Warning of consequences
   Bad comments
       Redundant
       Misleading
       Mandated
       Journal comments
       Noise comments (“Default constructor”)
       Closing brace comments
       Commented-out code
       HTML comments
       Nonlocal information
       TMI
       Javadocs in nonpublic code
Formatting
“Eastern Polish Christmas Tree Notation”
    public
    DataPair[] getHotelInformation(String hotelId, String informationId)
                                          {
                                            return getHotelInfo("EN", hotelId, informationId);
                                          }
    public
    DataPair[] getHotelInformation(String lang, String hotelId, String informationId)
                                          {
                              String key = "_HOINF_"+lng+"_"+hotelId+"_"+informationId;
                          DataPair[] tbl = (DataPair[])csh.getObject(key);
                            if(tbl!=null) return tbl;
                           Connection cn = null;
              OracleCallableStatement cs = null;
                                     try {
                              String qry = " begin HotelServices.getHotelInfo(?, ?, ?, ?, ?); end; ";
                                  logger . debug("---"+qry+" "+hotelId+" "+informationId);
                                      cn = DriverManager.getConnection("jdbc:weblogic:pool:oraclePool",null);
                                      cs = (OracleCallableStatement)cn.prepareCall(qry);
                                      cs . registerOutParameter(1,java.sql.Types.INTEGER);
                                      cs . registerOutParameter(2,java.sql.Types.OTHER);
                                      cs . setString(3,hotelId);
                                      cs . setString(4,informationId);
                                      cs . setString(5,lang);
                                      cs . execute();
                                 int sta = cs.getInt(1);
                               if(sta!=0) throw new Exception("status not zero sta="+sta);
                            ResultSet rs = cs.getResultSet(2);
                                     tbl = getDataPairArray(rs);
                                  logger . debug("sta="+sta+" key="+key+" cn="+cn);
                                     csh . put(key,tbl);
                                         }
                                    catch(Exception e)
                                         {
                                  logger . debug("!!! "+e.toString()+" "+key);
                                         }
                                  finally
                                         {
                                     try {
                         if(cs!=null) cs . close();
                         if(cn!=null) cn . close();
                                         }
                                    catch(Exception x)
                                         {
                                  logger . debug("!!! "+x.toString()+" "+key);
                                  logger . error("!!! "+x.toString());
                                         }
                                         }
                                   return tbl;
                                         }
Formatting
 Small files usually easier to understand
  than large files
 Newspaper metaphor
     Detail should increase as we move
     downward
 Vertical openness between concepts
 Vertical density & closeness implies
  close association
 Horizontal openness
     Accentuate operator precedence?
Objects and Data Structures
Objects and Data Structures
   Objects: hide data behind abstractions
    and expose functions that operate on
    that data
     OO code: easy to add new classes; hard to
     add new functions
   Data structures: expose their data and
    have no meaningful functions
     Procedural code: easy to add new functions;
     hard to add new data structures
Objects and Data Structures
   Law of Demeter: module shouldn’t know
    about the innards of the objects it
    manipulates
     Don’t expose internal structure through
        accessors
   “Train wrecks”
       final String outputDir =
        ctxt.getOptions().getScratchDir().getAbsolutePath();

   Hybrids
     Functions that do significant things, but also
      public variables/accessors
     Hard to add both new functions and new data
      structures
     Leads to feature envy
Error handling
 If it obscures logic, it’s wrong
 Exceptions rather than return codes
 Use unchecked exceptions
     Checked: low level changes propagate up
     Breaks encapsulation
 Wrap 3rd-party APIs
 Don’t return null – throw exception or
  return a special-case object
 Don’t pass null
Classes
   ...should also be small
     In terms of responsibilities
 SRP – should have ONE reason to
  change
 Big # of small classes vs. Small # of
  large classes
 Cohesion
 OCP – open for extension, closed for
  modification

Clean code

  • 1.
    “A Handbook ofAgile Software Craftsmanship”
  • 2.
  • 3.
    Meaningful Names  “Variablesshould be named with the same level of care given to naming a newborn child”  Use pronounceable names  genymdhms  Use searchable names  Length of a name should correspond to the size of its scope  Avoid disinformation  Inconsistent spellings
  • 4.
    Meaningful Names  Make meaningful distinctions  Writing code solely to appease the compiler  Noise words Product/ProductInfo/ProductData  Use intention-revealing names  Why does it exist?  What does it do?  How is it used?  One word per concept...but don’t pun  Don’t add gratuitous context
  • 5.
  • 6.
    Functions  Small  Smaller ○ Smaller than that  if/else/while: 1 line blocks  Do One Thing  Problem: What is “one thing”? ○ “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” ○ “A function is doing more than one thing if you can extract another function from it with a name that is not merely a restatement of its implementation”  Sections within functions – obviously doing more than one thing
  • 7.
    Functions  The stepdown rule  Top-down narrative  switch statements – always do N things  Should appear only once to create polymorphic objects, hidden from rest of system  Function arguments  Ideal # of arguments: 0  includeSetupPage() easier to understand than includeSetupPageInto(newPagecontent)  If the input’s going to be transformed, it should be returned
  • 8.
    Functions  Flag arguments  Immediately imply that the function does more than one thing!  Command query separation  Either change the state of an object, or return some information about that object  Extract try/catch blocks  Allows you to understand, then ignore, error processing  Error handling is one thing!
  • 9.
  • 10.
    Comments  “Comments are always failures”  Compensate for failure to express in code  They lie – we can’t realistically maintain them  Explain yourself in code  // Check to see if the employee is eligible for full benefits if ((employee.flags & HOURLY_FLAG) && (employee.age > 65)) vs. if (employee.isEligibleForFullBenefits())
  • 11.
    Comments  Good comments  Informative  Explain of intent  Clarification – when it’s code you can’t alter  Warning of consequences  Bad comments  Redundant  Misleading  Mandated  Journal comments  Noise comments (“Default constructor”)  Closing brace comments  Commented-out code  HTML comments  Nonlocal information  TMI  Javadocs in nonpublic code
  • 12.
    Formatting “Eastern Polish ChristmasTree Notation” public DataPair[] getHotelInformation(String hotelId, String informationId) { return getHotelInfo("EN", hotelId, informationId); } public DataPair[] getHotelInformation(String lang, String hotelId, String informationId) { String key = "_HOINF_"+lng+"_"+hotelId+"_"+informationId; DataPair[] tbl = (DataPair[])csh.getObject(key); if(tbl!=null) return tbl; Connection cn = null; OracleCallableStatement cs = null; try { String qry = " begin HotelServices.getHotelInfo(?, ?, ?, ?, ?); end; "; logger . debug("---"+qry+" "+hotelId+" "+informationId); cn = DriverManager.getConnection("jdbc:weblogic:pool:oraclePool",null); cs = (OracleCallableStatement)cn.prepareCall(qry); cs . registerOutParameter(1,java.sql.Types.INTEGER); cs . registerOutParameter(2,java.sql.Types.OTHER); cs . setString(3,hotelId); cs . setString(4,informationId); cs . setString(5,lang); cs . execute(); int sta = cs.getInt(1); if(sta!=0) throw new Exception("status not zero sta="+sta); ResultSet rs = cs.getResultSet(2); tbl = getDataPairArray(rs); logger . debug("sta="+sta+" key="+key+" cn="+cn); csh . put(key,tbl); } catch(Exception e) { logger . debug("!!! "+e.toString()+" "+key); } finally { try { if(cs!=null) cs . close(); if(cn!=null) cn . close(); } catch(Exception x) { logger . debug("!!! "+x.toString()+" "+key); logger . error("!!! "+x.toString()); } } return tbl; }
  • 13.
    Formatting  Small filesusually easier to understand than large files  Newspaper metaphor  Detail should increase as we move downward  Vertical openness between concepts  Vertical density & closeness implies close association  Horizontal openness  Accentuate operator precedence?
  • 14.
    Objects and DataStructures
  • 15.
    Objects and DataStructures  Objects: hide data behind abstractions and expose functions that operate on that data  OO code: easy to add new classes; hard to add new functions  Data structures: expose their data and have no meaningful functions  Procedural code: easy to add new functions; hard to add new data structures
  • 16.
    Objects and DataStructures  Law of Demeter: module shouldn’t know about the innards of the objects it manipulates  Don’t expose internal structure through accessors  “Train wrecks”  final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();  Hybrids  Functions that do significant things, but also public variables/accessors  Hard to add both new functions and new data structures  Leads to feature envy
  • 17.
    Error handling  Ifit obscures logic, it’s wrong  Exceptions rather than return codes  Use unchecked exceptions  Checked: low level changes propagate up  Breaks encapsulation  Wrap 3rd-party APIs  Don’t return null – throw exception or return a special-case object  Don’t pass null
  • 18.
    Classes  ...should also be small  In terms of responsibilities  SRP – should have ONE reason to change  Big # of small classes vs. Small # of large classes  Cohesion  OCP – open for extension, closed for modification

Editor's Notes

  • #17 Can split the train wreck into 3 variables. Whether this breaks Law of Demeter depends on whether or not those variables are objects or data structures
  • #18 Error codes: caller has to check for errors immediately after the callWrap APIs: make it returns a common exception type