Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Clean Code

Clean Code

Oursky Limited

March 11, 2013
Tweet

More Decks by Oursky Limited

Other Decks in Programming

Transcript

  1. Clean Code Title: Clean Code: A Handbook of Agile Software

    Craftsmanship Author: Robert C. Martin (Uncle Bob) Monday, 11 March, 13
  2. Why Clean Code? 0 10 20 30 40 50 60

    70 80 90 100 0 500 1000 2000 2500 3000 3500 4000 Productivity Ratio vs Time Monday, 11 March, 13
  3. Smart vs Professional Smart Great Coding Skill Write advanced code

    String r; / / lowercase url Monday, 11 March, 13
  4. Smart vs Professional Smart Great Coding Skill Write advanced code

    String r; / / lowercase url Professional Readable code Maintainable code String lowercaseUrl; Monday, 11 March, 13
  5. Name Choose your names thoughtfully If a name requires a

    comment, the name does not reveal its intent Monday, 11 March, 13
  6. Name Choose your names thoughtfully If a name requires a

    comment, the name does not reveal its intent int d; What does it mean? Days? Diameter? Monday, 11 March, 13
  7. Name Choose your names thoughtfully If a name requires a

    comment, the name does not reveal its intent int d; What does it mean? Days? Diameter? int d; / /elapsed time in days Is this any better? Monday, 11 March, 13
  8. Name Choose your names thoughtfully If a name requires a

    comment, the name does not reveal its intent int d; What does it mean? Days? Diameter? int elapsedTimeInDays; What about this? int d; / /elapsed time in days Is this any better? Monday, 11 March, 13
  9. Name Choose part of speech well method / function =>

    verb class / object => noun def authentication # ... end def authenticate # ... end Monday, 11 March, 13
  10. Name use Pronounceable Names class DtaRcrd102 { private Date genymdhms;

    private Date modymdhms; private final String pszqint = “102”; } class Customer { private Date generationTimestamp; private Date modificationTimestamp; private final String recordId = “102”; } Monday, 11 March, 13
  11. Names... Avoid encodings public class Part { private String mName;

    void setName(String name) { mName = name; } } public class Part { private String name; void setName(String name) { this.name = name; } } Hungarian notation bBusy: boolean chInitial: char cApples: count of items fpPrice: floating-point dbPi: double (Systems) pFoo: pointer Monday, 11 March, 13
  12. Discussion: Android vs IOS ListView listView = new ListView(context); listView.setAdapter(anAdapter);

    UITableView tableView = [[UITableView alloc] initWithFrame:aFrame style:UITableViewStylePlain]; tableView.datasource = aDataSource; Android: IOS: Which one is better? Monday, 11 March, 13
  13. Adapter The adapter pattern is adapting between classes and objects,

    like a bridge between two objects. e.g. SimpleCursorAdapter ArrayAdapter Monday, 11 March, 13
  14. Adapter Title: Design Patterns: Elements of Reusable Object-Oriented Software Author:

    John Vlissides Richard Helm Ralph Johnson Erich Gamma Monday, 11 March, 13
  15. Use design pattern as name Use Solution Domain Names, e.g.

    AccountVisitor JobQueue LabelObserver SimpleCursorAdapter Monday, 11 March, 13
  16. Deceptive API testCharge() { CreditCard cc; cc = new CreditCard(“1234567890121234”);

    cc.charge(100); } java.lang.NullPointerException at talk.CreditCard.charge(CreditCard.java:49) Monday, 11 March, 13
  17. Deceptive API testCharge() { CreditCardProcessor.init(...); CreditCard cc; cc = new

    CreditCard(“1234567890121234”); cc.charge(100); } java.lang.NullPointerException at talk.CreditCardProcessor.init (CreditCardProcessor.java:146) Monday, 11 March, 13
  18. Deceptive API testCharge() { OffineQueue.start(); CreditCardProcessor.init(...); CreditCard cc; cc =

    new CreditCard(“1234567890121234”); cc.charge(100); } java.lang.NullPointerException at talk.OfflineQueue.start (OfflineQueue.java:16) Monday, 11 March, 13
  19. Deceptive API testCharge() { Database.connect(...); OffineQueue.start(); CreditCardProcessor.init(...); CreditCard cc; cc

    = new CreditCard(“1234567890121234”); cc.charge(100); } CreditCard API lies It pretends to not need the CreditCardProcessor The API doesn’t tell the exact order of the initialization Monday, 11 March, 13
  20. Deceptive API testCharge() { database = new Database(...); queue =

    new OfflineQueue(database); creditCardProcessor = new CreditCardProcessor(queue); CreditCard cc; cc = new CreditCard(“1234567890121234”, creditCardProcessor); cc.charge(100); } Dependency injection enforces the order of initialization at compile time. Monday, 11 March, 13
  21. Discussion: Object passing in Android? How to pass objects to

    another Activity? Monday, 11 March, 13
  22. Comment Comment doesn’t make your code becomes good code /

    /* no Comments */ / Monday, 11 March, 13
  23. Good Comments Informative Comments // format matched kk:mm:ss EEE, MMM

    dd, yyyy Pattern timePattern = Pattern.compile( “\\d*:\\d*:\\d* \\w*, \\w* \\d*, \\d*”); Todo Comments /* TODO: All calls to getPage should actually come here, and be relative to the current page, not the parent page. It was a gross error to have the whole wiki know that references were relative to the parent instead of the page. */ Pubic API documentation Monday, 11 March, 13
  24. Bad Comments Redundant Comments /** * The processor delay for

    this component. */ protected int backgroundProcessorDelay = -1; /** * The container event listeners for this Container. */ protected ArrayList listeners = new ArrayList(); Monday, 11 March, 13
  25. Bad Comments Attribution Comments /* Added by Gary */ Big

    Banner Comments // ********************** // * Instance Variables * // ********************* private int myVariable; // *********************** // * Default Constructor * // *********************** public MyClass() {} Monday, 11 March, 13
  26. Mumbling /* For bug FS-13005, we had to add this.

    The bug was that the Now Playing screen was somehow being launched, in that viewDidAppear was being called, but the view was not being shown on the screen. The Now Playing screen then when on to do all it's stuff and the user was left looking at an incomplete Mode screen. So the "fix" is to kill off any residual Now Playing screen that is under the Mode tab whenever we start a new connection to a radio. */ What is FS-13005? Sorry! I have no idea what you are talking about. Monday, 11 March, 13
  27. Horizontal Alignment @interface Tape : NSObject { ! NSString *_brushName;

    ! NSString *_headImageNamed; ! NSString *_bodyImageNamed; ! NSString *_tailImageNamed; ! CGFloat _opacity; ! BOOL! _includeShadow; ! NSString *_text; ! NSString *_fontName; ! CGFloat! _fontSize; ! NSString *_colorHex; ! NSDictionary *_all; } @interface Tape : NSObject { ! NSString *_brushName; ! NSString *_headImageNamed; ! NSString *_bodyImageNamed; ! NSString *_tailImageNamed; ! CGFloat _opacity; ! BOOL! _includeShadow; ! NSString *_text; ! NSString *_fontName; ! CGFloat! _fontSize; ! NSString *_colorHex; ! NSDictionary *_all; } Monday, 11 March, 13
  28. Function should be Small does one thing the ideal number

    of arguments for a function is .... 0 the less arguments, the better try not to more than 3 arguments Monday, 11 March, 13
  29. Function No Side effects // do something or answer something,

    but not both public boolean set(String attribute, String value); if (attributeExists(“username”)) { setAttribute(“username”, “Ben”); } Monday, 11 March, 13
  30. Class Avoid God Class In OO, God Class is a

    class that does lots of things example: UITableViewController Monday, 11 March, 13
  31. Data Structure and Object public class Square { public Point

    topLeft; public double side; } public class Geometry { public double calculateArea(Object shape) throws noSuchShapeException { if (shape instanceof Square) { Square square = (Square)shape; return square.side * square.side; } else if (shape instanceof Rectangle) { Rectangle rectangle = (Rectangle)shape; return rectangle.height * rectangle.width; } throw new NoSuchShapeException(); } } public class Rectangle { public Point topLeft; public double height; public double width; } Monday, 11 March, 13
  32. Data Structure and Object public class Square implements Shape {

    public Point topLeft; public double side; public double area() { return side*side; } } public class Rectangle implements Shape{ public Point topLeft; public double height; public double width; public double area() { return height * width; } } Monday, 11 March, 13
  33. Data Structure and Object Procedural Code (code using data structure)

    Pros: easy to add new functions without changing existing data structure Cons: hard to add new data structure all the functions must change OO code Pros: easy to add new classes without changing existing function Cons: hard to a new function as all classes must change Monday, 11 March, 13
  34. Data Structure and Object Procedural Code (code using data structure)

    Pros: easy to add new functions without changing existing data structure Cons: hard to add new data structure all the functions must change OO code Pros: easy to add new classes without changing existing function Cons: hard to a new function as all classes must change Avoid Hybrids Monday, 11 March, 13
  35. Error Handling Prefer exceptions to returning error codes if (deletePage(page)

    == E_OK) { 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; } Monday, 11 March, 13
  36. Error Handling prefer exceptions to returning error codes try {

    deletePage(page); registry.deleteReference(page.name); configKeys.deleteKey(page.name.makeKey()); } catch (Exception e) { logger.log(e.getMessage()); } easier to find the normal path avoid nested conditions Monday, 11 March, 13
  37. Error Handling Don’t Return Null List<Employee> employees = getEmployees(); if

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

    (Employee e : employees) { totalPay += e.getPay(); } public List<Employee> getEmployees() { if (/* there are no employees */) { return Collections.emptyList(); } } Monday, 11 March, 13
  39. SOLID Single Responsibility Principle Open Closed Principle Liskov Substitution Principle

    Interface Segregation Principle Dependency inversion Principle Monday, 11 March, 13
  40. Test - a real scenario ... client server workers s3

    1. upload a video 2. store in s3 3. start worker and send request to worker 4. dedicated worker pulls the file from s3 and do transcoding Monday, 11 March, 13
  41. Test Remove FEAR during Development You know you break something

    during testing. For example: Rugby - ~178 tests Refer to Ben’s presentation https:/ /speakerdeck.com/oursky/testing Monday, 11 March, 13
  42. Refactor Title:Refactoring: Improving the Design of Existing Code Author: Martin

    Fowler Kent Beck John Brant William Opdyke Don Roberts Monday, 11 March, 13
  43. Familiar With your Tools try to familiar with your tools

    before coding, don’t create messy stuffs by your first impression do testing before adopting to the real code read the API, doc and Google ask others ... Monday, 11 March, 13
  44. Quiz (javascript) The expected output of the following javascript is

    alert count down from 5 to 0. Explain why it doesn’t work and fix the bug. function count (num) { for (var i = 0; i <= num; i += 1) { setTimeout(function () { alert(num - i); }, i * 1000); } } count(5); Monday, 11 March, 13
  45. Quiz (javascript) function count (num) { for (var i =

    0; i <= num; i += 1) { (function (time) { setTimeout(function () { alert(num - time); }, time * 1000); }(i)); } } count(5); Monday, 11 March, 13
  46. Quiz (javascript) cont. function changeAnchorsToLightBox(anchors) { var length = anchors.length;

    for (var i = 0; i < length; i++) { anchors[i].onclick = function () { lightBox.open(anchors[i]); return false; }; } } Monday, 11 March, 13
  47. Quiz (javascript) cont. function changeAnchorsToLightBox(anchors) { var length = anchors.length;

    for (var i = 0; i < length; i++) { (function (anchor) { anchor.onclick = function () { lightBox.open(anchor); return false; }; }(anchors[i])); } } Monday, 11 March, 13
  48. Quiz (javascript) cont. function changeAnchorsToLightBox(anchors) { var length = anchors.length;

    for (var i = 0; i < length; i++) { (function (anchor) { anchor.onclick = function () { lightBox.open(anchor); return false; }; }(anchors[i])); } } Monday, 11 March, 13
  49. Reference Clean Code: A Handbook of Agile Software Craftsmanship http:/

    /www.amazon.com/Clean-Code-Handbook- Software-Craftsmanship/dp/0132350882 The Clean Code Talks - "Global State and Singletons" https:/ /www.youtube.com/watch?v=-FRm3VPhseI Monday, 11 March, 13
  50. Q & A and ... “Any fool can write code

    that a computer can understand. Good programmers write code that humans can understand.” Martin Fowler: Monday, 11 March, 13