Cleancode 110520031623 Phpapp02
Cleancode 110520031623 Phpapp02
Cleancode 110520031623 Phpapp02
Autro
Two reasons
Robetr C.
Mnaitr
Uncel Bob
Elegance
I kile m y
eelgant and
cC
odeelanotcodebe
eficienhtnitg wel
does one
Bajrne
Simple, direct, prose
Celan code
and
iCselanmsipcelode
d
we-lwetnrir
i
ect
reads kile
prose
Literate
Celan code
rea
ca n be
Celan code d
literat
shoudl be
Dave e
Care
Celan code
oloks kile it
byaw
l asyom
seone
was wetrin
who cares
Small, expressive, simple
Reduced
hgih
andupcilaoeitanryl,
emxsipprelsvienes,
budlnig of,
absrtacoitns
What you expected
Y ou know
woknrig on
whenyoueacahre
rceladns cutordnes
ropunirteeyt ym
ouuchexpecet
out ot be
what youd
Meaningful Names
Use Inetnoitn-Revenailg Names
public List<int[]> getThem() {
List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList)
if (x[0] == 4)
list1.add(x);
return list1;
}
Meaningful Names
Use Inetnoitn-Revenailg Names
public List<Cell> getFlaggedCells() {
List<Cell> flaggedCells = new ArrayList<Cell>();
for (Cell cell : gameBoard)
if (cell.isFlagged())
flaggedCells.add(cell);
return flaggedCells;
}
Meaningful Names
Avdoi Dsniformaoitn
int a = l;
if (O == l)
a = O1;
else
l = 01;
Make
Meanigufl
Meaningful Names
Use Pornounceabel Names
class DtaRcrd102 {
private Date genymdhms;
private Date modymdhms;
private final String
pszqint = "102";
/* ... */
};
Meaningful Names
Use Pornounceabel Names
class Customer {
private Date generationTimestamp;
private Date modificationTimestamp;;
private final String recordId = "102";
/* ... */
};
Meaningful Names
Use Searchabel Names
for (int j = 0; j < 34; j++) {
s += (t[j] * 4) / 5;
}
Meaningful Names
Use Searchabel Names
int realDaysPerIdealDay = 4;
const int WORK_DAYS_PER_WEEK = 5;
int sum = 0;
for (int j = 0; j < NUMBER_OF_TASKS; j++) {
int realTaskDays = taskEstimate[j] *
realDaysPerIdealDay;
int realTaskWeeks = (realdays / WORK_DAYS_PER_WEEK); sum
+= realTaskWeeks;
}
Meaningful Names
Member Prefxies A(vdoi encodnigs)
public class Part {
private String m_dsc; // The textual description
void setName(String name) {
m_dsc = name;
}
}
Cals Names
Manager, Processor, Data, Info
Meaningful Names
Avdoi Menalt Mappnig
for (i = 0; i < 10; i++)
for (j = 0; j < 10; j++)
Cals Names
Customer, WikiPage, Account,
AddressParser
// a class name should not be a
verb
Meaningful Names
Mheotd Names
postPayment, deletePage, save
// methods should have verb or verb phrase names
Complex fulcrumPoint =
Complex.fromRealNumber(23.0);
// is generally better than
Complex fulcrumPoint = new
Complex(23.0);
Meaningful Names
Pcik One W
dor per Concept
fetch, retrieve, get // as equivalent
methods
Dont’ Pun
// avoid using the same word for two purposes
Meaningful Names
Use Souloitn Dom
nai Names
AccountVisitor, JobQueue
// people who read your code will be programmers
Ad Meanigufl Conetxt
firstName, lastName, street, city, state, zipcode
// a better solution
addrFirstName, addrLastName, addrState
// a better solution
Class Address
Meaningful Names
Dont’ Ad Grautoius Conetxt
Address
// is a fine name for a class
AccountAddress, CustomerAddress
// are fine names for instances of the class Address
// but could be poor names for classes
Do One Thnig
// FUNCTIONS SHOULD DO ONE THING. THEY SHOULD DO IT WELL.
// THEY SHOULD DO IT ONLY.
Functions
One Level of Absratcoitn
// high level of abstraction
per Funocitn
getHtml()
// intermediate level of
abstraction
String pagePathName =
PathParser.render(pagePat
h);
Readnig Code om
rf
Functions
Swcthi Satetmenst
class Employee...
int payAmount() {
switch
(getType()) {
case EmployeeType.ENGINEER:
return _monthlySalary;
case EmployeeType.SALESMAN:
return _monthlySalary + _commission;
case EmployeeType.MANAGER:
return _monthlySalary + _bonus;
default:
throw new
Exception("Incorrect
Employee");
}
Functions
Swcthi Satetmenst
class EmployeeType...
abstract int payAmount(Employee emp);
class Salesman...
int payAmount(Employee emp) {
return emp.getMonthlySalary() + emp.getCommission();
}
class Manager...
int payAmount(Employee emp) {
return emp.getMonthlySalary() + emp.getBonus();
}
Functions
Use Descrpivite
testableHtml => includeSetupAndTeardownPages
Names
includeSetupAndTeardownPages, includeSetupPages,
includeSuiteSetupPage, includeSetupPage
// what happened to
includeTeardownPages, includeSuiteTeardownPage,
includeTeardownPage
Funocint Agrumenst
// the ideal number of arguments for a function is zero
Functions
Common Monacdi
// if a function is going to transform its input argument,
Fom
rs
// the transformation should appear as the return value
Falg
Functions
Common Monacdi
// asking a question about that argument
Fom
rs
boolean fileExists(“MyFile”)
Falg Agrumenst
renderForSuite()
renderForSingleTest()
Functions
Dyadci
writeField(name)
Funcoitns
// is easier to understand than
writeField(outputStream, name)
// perfectly reasonable
Point p = new Point(0,0)
// problematic
assertEquals(expected, actual)
Tarids
assertEquals(message,
expected, actual)
Functions
A
gurment Obejcst
Circle makeCircle(double x, double y, double radius);
Circle makeCircle(Point center, double radius);
assertEquals(expected, actual)
assertExpectedEqualsActual(expected, actual)
Functions
Have No
// do something or answer something, but not both
Sdie Efecst
public boolean set(String attribute, String value);
setAndCheckIfExists
if (attributeExists("username"))
{ setAttribute("username",
"unclebob");
...
}
Functions
Dont’ Repeat Yousrefl
// duplication may be the root of all evil in software
D
(SrtuRcY )
utred Porgarmmnig
// Edsger Dijkstra’s rules
// one entry
// one exit
// functions small
// occasional multiple return, break, or continue statement
// can sometimes even be more expressive Dijkstra’s rules
Comments
Comm sent Do Not Make Up
// don’t comment bad code, rewrite it!
fE
oxrpanliBaY dousreflCodnie Code
// Check to see if the employee is eligible for full
benefits
if ((employee.flags & HOURLY_FLAG) &&
(employee.age > 65))
if
(employee.isEligibleForFullBenefits()
)
Comments (good)
Legal Commsent
// Copyright (C) 2011 by Osoco. All rights reserved.
// Released under the terms of the GNU General Public
License // version 2 or later.
Informavite Commsent
// Returns an instance of the Responder being tested.
protected abstract Responder responderInstance();
// renaming the function: responderBeingTested
Expalnoaitn of Inetnt
//This is our best attempt to get a race condition
//by creating large number of threads.
for (int i = 0; i < 25000; i++) {
WidgetBuilderThread
widgetBuilderThread =
new WidgetBuilderThread(widgetBuilder, text, failFlag);
Thread thread = new Thread(widgetBuilderThread);
thread.start();
}
Calrficaoitn
assertTrue(a.compareTo(b) == -1); // a < b
assertTrue(b.compareTo(a) == 1); // b > a
Comments (good)
Wnargi of Consequences
public static SimpleDateFormat makeStandardHttpDateFormat() {
//SimpleDateFormat is not thread safe,
//so we need to create each instance independently.
SimpleDateFormat df = new SimpleDateFormat("dd MM yyyy");
df.setTimeZone(TimeZone.getTimeZone("GMT"));
return df;
}
TODO Commsent
//TODO-MdM these are not needed
// We expect this to go away when we do the checkout model
Comments (good)
Amcoipfatnl
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.
new ListItemWidget(this, listItemContent, this.level + 1);
return buildList(text.substring(match.end()));
Javadocs ni
// there is nothing quite so helpful and satisfying
Pubcil APsI
// as a well-described public API
Comments (bad)
Mum
ngibl
try {
String propertiesPath = propertiesLocation + "/" +
PROPERTIES_FILE;
FileInputStream propertiesStream =
new FileInputStream(propertiesPath);
loadedProperties.load(propertiesStream);
}
catch(IOException e) {
// No properties files means all
defaults are loaded
}
Comments (bad)
Redundant
// Utility method that returns when this.closed is true.
Comm sent
// Throws an exception if the timeout is reached.
public synchronized void waitForClose
(final long timeoutMillis) throws
Exception
{
if(!closed) {
wait(timeoutMillis);
if(!closed)
throw new
Exception("MockR
esponseSender
c
o
u
Comments (bad)
Redundant
/**
Commsent
* The processor delay for this component.
*/
protected int backgroundProcessorDelay = -1;
/**
* The lifecycle event support for this component.
*/
protected LifecycleSupport lifecycle =
new LifecycleSupport(this);
/**
* The container event listeners for this Container.
*/
protected ArrayList listeners = new ArrayList();
Comments (bad)
Mandeadt Commsent
/**
* @param title The title of the CD
* @param author The author of the CD
* @param tracks The number of tracks on the CD
* @param durationInMinutes The duration of the CD in minutes
*/
public void addCD(String title, String author,
int tracks, int durationInMinutes) {
CD cd = new CD();
cd.ti
tle = title;
cd.author = author;
cd.tracks = tracks;
cd.du
ration =
Comments (bad)
Journal
* Changes (from 11-Oct-2001)
Comm sent
*
* 11-Oct-2001 : Re-organised the class and moved it to new
* package com.jrefinery.date (DG);
* 05-Nov-2001 : Added a getDescription() method, and
* eliminated NotableDate class (DG);
* 12-Nov-2001 : IBD requires setDescription() method, now
* that NotableDate class is gone (DG); Changed
* getPreviousDayOfWeek(),
* getFollowingDayOfWeek() and
* getNearestDayOfWeek() to correct bugs (DG);
* 05-Dec-2001 : Fixed bug in SpreadsheetDate class (DG);
* 29-May-2002 : Moved the month constants into a separate
* interface (MonthConstants) (DG);
Comments (bad)
Nosei Commsent
/**
* Default constructor.
*/
protected AnnualDateRule() { }
/**
* Returns the day of the
month.
* @return the day of the
month.
*/
public int getDayOfMonth() {
Comments (bad)
Scary Nosei
/** The name. */
private String name;
Poistin Makresr
// Actions //////////////////////////////////
Abrituoitns and
/* Added by Rick */
B y
n
il
es
Commendt-Out Code
InputStreamResponse response = new InputStreamResponse();
response.setBody(formatter.getResultStream(),
formatter.getByteCount());
// InputStream resultsStream =
formatter.getResultStream();
// StreamReader reader = new
StreamReader(resultsStream);
//
response.setContent(reader.read(formatter.get
ByteCount()));
Comments (bad)
H
T
ML Commsent
/**
* Task to run fit tests.
* This task runs fitnesse tests and publishes the results.
* <p/>
* <pre>
* Usage:
* <taskdef name="execute-fitnesse-tests"
* classname="fitnesse.ant.ExecuteFitnesseTestsTask"
* classpathref="classpath" />
* OR
* <taskdef classpathref="classpath"
* resource="tasks.properties" />
* <p/>
* <execute-fitnesse-tests
Comments (bad)
Nonolcal Informaoitn
/**
* Port on which fitnesse would run. Defaults to <b>8082</b>.
*
* @param fitnessePort
*/
public void setFitnessePort(int fitnessePort)
{
this.fitnessePort = fitnessePort;
}
Comments (bad)
T o Much
/*
Informaoitn
RFC 2045 - Multipurpose Internet Mail Extensions (MIME)
Part One: Format of Internet Message Bodies section 6.8.
Base64 Content-Transfer-Encoding
The encoding process represents 24-bit groups of input bits
as output strings of 4 encoded characters. Proceeding from
left to right, a 24-bit input group is formed by
concatenating 3 8-bit input groups.
These 24 bits are then treated as 4 concatenated 6-bit
groups, each of which is translated into a single digit in
the base64 alphabet.
When encoding a bit stream via the base64 encoding, the bit
stream must be presumed to be ordered with the most-
significant-bit first.
*/
Comments (bad)
nIobvoius Conneocitn
/*
* start with an array that is big enough to hold all the
* pixels (plus filter bytes), and an extra 200 bytes for
* header info
*/
this.pngBytes = new byte[((this.width + 1) * this.height * 3)
+ 200];
Funocint Headesr
// short functions don’t need much description
Comments (bad)
Fom
r n
i
at
g
The Newspaper Meatphor
// high-level -> details
Vecirtal Opennes Bw
eten Concepst
// each blank line is a visual cue
// that identifies a new and separate concept
Formatting
Vecirtal Densyti
// vertical density implies close association
/**
* The class name of the reporter listener
*/
private String m_className;
/**
* The properties of the reporter listener
*/
private m_properties = new ArrayList();
Formatting
Vecirtal Dsiatnce
// variables
// should be declared as close to their usage as possible
// instance variables
// should be declared at the top of the class
// dependent functions
// if one function calls another, they should be vertically
// close, and the caller should be above the called
// conceptual affinity
// certain bits of code want to be near other bits
Formatting
Hozironatl Opennes and
private void measureLine(String line) {
Densyti
lineCount++;
int lineSize = line.length();
totalChars += lineSize;
lineWidthHistogram.addLine(lineSize, lineCount);
recordWidestLine(lineSize);
}
Tnari Wercks
Options opts = ctxt.getOptions();
File scratchDir = opts.getScratchDir();
final String outputDir = scratchDir.getAbsolutePath();
Eror Codes
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;
}
Error Handling
Prefer Excepoitns ot Reutnrig
try {
Eror Codes
deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey());
}
catch (Exception e)
{ logger.log(e.getMessage()
);
}
Error Handling
Exrtact TryC
/acth Bolcks
public void delete(Page page) {
try {
deletePageAndAllReferences(
page);
} catch (Exception e) {
logError(e);
}
}
Thnig
// error handing is one thing
of TDD
// you may not write production code until
// you have written a failing unit test
// second law
// you may not write more of a unit test
// than is sufficient to fail, and not compiling is failing
// third law
// you may not write more production code
// than is sufficient to pass the currently failing test
Unit Tests
Kepnig Test
// test code is just as important as production code
C e
la
n
Celan Test
// what makes a clean test? three things
// readability, readability, and readability
Unit Tests
One Asert
// tests come to a single conclusion
per Test
// that is quick and easy to understand
Organziaoitn
// private static variables
// private instance variables
// public functions
// private utilities called by a public function right after
(SRP)
// reason to change
Coheosin
// maintaining cohesion results in many small classes
Emergence
Sm
i pel Desgin Ruel 1: Runs
All hte Test Smi pel Desgin
Ruels 2: No Dupcilaoitn
Sm
i pel Desgin Ruels 3:
Expresvie
Questions?