Kuliah umum OOP,
Computer Science IPB
Ifnu, 28 Maret 2017
Who am I?
• Ifnu Bima
• Ilmu Komputer IPB, 38
• Join blibli in 2012
• Was working for Deustche Bank Singapore
• Employee no 69
• Engineers no ~13
• Development Manager
– blibli.com Web UI
– Mobile Apps : Android, iOS, Windows Phone
– Content Management System
– Search
– Product Discovery : Wishlist, Product Review
Survey
Ingin bekerja sebagai
Software Developer?
Survey
Ingin bekerja sebagai
Software Developer seumur
hidup?
Clean Code Agenda
• Code Quality
– External quality
– Internal quality
• Clean Code
– Meaningful Names
– High quality function
– Comments
– Unit Test
Code quality metrics
Robert C. Martin (Uncle Bob) Book
External Quality
• Easy to use Application
• Zero bug
• Fast
• Scalable
Internal Code Quality
• Readable
• Mantainable
• Testable
• Elegant
Why do we care?
• There’s no such thing as write-once code
• Code written, read & modified hundreds times
Why do we care?
• Bug Fixes
• Business Changes
• Enhancements
• New Functionality
What Prevents Clean Code?
• Ignorance
• Stubbornness
• Short-Timer Syndrome
• Arrogance
• Job Security
• Scheduling, Deadline Driven Development
What Prevents Clean Code?
Number one reason:
“I’ll clean it up later.”
“Ahh, gampang, ntar
aja, yang penting
beres dulu”
The Truth about Clean Code
• Clean Code saves time.
• We can’t take a short-term view of software.
• We need to look at the lifespan of the
application.
How Do You Write Clean Code?
Rule of Thumb:
Imagine that the developer who
comes after you is a homicidal
maniac who knows where you
live.
-Unknown
The next developer
The next
developer
that mantain
code you
write
Better motivation
Clean Code : Maningful Names
Clean Code : Meaningful Names
• Intention-Revealing Names
• Self Explained Names
• theList, x1, y1, i, j, k, index
– Not very good
• productList, indexOfProductList
– A bit better
Intention-Revealing Names : Bad
List<int[]> getThem() {
List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList) {
if (x[0] == 4) {
list1.add(x);
}
}
return list1;
}
Intention-Revealing Names : Good
List<Cell> getFlaggedCells() {
List<Cell> flaggedCells = new ArrayList<Cell>();
for (Cell cell : gameBoard) {
if (cell.isFlagged()) {
flaggedCells.add(cell);
}
}
return flaggedCells;
}
Clean Code : Meaningful Names
• Avoid Disinformation
int a = l;
if (O == l) a = O1;
else l = 01;
• Make Meaningful Distinctions
public static void copyChars(char a1[], char a2[]) {
for (int i = 0; i < a1.length; i++) {
a2[i] = a1[i];
}
}
Meaningful Names
• Use Pronounceable Names : Bad
class DtaRcrd102 {
private Date genymdhms;
private Date modymdhms;
private final String pszqint = "102";
/* ... */
}
• Use Pronounceable Names : Good
class Customer {
private Date generationTimestamp;
private Date modificationTimestamp;
private final String recordId = "102";
/* ... */ };
}
Meaningful Names
• Use Searchable Names : Bad
for (int j = 0; j < 34; j++) {
s += (t[j] * 4) / 5;
}
• Use Searchable Names : Good
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
• Avoid mental mapping : Bad
for (i = 0; i < arr.length; i++) {
for (j = i; j < arr.length; j++) {
//bubble sort
}
}
• Dont try to be funny : Bad
public void canggih() {
//TODO
}
Meaningful Names
• Code Convention
• Class should be noun
• Method should be verb
High Quality Function
• Small!
• rules of functions:
1. should be small
2. should be smaller than that
• < 150 characters per line
• < 20 lines
• Do One Thing
1. FUNCTIONS SHOULD DO ONE THING. THEY
SHOULD DO IT WELL.
2. THEY SHOULD DO IT ONLY.
High Quality Function
• DRY : Dont repeat yourself
– Copy paste code everywhere is root of all evil in
software
Comments
• Do Not Make Up for Bad Code
– don’t comment bad code, rewrite it!
//edan ini kode siapa yang bikin!!
for (int j = 0; j < 34; j++) {
s += (t[j] * 4) / 5;
}
• 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()) {
}
}
Comments (good)
• Legal Comments
// Copyright (C) 2017 by blibli.com. All rights reserved.
// Released under the terms of the GNU General Public License
// version 2 or later
• Informative Comments
// Returns an instance of the Responder being tested.
protected abstract Responder responderInstance();
// format matched kk:mm:ss EEE, MMM dd, yyyy
Pattern timeMatcher = Pattern.compile(
"d*:d*:d* w*, w* d*, d*");
Comments (good)
• Explanation 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();
}
Comments (good)
• Clarification
assertTrue(a.compareTo(b) == -1); // a < b
assertTrue(b.compareTo(a) == 1); // b > a
• Warning 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;
}
Comments (good)
• TODO Comments
//TODO - MdM these are not needed
//We expect this to go away when we do the checkout model
• Amplification
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()));
Comments (bad)
• Mumbling
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 Comments
/** * 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)
• Mandated Comments
/**
* @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.title = title;
cd.author = author;
cd.tracks = tracks;
cd.duration = durationInMinutes;
}
Comments (bad)
• Journal Comments
/** 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)
• Noise Comments
/**
* 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() {
return dayOfMonth;
}
Comments (bad)
• Scary Noise
/**
* The name.
*/
private String name;
/**
* The version.
*/
private String version;
/**
* The licenceName.
*/
private String licenceName;
/**
* The version.
*/
private String info;
Comments (bad)
• Position Markers
// Actions //////////////////////////////////
//End of Actions ///////////////////////////
Comments (bad)
• All sort of funny comments and stupid code
// For the sins I am about to commit, may James Gosling forgive me
// If this code works, it was written by Ifnu.
// If not, I don’t know who wrote it
Exception up = new Exception(“Something is really wrong.”);
throw up; //ha ha
//When I wrote this, only God and I understood what I was doing
//Now, God only knows
// I dedicate all this code, all my work, to my wife, Dian, who will
// have to support me and our two children and the cupang once it gets
// released into the public.
• All sort of funny comment and stupid code
//Dear future me. Please forgive me.
//I can’t even begin to express how sorry I am.
// Magic. Do not touch.
return 1; # returns 1
/////////////////////////////////////// this is a well
commented line
// I am not sure if we need this, but too scared to
delete.
// I am not responsible of this code.
// They made me write it, against my will.
// If I from the future read this I’ll back in time and
kill myself.
Unit Test
• Mengetes logic aplikasi secara otomatis dan
berulang-ulang
• Menghindarkan developer mengetes dengan
manual menggunkan mata
• Menghindari “regression bug”: mengubah
satu kode membuat kode lain jadi error
Unit Test
• Membuat developer percaya diri untuk
melakukan refactoring karena ada Unit Testing
• Digunakan secara luas sebagai ukuran internal
code quality
• JUnit secara de facto diterima sebagai tools
untuk Unit Testing di Java
Unit Test
Demo
Unit Test
• Buat kode untuk melakukan grading dari nilai
0-100 menjadi grade A-D
Agile, Clean Code, Refactor, Automation Test
We Are Hiring!!
THANK YOU

Clean code

  • 1.
    Kuliah umum OOP, ComputerScience IPB Ifnu, 28 Maret 2017
  • 2.
    Who am I? •Ifnu Bima • Ilmu Komputer IPB, 38 • Join blibli in 2012 • Was working for Deustche Bank Singapore • Employee no 69 • Engineers no ~13 • Development Manager – blibli.com Web UI – Mobile Apps : Android, iOS, Windows Phone – Content Management System – Search – Product Discovery : Wishlist, Product Review
  • 3.
  • 4.
  • 5.
    Clean Code Agenda •Code Quality – External quality – Internal quality • Clean Code – Meaningful Names – High quality function – Comments – Unit Test
  • 6.
  • 7.
    Robert C. Martin(Uncle Bob) Book
  • 8.
    External Quality • Easyto use Application • Zero bug • Fast • Scalable
  • 9.
    Internal Code Quality •Readable • Mantainable • Testable • Elegant
  • 10.
    Why do wecare? • There’s no such thing as write-once code • Code written, read & modified hundreds times
  • 11.
    Why do wecare? • Bug Fixes • Business Changes • Enhancements • New Functionality
  • 12.
    What Prevents CleanCode? • Ignorance • Stubbornness • Short-Timer Syndrome • Arrogance • Job Security • Scheduling, Deadline Driven Development
  • 13.
    What Prevents CleanCode? Number one reason: “I’ll clean it up later.” “Ahh, gampang, ntar aja, yang penting beres dulu”
  • 14.
    The Truth aboutClean Code • Clean Code saves time. • We can’t take a short-term view of software. • We need to look at the lifespan of the application.
  • 15.
    How Do YouWrite Clean Code? Rule of Thumb: Imagine that the developer who comes after you is a homicidal maniac who knows where you live. -Unknown
  • 16.
    The next developer Thenext developer that mantain code you write
  • 17.
  • 18.
    Clean Code :Maningful Names
  • 19.
    Clean Code :Meaningful Names • Intention-Revealing Names • Self Explained Names • theList, x1, y1, i, j, k, index – Not very good • productList, indexOfProductList – A bit better
  • 20.
    Intention-Revealing Names :Bad List<int[]> getThem() { List<int[]> list1 = new ArrayList<int[]>(); for (int[] x : theList) { if (x[0] == 4) { list1.add(x); } } return list1; }
  • 21.
    Intention-Revealing Names :Good List<Cell> getFlaggedCells() { List<Cell> flaggedCells = new ArrayList<Cell>(); for (Cell cell : gameBoard) { if (cell.isFlagged()) { flaggedCells.add(cell); } } return flaggedCells; }
  • 22.
    Clean Code :Meaningful Names • Avoid Disinformation int a = l; if (O == l) a = O1; else l = 01; • Make Meaningful Distinctions public static void copyChars(char a1[], char a2[]) { for (int i = 0; i < a1.length; i++) { a2[i] = a1[i]; } }
  • 23.
    Meaningful Names • UsePronounceable Names : Bad class DtaRcrd102 { private Date genymdhms; private Date modymdhms; private final String pszqint = "102"; /* ... */ } • Use Pronounceable Names : Good class Customer { private Date generationTimestamp; private Date modificationTimestamp; private final String recordId = "102"; /* ... */ }; }
  • 24.
    Meaningful Names • UseSearchable Names : Bad for (int j = 0; j < 34; j++) { s += (t[j] * 4) / 5; } • Use Searchable Names : Good 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; }
  • 25.
    Meaningful Names • Avoidmental mapping : Bad for (i = 0; i < arr.length; i++) { for (j = i; j < arr.length; j++) { //bubble sort } } • Dont try to be funny : Bad public void canggih() { //TODO }
  • 26.
    Meaningful Names • CodeConvention • Class should be noun • Method should be verb
  • 27.
    High Quality Function •Small! • rules of functions: 1. should be small 2. should be smaller than that • < 150 characters per line • < 20 lines • Do One Thing 1. FUNCTIONS SHOULD DO ONE THING. THEY SHOULD DO IT WELL. 2. THEY SHOULD DO IT ONLY.
  • 28.
    High Quality Function •DRY : Dont repeat yourself – Copy paste code everywhere is root of all evil in software
  • 29.
    Comments • Do NotMake Up for Bad Code – don’t comment bad code, rewrite it! //edan ini kode siapa yang bikin!! for (int j = 0; j < 34; j++) { s += (t[j] * 4) / 5; } • 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()) { } }
  • 30.
    Comments (good) • LegalComments // Copyright (C) 2017 by blibli.com. All rights reserved. // Released under the terms of the GNU General Public License // version 2 or later • Informative Comments // Returns an instance of the Responder being tested. protected abstract Responder responderInstance(); // format matched kk:mm:ss EEE, MMM dd, yyyy Pattern timeMatcher = Pattern.compile( "d*:d*:d* w*, w* d*, d*");
  • 31.
    Comments (good) • Explanationof 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(); }
  • 32.
    Comments (good) • Clarification assertTrue(a.compareTo(b)== -1); // a < b assertTrue(b.compareTo(a) == 1); // b > a • Warning 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; }
  • 33.
    Comments (good) • TODOComments //TODO - MdM these are not needed //We expect this to go away when we do the checkout model • Amplification 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()));
  • 34.
    Comments (bad) • Mumbling 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 }
  • 35.
    Comments (bad) • RedundantComments /** * 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();
  • 36.
    Comments (bad) • MandatedComments /** * @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.title = title; cd.author = author; cd.tracks = tracks; cd.duration = durationInMinutes; }
  • 37.
    Comments (bad) • JournalComments /** 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); */
  • 38.
    Comments (bad) • NoiseComments /** * 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() { return dayOfMonth; }
  • 39.
    Comments (bad) • ScaryNoise /** * The name. */ private String name; /** * The version. */ private String version; /** * The licenceName. */ private String licenceName; /** * The version. */ private String info;
  • 40.
    Comments (bad) • PositionMarkers // Actions ////////////////////////////////// //End of Actions ///////////////////////////
  • 41.
    Comments (bad) • Allsort of funny comments and stupid code // For the sins I am about to commit, may James Gosling forgive me // If this code works, it was written by Ifnu. // If not, I don’t know who wrote it Exception up = new Exception(“Something is really wrong.”); throw up; //ha ha //When I wrote this, only God and I understood what I was doing //Now, God only knows // I dedicate all this code, all my work, to my wife, Dian, who will // have to support me and our two children and the cupang once it gets // released into the public.
  • 42.
    • All sortof funny comment and stupid code //Dear future me. Please forgive me. //I can’t even begin to express how sorry I am. // Magic. Do not touch. return 1; # returns 1 /////////////////////////////////////// this is a well commented line // I am not sure if we need this, but too scared to delete. // I am not responsible of this code. // They made me write it, against my will. // If I from the future read this I’ll back in time and kill myself.
  • 43.
    Unit Test • Mengeteslogic aplikasi secara otomatis dan berulang-ulang • Menghindarkan developer mengetes dengan manual menggunkan mata • Menghindari “regression bug”: mengubah satu kode membuat kode lain jadi error
  • 44.
    Unit Test • Membuatdeveloper percaya diri untuk melakukan refactoring karena ada Unit Testing • Digunakan secara luas sebagai ukuran internal code quality • JUnit secara de facto diterima sebagai tools untuk Unit Testing di Java
  • 45.
  • 46.
    Unit Test • Buatkode untuk melakukan grading dari nilai 0-100 menjadi grade A-D
  • 47.
    Agile, Clean Code,Refactor, Automation Test
  • 48.