0% found this document useful (0 votes)
41 views82 pages

Clean Code March 2017

The document discusses principles of clean code including issues with bad code, naming conventions, functions, and comments. It provides examples of good and bad code to illustrate how to write clean, readable, and maintainable code.

Uploaded by

calabi mozart
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views82 pages

Clean Code March 2017

The document discusses principles of clean code including issues with bad code, naming conventions, functions, and comments. It provides examples of good and bad code to illustrate how to write clean, readable, and maintainable code.

Uploaded by

calabi mozart
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 82

Clean Code

Benedikus H Tjuatja
David Setyanugraha
Fakhri
Lutvianes Advendianto
Overview
● Issues

● Solution

● Conclusion

3
© GDP Labs 2017
Issues !

● Bad Code

● Great vs Bad Company

● Who is Responsible?

4
© GDP Labs 2017
Bad Code

● Technical debt:
the eventual consequences of poor software
architecture and software development within a code
base.
○ Rushed the product to the market
○ Had made a huge mess in the code
○ Added more features
○ The code got worse and worse

5
© GDP Labs 2017
Bad Code

● LeBlanc’s Law:
Later equals never
○ They never go back
to fix the bad code
● Sink projects, careers
and companies
● Example: netscape and
myspace

6
© GDP Labs 2017
Death Spiral:
The downward,
corkscrew-motion of a disabled
aircraft which is unrecoverably
headed for a crash

7
Great Company vs Bad Company

8
© GDP Labs 2017
Great Company vs Bad Company

9
© GDP Labs 2017
Great Company vs Bad Company

10
© GDP Labs 2017
Who is ● BOD?
● Management?
Responsible ● Program Manager?

for Bad Code? ●



Product Manager?
Unrealistic schedule?

Unprofessional Software Engineers.


It is your job to defend your code with equal passion.

11
© GDP Labs 2017
It is a crime if a
surgeon does not
“clean” his hands

12
For the things we have
to learn before we can
do them, we learn by
doing them - Aristotle

13
Solution
● Naming
● Function
● Comment
● Formatting
● Objects and Data Structures
● Error Handling
● Class
● Emergence

14
© GDP Labs 2017
Naming

“ The name of a variable, function, or


class, should answer all the big
questions. It should tell you why it


exists, what it does, and how it is used.

- Robert C. Martin

15
© GDP Labs 2017
Naming
public List<int[]> getThem() {
List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList)
if (x[0] == 4)
list1.add(x);
return list1;
}

Say that we’re working in a mine sweeper game.

16
© GDP Labs 2017
Naming

Use intention-revealing names


public List<int[]> getFlaggedCells() {
List<int[]> flaggedCells = new ArrayList<int[]>();
for (int[] cell : gameBoard)
if (cell[STATUS_VALUE] == FLAGGED)
flaggedCells.add(cell);
return flaggedCells;
}

17
© GDP Labs 2017
Naming

Use intention-revealing names


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

18
© GDP Labs 2017
Naming
Avoid misleading and unmeaningful distinctions

int a = l;
if (O == l)
a = O1;
else
l = 01;
MISLEADING

private void copyChars(char a1[], char a2[]) {


for (int i = 0; i < a1.length; i++) {
a2[i] = a1[i];
}
}
UNMEANINGFUL DISTINCTIONS

19
© GDP Labs 2017
Naming

public class DtaRcrd102 {


private Date genymdhms;
private Date modymdhms;
private final String pszqint = ”102”;
/* … */
} CAN YOU PRONOUNCE THEM?

20
© GDP Labs 2017
Naming

Use pronounceable names

public class Customer {


private Date generationTimestamp;
private Date modificationTimestamp;
private final String recordId = ”102”;
/* … */
}

21
© GDP Labs 2017
Naming

Classes and objects should be noun,


methods should be verb

public class Point {


private int x, y;
public Point(int x, int y) {...}
public int getX() {...}
public void setX(int x) {...}
public int getY() {...}
public void setY(int y) {...}
}

22
© GDP Labs 2017
Naming

public class Circle {


double radius;
String color;

public double getRadius() {...}


public String fetchColor() {...}
public double retrieveArea() {...}
}
GET OR FETCH OR RETRIEVE?

23
© GDP Labs 2017
Naming

Pick one word per concept

public class Circle {


double radius;
String color;

public double getRadius() {...}


public String getColor() {...}
public double getArea() {...}
}

24
© GDP Labs 2017
Naming
for (int i=0; i<34; i++) {
s += (t[i]*4)/5;
} NOT EASY TO SEARCH

if single-letter names and numeric constants are


used across body of text, they are not easy to locate

25
© GDP Labs 2017
Naming

Use searchable names


int realDaysPerIdealDay = 4;
const int WORK_DAYS_PER_WEEK = 5;
int sum = 0;
for (int i=0; i < NUMBER_OF_TASKS; i++) {
int realTaskDays = taskEstimate[i] * realDaysPerIdealDay;
int realTaskWeeks = (realdays / WORK_DAYS_PER_WEEK);
sum += realTaskWeeks;
}

26
© GDP Labs 2017
Function

“ The first rule of functions is that they


should be small. The second rule of
functions is that they should be
smaller than that.

- Robert C. Martin

27
© GDP Labs 2017
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();
} TOO BIG
28
Function
Do one thing
public static String renderPageWithSetupsAndTeardowns(
PageData pageData, boolean isSuite) throws Exception {
if (isTestPage(pageData))
includeSetupAndTeardownPages(pageData, isSuite);
return pageData.getHtml();
}

Function is doing more than “one thing” if you can


extract another function from it with a name that is not
merely a restatement

29
© GDP Labs 2017
Function

public boolean set(String attribute, String value);

if (set(”username”, ”unclebob”))

Is it asking whether the “username” attribute was


previously set to “unclebob”? Or is it asking whether the
“username” attribute was successfully set to “unclebob”?

30
© GDP Labs 2017
Function

Do something or answer something,


but not both

if (attributeExists(”username”)) {
setAttribute(”username”, ”unclebob”);
}

31
© GDP Labs 2017
Function

Transformational function should appear as the return


value

void transform(StringBuffer out)

These implementation simply returns the input argument

StringBuffer transform(StringBuffer in)

32
© GDP Labs 2017
Function
Avoid too many function parameters

Car createCar(float wheelDiameter, float


wheelColor, float wheelMaterial, float
wheelManufacturer, String engineType, String
engineColor, String engineManufacturer);

Too many parameters will make function hard to be


understood and maintained.

Car createCar(Wheel wheel, Engine engine);

33
© GDP Labs 2017
Comments

“ Good code is its own best documentation.


As you’re about to add a comment, ask
yourself, ‘How can I improve the code so


that this comment isn’t needed?'

- Steve McConnell

34
© GDP Labs 2017
Comments
Redundant Comments
The comment is not more informative than the code
// 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(
"MockResponseSender could not be closed");
}
}
35
© GDP Labs 2017
Comments
Noise Comments
Only restate the obvious and provide no new information
/**
* Returns the day of the month.
* @return the day of the month.
*/
public int getDayOfMonth() {
return dayOfMonth;
}

36
© GDP Labs 2017
Comments

Explain yourself in code


// Check to see if the employee is eligible for full
benefits
if ((employee.flags & HOURLY_FLAG) &&
(employee.age > 65))

if (employee.isEligibleForFullBenefits())

37
© GDP Labs 2017
Comments
// format matched kk:mm:ss EEE, MMM dd, yyyy
Pattern timeMatcher = Pattern.compile("\\d*:\\d*:\\d* \\w*,
\\w* \\d*, \\d*");
INFORMATIVE

public void writeJournal(Diary diary) {


for (Thread thread : threadList) {
thread.run(() -> {
// Prevent original object to be modified
Diary copyOfDiary = new Diary(diary);
write(copyOfDiary);
});
}
} EXPLANATION OF INTENT
38
© GDP Labs 2017
Comments
public static SimpleDateFormat makeStandardHttpDateFormat() {
//SimpleDateFormat is not thread safe,
//so we need to create each instance independently.
SimpleDateFormat df = new SimpleDateFormat(
”EEE, dd MMM yyyy HH:mm:ss z”);
df.setTimeZone(TimeZone.getTimeZone(”GMT”));
return df;
}
WARNING OF CONSEQUENCES

39
© GDP Labs 2017
Formatting

40
© GDP Labs 2017
Formatting
Variables
Should be declared as close to their usage as possible

public void paySalary(Employee employee) {


float bonus;
float totalSalary;
bonus = calculateBonus(employee.getSalary());
totalSalary = bonus + employee.getSalary();
sendMoney(employee, totalSalary);
}

41
© GDP Labs 2017
Formatting
Variables
Should be declared as close to their usage as possible

public void paySalary(Employee employee) {


float bonus;
bonus = calculateBonus(employee.getSalary());
float totalSalary;
totalSalary = bonus + employee.getSalary();
sendMoney(employee, totalSalary);
}

42
© GDP Labs 2017
Formatting
Instance Variables
Should be declared at the top of the class

public class Employee {


private String name;
private String id;
private float salary;

public void getName() { … }


}

43
© GDP Labs 2017
Formatting
Dependent Functions
Should be vertically close, and the caller should be above
the called
public void paySalary() {
calculateBonus(salary);
}

private float calculateBonus(float salary) {


return (salary / 10);
}

44
© GDP Labs 2017
Formatting
Conceptual Affinity
Certain bits of code want to be near other bits
public class Employee {
public void payTax() {
}
public void payOverdueTax(Date date) {
}
public void increaseSalary() {
}
public void decreaseSalary() {
}
}

45
© GDP Labs 2017
Formatting
Space
public float volume (float length,float width,float height) {
// code
}

public float volume(float length, float width, float height) {


// code
}

46
© GDP Labs 2017
Formatting
Horizontal Alignment

public class WebService {


private Request request;
private Response response;
private FitnesseContext context;
protected long requestTimeLimit;
}
DIFFICULT TO MAINTAIN

47
© GDP Labs 2017
Formatting
Horizontal Alignment

public class WebService {


private Request request;
private Response response;
private FitnesseContext context;
protected long requestTimeLimit;
}

48
© GDP Labs 2017
Formatting
Indentation

public String functionName() {return "";}

public String functionName() {


return "";
}

49
© GDP Labs 2017
Objects and Data
Structures

50
© GDP Labs 2017
Objects and Data Structures
Data structures expose data and have no behavior
Data structures make it easy to add functions without the
need to modify existing structures.

public class Point {


public double x;
public double y;
}

51
© GDP Labs 2017
Objects and Data Structures
Object expose behavior and hide data
Objects make it easy to add classes without the need to
modify existing functions.

public class Vehicle {


public getFuelCapacity() {...}
public getPercentageFuelRemaining() {...}
}

52
© GDP Labs 2017
Objects and Data Structures
Law of Demeter
Given method f of class C, f should only call methods of:
● C
● An Object created by f
● An Object passed as an argument to f
● An instance variable of C

53
© GDP Labs 2017
Objects and Data Structures
Law of Demeter
Given method f of class C, f should only call methods of:
● C

public class Vehicle {


public getFuelCapacity() {...}

public getPercentageFuelRemaining() {
return (fuel / getFuelCapacity() * 100);
}
}

54
© GDP Labs 2017
Objects and Data Structures
Law of Demeter
Given method f of class C, f should only call methods of:
● An Object created by f

public void registryEmployee() {


Employee newEmployee = new Employee();
registry.createEmplyeeId(newEmployee);
employeeIdList.add(newEmployee.getId());
}

55
© GDP Labs 2017
Objects and Data Structures
Law of Demeter
Given method f of class C, f should only call methods of:
● An Object passed as an argument to f

public void calculateEmployeeBonus(Employee employee) {


return (employee.getSalary() / 10);
}

56
© GDP Labs 2017
Objects and Data Structures
Law of Demeter
Given method f of class C, f should only call methods of:
● An instance variable of C

public class Car {


private Engine engine;

public String getCarFuelType() {


return engine.getFuelType();
}
}

57
© GDP Labs 2017
Error Handling

58
© GDP Labs 2017
Error Handling
Prefer exceptions to return error code
if (deletePage(page) == E_OK) {
if (registry.delete(page.reference) == E_OK) {
logger.log(“page deleted”);
} else {
logger.log(“delete registry failed”);
}
} else {
logger.log(“delete failed”);
}

59
© GDP Labs 2017
Error Handling
Prefer exceptions to return error code

try {
deletePage(page);
registry.delete(page.reference);
} catch (Exception e) {
logger.log(e.getMessage());
}

60
© GDP Labs 2017
Error Handling

● Functions should do one thing and error handling is


one thing
○ Implement the normal flow of the function

● Don’t return NULL


○ So other function doesn’t need to implement error
handling

● Don’t pass NULL


○ So other function doesn’t need to implement error
handling
61
© GDP Labs 2017
Class

62
© GDP Labs 2017
Class
Class Organization
Declare the constants, variables, and methods in this order:
public class TimeCalculator {
public static final int TIME = 25; // public static constant
public static int DURATION = 25; // private static variables
private int now; // private instance variables
public int addTime(int time) { // public functions

configTime = getConfigTime()

}
private int getConfigTime() { … } // private utilities
}

63
© GDP Labs 2017
Class

Classes should be small!

● The first rule is that they should be small


● The second rule is that they should be smaller than that

Single Responsibility Principle (SRP)

● A class or module should have one, and only one,


reason to change
● SRP is one of the more important concept in OO design

64
© GDP Labs 2017
Class
Refactored:

public class TimeCalculator {



public int addTime(int time) { … }

}

public class UserConfiguration {



public int getConfigTime() { … }

}

65
© GDP Labs 2017
Class
Cohesion

● Classes should have a small number of instance


variables
● The more variables (or class modules) a method
manipulates the more cohesive that method is to its
class.
● A class in which each variable is used by each
method is maximally cohesive.
● Maintaining cohesion results in many small classes

66
© GDP Labs 2017
public class CustomStack {
private int topOfStack = 0;
private int duration = 100;
List<Integer> elements = new LinkedList<Integer>();
public int size() { … }
public void push(int element) { … }
public int pop() throws PoppedWhenEmpty { … }

public void sleep() {


TimeUnit.SECONDS.sleep(duration);
}
public void log() {

logger.log(Level.WARNING, ”This is a warning!”);

}

} LOW COHESION

67
© GDP Labs 2017
public class Stack {
private int topOfStack = 0;
List<Integer> elements = new LinkedList<Integer>();
public int size() {
return topOfStack;
}
public void push(int element) {
topOfStack++;
elements.add(element);
}
public int pop() throws PoppedWhenEmpty {
if (topOfStack == 0)
throw new PoppedWhenEmpty();
int element = elements.get(--topOfStack);
elements.remove(topOfStack);
return element;
}
} HIGH COHESION

68
© GDP Labs 2017
Emergence

69
© GDP Labs 2017
Emergence

● Runs all the tests. To make it easy, make sure:


○ Low coupling
○ SRP
● Contains no duplication (Refactoring)

● Expresses the intent of the programmer (Refactoring)


○ Easy to read and understand
● Minimizes the number of classes and methods
(Refactoring)
○ But don’t take it too far

70
© GDP Labs 2017
public void scaleToOneDimension(…) {

RenderedOp newImage = ImageUtilities.getScaledImage(
image, scalingFactor, scalingFactor);
image.dispose();
System.gc();
image = newImage;
}
public synchronized void rotate(int degrees) {
RenderedOp newImage = ImageUtilities.getRotatedImage(
image, degrees);
image.dispose();
System.gc();
image = newImage;
} DUPLICATION

71
© GDP Labs 2017
public void scaleToOneDimension(…) {

replaceImage(ImageUtilities.getScaledImage(
image, scalingFactor, scalingFactor));
}
public synchronized void rotate(int degrees) {
replaceImage(ImageUtilities.getRotatedImage(
image, degrees));
}
private void replaceImage(RenderedOp newImage) {
image.dispose();
System.gc();
image = newImage;
}
DUPLICATION REFACTORED

72
© GDP Labs 2017
Give a man a fish and you feed
him for a day; teach a man to fish
and you feed him for a lifetime.
- Anne Thackeray Ritchie

73
Conclusion
1. Practice
Is there a set of simple practices that
can replace experience? Clearly not
2. Beware of Bad Code or Code Smell
3. Refactor

74
© GDP Labs 2017
Clean Code:
A Handbook of Agile
Software Craftsmanship

Robert C. Martin
©2009 | Prentice Hall

75
© GDP Labs 2017
A programmer who writes clean
code is an artist who can take a
blank screen through a series of
transformations until it is an
elegantly coded system

76
Thank You
Q&A
speakerdeck.com/gdplabs

77
We Are Hiring!
[email protected]

78
Cracking the
Coding Interview:
189 Programming
Questions and Solutions

Gayle Laakmann McDowell


©2015 | CareerCup

79
© GDP Labs 2017
Extras
● Code Smells

● OO Design Principles

80
© GDP Labs 2017
Code Smells

● Large class ● Duplicated code


● Feature envy ● Too many parameters
● Inappropriate intimacy ● Long method
● Refused bequest ● Excessive return of data
● Lazy class ● Excessively long
● Excessive use of literals identifiers
● Cyclomatic complexity ● Excessively short
● Data clump identifiers
● Orphan variable or
constant class

81
© GDP Labs 2017
OO Design Principles: S.O.L.I.D

S Single-responsibility principle

O Open-closed principle

L Liskov substitution principle

I Interface segregation principle

D Dependency Inversion Principle

82
© GDP Labs 2017

You might also like