Upload
james-brown
View
442
Download
0
Embed Size (px)
Citation preview
CLEAN CODE“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 namesgenymdhms
Use searchable namesLength of a name should correspond to the
size of its scope Avoid disinformation
Inconsistent spellings
Meaningful Names
Make meaningful distinctionsWriting code solely to appease the compilerNoise words Product/ProductInfo/ProductData
Use intention-revealing namesWhy 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 argumentsIdeal # of arguments: 0includeSetupPage() easier to understand
than includeSetupPageInto(newPagecontent)
If the input’s going to be transformed, it should be returned
Functions
Flag argumentsImmediately 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 blocksAllows you to understand, then ignore, error
processingError 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 benefitsif ((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
FormattingpublicDataPair[] getHotelInformation(String hotelId, String informationId) { return getHotelInfo("EN", hotelId, informationId); }
publicDataPair[] 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; }
“Eastern Polish Christmas Tree Notation”
Formatting
Small files usually easier to understand than large files
Newspaper metaphorDetail 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 dataOO code: easy to add new classes; hard to
add new functions Data structures: expose their data and
have no meaningful functionsProcedural 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 manipulatesDon’t expose internal structure through accessors
“Train wrecks” final String outputDir =
ctxt.getOptions().getScratchDir().getAbsolutePath();
HybridsFunctions that do significant things, but also public
variables/accessorsHard to add both new functions and new data
structuresLeads 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 upBreaks 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 smallIn 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