0% found this document useful (0 votes)
19 views88 pages

Cleancode 110520031623 Phpapp02

The document discusses clean code and provides guidelines for writing clean code in 3 sentences or less: 1. Clean code should have meaningful names, small and focused functions, and avoid duplication through principles like the single responsibility principle and DRY. 2. Comments should explain intent, document legal issues, and warn of consequences but not make up for bad code, and functions should do one thing, use descriptive names, and have few understandable arguments. 3. Overall the document provides best practices for writing code that is readable, maintainable and modifyable through techniques like breaking code into small, pure functions and using intention-revealing names.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
19 views88 pages

Cleancode 110520031623 Phpapp02

The document discusses clean code and provides guidelines for writing clean code in 3 sentences or less: 1. Clean code should have meaningful names, small and focused functions, and avoid duplication through principles like the single responsibility principle and DRY. 2. Comments should explain intent, document legal issues, and warn of consequences but not make up for bad code, and functions should do one thing, use descriptive names, and have few understandable arguments. 3. Overall the document provides best practices for writing code that is readable, maintainable and modifyable through techniques like breaking code into small, pure functions and using intention-revealing names.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 88

C L E A N CODE

Arturo
Two reasons

1.You are a
porgarmmer
2.You want to
The Boy Scout Rule

Robert
C.
Martn
Uncle
Elegance
I lke
elgant
my
Cl ean
anthng
d
co
co de
de
effcentwel
to be
Simple, direct, prose
Clean
and
co
de
Clean s
w-
e
lldrec
sm e
p
l
codet
wrtte
L iterat
e
Clean
era
code
Clean d
can blt
ee r
at
code
Dave e
Care

Clean
oloks lke
by
code
t was
osmeone
al ways
wrtt en
Small, expressive, simple

Reduced
hgh
anduplcat
d early
exsm ple n
pressve
buldn
onarbstracton
esr
g ofr
What you expected
You
workng
wheknown
e
ron
ads celtuan
rns
epr
achye
ott
y
u a
e
xr
e
p
ec
et
o
cmut
deuchto
o
rutned
be
Meaningful Names
Use n
Itenton-
public List<int[]> getThem() {

Revealng Names
List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList)
if (x[0] == 4)
list1.add(x);
return list1;
}
Meaningful Names
Use n
Itenton-
public List<Cell> getFlaggedCells() {

Revealng Names
List<Cell> flaggedCells = new ArrayList<Cell>();
for (Cell cell : gameBoard)
if (cell.isFlagged())
flaggedCells.add(cell);
return flaggedCells;
}
Meaningful Names
Avod Dsnofm
int a
r aton
= l;
if (O == l)
a = O1;
else
l = 01;

Make
Mean
Meaningful Names
Use Pornounceable
class DtaRcrd102 {

Names
private Date genymdhms;
private Date
modymdhms;
private final String
pszqint = "102";
/* ... */
};
Meaningful Names
Use Pornounceable
class Customer {

Names
private Date generationTimestamp;
private Date modificationTimestamp;;
private final String recordId = "102";
/* ... */
};
Meaningful Names
Use Searchable
Names
for (int j = 0; j < 34; j++) {
s += (t[j] * 4) / 5;
}
Meaningful Names
Use Searchable
int realDaysPerIdealDay = 4;

Names
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
Mem
ber Prefxes
public class Part {
private String m_dsc; // The textual description

(Avod encodngs)
}
void setName(String name) {
m_dsc = name;

Hungaran Noatton
A
(vod encodngs)
PhoneNumber phoneString;
Meaningful Names
Mem
ber Prefxes
public class Part
{ String

(Avod encodngs)
description;
void setDescription(String description) {
this.description = description;
}
}

Hungaran
Noatton A(vod encodngs)
Meaningful Names
Avod Menat l
for (a = 0; a < 10; a++)

Mappng
for (b = 0; b < 10; b++)

Cal ss Names
Manager, Processor, Data, Info
Meaningful Names
Avod Menat l
for (i = 0; i < 10; i++)

Mappng
for (j = 0; j < 10; j++)

Cal ss Names
Customer, WikiPage, Account,
AddressParser
// a class name should not be a
verb
Meaningful Names
Method Names
postPayment, deletePage, save
// methods should have verb or verb phrase names

string name = employee.getName();


customer.setName("mike");
if (paycheck.isPosted())...

Complex fulcrumPoint =
Complex.fromRealNumber(23.0);
// is generally better than
Complex fulcrumPoint = new
Complex(23.0);
Meaningful Names
Pck One Word
fetch, retrieve, get // as equivalent

per Concept
methods

controller, manager, driver // confusing

Don’t Pun
// avoid using the same word for two purposes
Meaningful Names
Use Soluton
AccountVisitor, JobQueue

Do man Names
// people who read your code will be programmers

Add Meanngful
Conet xt
firstName, lastName, street, city, state, zipcode
// a better solution
addrFirstName, addrLastName, addrState
Meaningful Names
Don’t Add
Address

Gratutous
// is a fine name for a class

AccountAddress, CustomerAddress
// are fine names for instances of the class Address

Context
// but could be poor names for classes

MAC addresses, port addresses, Web addresses


// a better solution
PostalAddress, MAC, URI
Functions
Sma!l
// rules of functions:
// 1. should be small
// 2. should be smaller than that

// < 150 characters per line


// < 20 lines

Do One Thng
// FUNCTIONS SHOULD DO ONE THING. THEY SHOULD DO IT WELL.
// THEY SHOULD DO IT ONLY.
Functions
One Level of
// high level of abstraction

Abstracton per
getHtml()

// intermediate level of
abstraction

Functon
String pagePathName =
PathParser.render(pagePat
h);

// remarkably low level


.append("\n")

Readng Code
Functions
Swtch
class Employee...

Statemenst
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
Swtch
class EmployeeType...

Statemenst
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
testableHtml => includeSetupAndTeardownPages

Descrp
includeSetupAndTeardownPages, includeSetupPages,
includeSuiteSetupPage, includeSetupPage
// what happened to

tve
includeTeardownPages, includeSuiteTeardownPage,
includeTeardownPage

Func
Nm
aes ton A
rgu
m ent
s
// the ideal number of arguments for a function is zero
Functions
Common
// if a function is going to transform its input argument,

Monadc
// the transformation should appear as the return value

StringBuffer transform(StringBuffer in)


// is better than

Fom
rs
void transform(StringBuffer out)

Fal g
Functions
Common
// asking a question about that argument

Monadc
boolean fileExists(“MyFile”)

// operating on that argument, transforming and returning it


InputStream fileOpen(“MyFile”)

Fom
rs
// event, use the argument to alter the state of the system
void passwordAttemptFailedNtimes(int attempts)

Fal g Argu
ments
renderForSuite()
renderForSingleTest()
Functions
Dyadc
writeField(name)

Functon
// is easier to understand than
writeField(outputStream, name)

// perfectly reasonable

s
Point p = new Point(0,0)

// problematic
assertEquals(expected, actual)

Trads
assertEquals(message,
expected, actual)
Functions
Argumen
Circle makeCircle(double x, double y, double radius);

t Objects
Circle makeCircle(Point center, double radius);

Verbs and
Keywodrs
write(name)
writeField(name)

assertEquals(expected, actual)
Functions
Have No
// do something or answer something, but not both

Sde
public boolean set(String attribute, String value);

setAndCheckIfExists

Eff
ects
if (attributeExists("username"))
{ setAttribute("username",
"unclebob");
...
}
Functions
Don’t
// duplication may be the root of all evil in software

R epeat
Structured Porgarmmng
Yousrelf (DRY)
// 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
Comments Do Not
// don’t comment bad code, rewrite it!

M a
k e Up o
f r B
ad
Explan Yourself n
C o
de
Code
// Check to see if the employee is eligible for full
benefits
if ((employee.flags & HOURLY_FLAG) &&
(employee.age > 65))
Comments (good
)

Legal Commen
st
// Copyright (C) 2011 by Osoco. All rights reserved.
// Released under the terms of the GNU General Public
License // version 2 or later.

nIofrmatve Comments
// Returns an instance of the Responder being tested.
protected abstract Responder responderInstance();
// renaming the function: responderBeingTested

// format matched kk:mm:ss EEE, MMM dd, yyyy


Pattern timeMatcher = Pattern.compile( "\\
d*:\\d*:\\d* \\w*, \\w* \\d*, \\d*");
Comments (good
)

Explanaton of Intent
//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();
}

Calrfcaton
assertTrue(a.compareTo(b) == -1); // a < b
assertTrue(b.compareTo(a) == 1); // b > a
Comments (good)

Warnng of
public static SimpleDateFormat makeStandardHttpDateFormat() {

Consequences
//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 Comments
//TODO-MdM these are not needed
// We expect this to go away when we do the checkout model
Comments (good
)

Amp
cfalo
tn
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 n
// there is nothing quite so helpful and satisfying

Publc
// as a well-described public API
Comments (bad
)

Mumnbgl
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.

Commen st
// 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
/**

Commen st
* 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
)

Mandate
/**

d
* @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

Comments
*/
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
Comments (bad
)

Journal Commen
*
st
Changes (from 11-Oct-2001)
*
* 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
)

Nose
/**

Commen
st
* Default constructor.
*/
protected AnnualDateRule() { }

/** The day of the month. */


private int dayOfMonth;

/**
* Returns the day of the
month.
* @return the day of the
month.
*/
public int getDayOfMonth() {
Comments (bad
)

Scary
/** The name. */

Nose
private String name;

/** The version. */


private String version;

/** The licenceName. */


private String licenceName;

/** The version. */


private String info;
Comments (bad
)

Don’t Use a Comment When You


Can Use a Functon or a
Varable
// does the module from the global list <mod> depend on the
// subsystem we are part of?
if (smodule.getDependSubsystems()
.contains(subSysMod.getSubSystem()))

// this could be rephrased without the comment as


ArrayList moduleDependees = smodule.getDependSubsystems();
Comments (bad
)

Poston Markers
// Actions //////////////////////////////////

Colsng Brace Commen


st
while ((line = in.readLine()) != null) {
lineCount++;
charCount += line.length();
String words[] = line.split("\\W");
wordCount += words.length;
} //while
Comments (bad
)

Attrbuto
/* Added by Rick */

ns and
CommenetdO
- ut Code
Bylnes
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
)

HTML
Commesnt
/**
* Task to run fit tests.
* This task runs fitnesse tests and publishes the results.
* <p/>
* <pre>
* Usage:
* &lt;taskdef name=&quot;execute-fitnesse-tests&quot;
* classname=&quot;fitnesse.ant.ExecuteFitnesseTestsTask&quot;
* classpathref=&quot;classpath&quot; /&gt;
* OR
* &lt;taskdef classpathref=&quot;classpath&quot;
* resource=&quot;tasks.properties&quot; /&gt;
* <p/>
* &lt;execute-fitnesse-tests
Comments (bad
)

Nonolcal
/**

Infom r ato
* Port on which fitnesse would run. Defaults to <b>8082</b>.
*
* @param fitnessePort
*/

n
public void setFitnessePort(int fitnessePort)
{
this.fitnessePort = fitnessePort;
}
Comments (bad
)

o
To
/*

Much
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

nIofrmaton
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
)

nIobvous
/*

Connecto
* start with an array that is big enough to hold all the
* pixels (plus filter bytes), and an extra 200 bytes for
* header info
*/

n
this.pngBytes = new byte[((this.width + 1) * this.height * 3)
+ 200];

Functon Headers
// short functions don’t need much description
Comments (bad
)

Javadocs n Nonpublc
Code
// extra formality of the javadoc comments
Formatting
The
// communication

Purpose
The Newp
saper
of Fo
m
r a
ttn
Metaphor g
// high-level -> details

Vertcal
Formatting
Vertca
// vertical density implies close association

l Densty
/**
* The class name of the reporter listener
*/
private String m_className;

/**
* The properties of the reporter listener
*/
private m_properties = new ArrayList();
Formatting
Vertca
// variables

l Dsatnce
// should be declared as close to their usage as possible

// instance variables
// should be at the top of the class
declared

// 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
Horzontal
private void measureLine(String line) {

Openness
lineCount++;
int lineSize = line.length();
totalChars += lineSize;
lineWidthHistogram.addLine(lineSize, lineCount);

and
recordWidestLine(lineSize);
}

public static double root2(int a, int b, int c) {

Densty
double determinant = determinant(a, b, c);
return (-b - Math.sqrt(determinant)) / (2*a);
}
Formatting
Horzonta
public class FitNesseExpediter implements ResponseSender

l
{
private Socket socket;
private InputStream input;
private OutputStream output;

Algnme
private Request request;
private Response response;
private FitNesseContext context;
protected long requestParsingTimeLimit;

nt
private long requestProgress;
private long requestParsingDeadline;
private boolean hasError;
...
}
Formatting
Horzonta
public class FitNesseExpediter implements ResponseSender

l
{
private Socket socket;
private InputStream input;
private OutputStream output;

Algnme
private Request request;
private Response response;
private FitNesseContext context;
protected long requestParsingTimeLimit;

nt
private long requestProgress;
private long requestParsingDeadline;
private boolean hasError;
...
}
Formatting
Breakng
public class CommentWidget extends TextWidget {

nIdentato
public static final String REGEXP =
"^#[^\r\n]*(?:(?:\r\n)|\n|\r)?";
public CommentWidget(String text) { super(text); } public
String render() throws Exception { return ""; }

n
}
Formatting
Breakng
public class CommentWidget extends TextWidget {

nIdentato
public static final String REGEXP =
"^#[^\r\n]*(?:(?:\r\n)|\n|\r)?";

public CommentWidget(String text) {

n
super(text);
}

public String render() throws Exception {


return "";
}
}
Formatting
Team
// every programmer has his own favorite formatting rules

Rules
// but if he works in a team
// then the team rules
Objects and Data Structures
Data Abstracton
Concrete Point

public class Point {


public double
x; public
double y;
}
Objects and Data Structures
Data Abstracton
Abstract Point

public interface Point {


double getX();
double getY();
void setCartesian(double x, double y);
double getR();
double getTheta();
void setPolar(double r, double theta);
}
Objects and Data Structures
Data Abstracton
Concrete Vehicle

public interface Vehicle {


double getFuelTankCapacityInGallons();
double getGallonsOfGasoline();
}
Objects and Data Structures
Data Abstracton
Abstract Vehicle

public interface Vehicle {


double getPercentFuelRemaining();
}
Objects and Data Structures
Data/Object Ant-Symmyert
// objects hide their data behind abstractions and
// expose functions that operate on that data

// data structure expose their data and


// have no meaningful functions
Objects and Data Structures
The Law of Demetr
final String outputDir = ctxt.getOptions()
.getScratchDir()
.getAbsolutePath();

Tran Wrecks
Options opts = ctxt.getOptions();
File scratchDir = opts.getScratchDir();
final String outputDir = scratchDir.getAbsolutePath();

final String outputDir = ctxt.options.scratchDir.absolutePath;


Error Handling
Preef r Exceptons
if (deletePage(page) == E_OK) {

to Returnng
if (registry.deleteReference(page.name) == E_OK) {
if (configKeys.deleteKey(page.name.makeKey()) == E_OK){
logger.log("page deleted");
} else {

Error Codes
logger.log("configKey not deleted");
}
} else {
logger.log("deleteReference from registry failed");
}
} else {
logger.log("delete failed");
return E_ERROR;
}
Error Handling
Preef r Exceptons
try {

to Returnng
deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey());
}

Error Codes
catch (Exception e)
{ logger.log(e.getMessage(
));
}
Error Handling
Extract
public void delete(Page page) {

Try/Catch Bolcks
try {
deletePageAndAllReferences(
page);
} catch (Exception e) {
logError(e);
}
}

private void deletePageAndAllReferences(Page page) throws Exception {


deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey());
}

private void logError(Exception e) {


logger.log(e.getMessage());
Error Handling
Eror Handlng Is
// functions should do one thing

One Thng
// error handing is one thing

// if the keyword try exists in a function


// it should be the very first word in the function and that
// there should be nothing after the catch/finally blocks
Error Handling
Defne the
try {

Nom
ral Flow
MealExpenses expenses = expenseReportDAO
.getMeals(employee.getID());
m_total += expenses.getTotal();
} catch(MealExpensesNotFound e) {
m_total += getMealPerDiem();
}
Error Handling
Defne the
MealExpenses expenses = expenseReportDAO

Nom
ral Flow
.getMeals(employee.getID());
m_total += expenses.getTotal();
Error Handling
Don’t
List<Employee> employees = getEmployees();

Return Null
if (employees != null) {
for(Employee e : employees) {
totalPay += e.getPay();
}
}
Error Handling
Don’t
List<Employee> employees = getEmployees();

Return Null
for(Employee e : employees) {
totalPay += e.getPay();
}

public List<Employee> getEmployees() {


if( .. there are no
employees .. )
return Collections.emptyList();
}
Error Handling
Don’t Pass
public double xProjection(Point p1, Point p2) {

Null
return (p2.x – p1.x) * 1.5;
}

public double xProjection(Point p1, Point p2) {


if (p1 == null || p2 == null) {
throw InvalidArgumentException ("Invalid
argument
for
MetricsCalculator.xPro
jection");
}
return (p2.x – p1.x) * 1.5;
}
Unit Tests
The Ther e
// first law

Laws of
// you may not write production code until
// you have written a failing unit test

// second law

TDD
// 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
Keepn
// test code is just as important as production code

gClean
TestsTests
Clean
// what makes a clean test? three things
// readability, readability, and readability
Unit Tests
One
// tests come to a single conclusion

Asert
// that is quick and easy to understand

Sngle Concept per


per
Test
Test
// the best rule is that you should
// minimize the number of asserts per concept and
// test just one concept per test function
Unit Tests
F.IR.ST..
// Fast
// Independent
// Repeatable
// Self-validating
// Timely
Classes
Cal ss
// public static constants

Organz
// private static variables
// private instance variables
// public functions
// private utilities called by a public function right after

ato n
Cal sses Should Be Small!
// the first rule is that they should be small
// the second rule is that they should be smaller than that
Classes
The Sngle
// a class or module should have one, and only one,

Responsblty
// reason to change

// SRP is one of the more important concept in OO design

Cohe
son
Prncple (SRP)
// maintaining cohesion results in many small classes
Emergence
Smple Desgn
Rule 1: Runs All
the TestsSmple
Desgn Rules
2: No
Questions?

You might also like