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

Architecting is Difficult: Breaking Borders, April 2014

Architecting is Difficult: Breaking Borders, April 2014

Aea964cf59c0c81fff752896f070cbbb?s=128

Jack Franklin

April 15, 2014
Tweet

Transcript

  1. Architecting is Difficult

  2. @Jack_Franklin — Student (for one more month) at University of

    Bath — (Soon to be a) developer for @GoCardless — Blogger at javascriptplayground.com, tilvim.com — Google Developer Expert on the Chrome team — Does a pretty epic Gangnam Style with @benmacgowan
  3. Any fool can write code that a computer can understand.

    Good programmers write code that humans can understand. -- Martin Fowler.
  4. Audience Participation

  5. None
  6. What makes code difficult to work with?

  7. You're never going to get it right first time

  8. Defer concrete decisions as late as possible - you'll never

    again know less about the problem than you do right now and the correct abstraction will become clearer over time. -- Andy Appleton
  9. Tests

  10. drive your API design you can try things out at

    no cost
  11. difficult to test? difficult to use a good sign something

    isn't quite right
  12. confidence when refactoring (more on this later) you'll know when

    you broke something
  13. Naming Conventions

  14. There are only two hard things in Computer Science: cache

    invalidation and naming things. -- Phil Karlton
  15. There are only two hard things in Computer Science: cache

    invalidation, naming things and off by one errors. -- ??
  16. prefer verbosity because auto complete

  17. be consistent use the same nouns and verbs

  18. Coding Standards http://editorconfig.org Pick a standard and stick to it

  19. Single Responsibility

  20. Do one thing And do it well

  21. Not good class EmailSender def initialize(csv) def parse_csv_for_emails def send_email

    end
  22. Better class EmailSender def initialize(csv) def parse_csv_for_emails Parser.new(csv).emails def send_email

    end class Parser def initialize(csv) def emails end
  23. Decoupled Components

  24. Ye know too much class EmailSender def initialize(csv) def parse_csv_for_emails

    Parser.new(csv).emails def send_email end class Parser def initialize(csv) def emails end
  25. Ignorance is bliss class EmailSender def initialize(emails) def send_email end

    class Parser def initialize(csv) def emails end emails = Parser.new(csv).emails EmailSender.new(emails).send_email
  26. Separate Aggressively

  27. don't be afraid to create classes / objects It's easier

    to merge two small things than split one large thing
  28. Refactoring

  29. None
  30. Refactoring Alter code without changing behaviour You have to have

    tests!
  31. Code smells Some code which may indicate a problem

  32. You don't fix code smells. You look at them and

    see if they indicate a problem you can fix. -- Joe Ferris
  33. Spot the smell 1

  34. var googleMapPin = function(x, y) {...}; var getLatLong = function(x,

    y) {...}; var user = { coordinates: [x, y]; };
  35. Data Clumps Continually passing round two (or more) variables as

    arguments.
  36. var googleMapPin = function(coords) {...}; var getLatLong = function(coords) {...};

    var user = { coordinates: coords }; var coords = { x: 1, y: 2 };
  37. Implicit Knowledge The relationship of x and y was implicit.

    By extracting the coords object, we make it explicit.
  38. Implicit Knowledge Seek to remove all implicit knowledge in a

    system. If I was handing it over to you, what would I need to explain?
  39. Spot the smell 2

  40. var drawGraph = function(graphWidth, graphHeight) { var width = 165

    + graphWidth; var height = 170.5 + graphHeight; };
  41. Magic Numbers! 165? 170.2? Implicit knowledge!

  42. var drawGraph = function(graphWidth, graphHeight) { var extra_graph_width_padding = 165;

    var extra_graph_height_padding = 170.5; var width = extra_graph_width_padding + graphWidth; var height = extra_graph_height_padding + graphHeight; };
  43. Spot the smell 3

  44. <% if user != nil %> <h2><%= user.welcome_message %></h2> <%

    else %> <h2>Please Sign In</h2> <% end %>
  45. Checking for nil (Or undefined / null in JS) What

    does nil mean? Nothing.
  46. Checking for nil Don't use it to stand in for

    something.
  47. Null Object Pattern Avoids conditional checks.

  48. class GuestUser def welcome_message "Please Sign In" end user =

    current_user || GuestUser.new View: <h2><%= user.welcome_message %></h2>
  49. Spot the smell 4

  50. var shouldScrollToBeginning = function(carousel) { if(carousel.isAtEnd()) { carousel.goToStart(); } };

  51. Tell, don't ask This function refers to carousel three times.

    Is this the best place for this code?
  52. var carousel = { ... startAgain: function() { if(this.isAtEnd()) {

    this.goToStart(); } } }
  53. Tell, don't ask Move the behaviour to where it makes

    most sense.
  54. Publish and Subscribe

  55. var carousel = function(accordion) { start: function() { accordion.close(); }

    }; var accordion = { ... }
  56. Ye know too much (again) The carousel knows that when

    it starts, it needs the accordion to close. That seems a bit odd?
  57. Pub Sub! var carousel = function() { start: function() {

    event.publish('carousel_start'); } }; var accordion = { init: function() { event.subscribe('carousel_start', function() { this.close(); }); } }
  58. Pub Sub! Neither module knows about the existance of the

    other. Easily extended.
  59. Spot the smell 5

  60. var someMethod = function() { doSomething(); doSomethingMore(); doAnotherThing(); if(something) {

    ... } doSomethingElse(); while(someOtherThing) { ... } };
  61. Doing too much Functions should be small, reusable and composable.

  62. Spot the smell 6

  63. var carousel = function( width, height, images, arrowLeft, arrowRight, animationSpeed,

    loopBackOnEnd ) { ... }
  64. Too many parameters carousel(500, 400, someImages, 'a.left', 'a.right', 500, false);

    Try to guess what each of those mean...
  65. Fix one var carousel = function(options) { var width =

    options.width; var height = options.height; ... }
  66. But If you need that many arguments, that might indicate

    the function is doing too much
  67. Getting into the habit

  68. Everytime you leave code, leave it a tiny bit better

    Note: better. Not best.
  69. Don't leave comments #TODO: this entire class is screwed, fix

    it #todo REMOVE BEFORE PRODUCTION... SERIOUSLY!
  70. They don't get done 243,803 #TODO comments.

  71. Changing code 1. Refactor to make the change easy. 2.

    Make the change Each change should be easy to introduce. If it's not, refactor.
  72. Refactor as you go Should be a constant process of

    small improvements.
  73. Remember You can't get it right first time!

  74. URLS — @Jack_Franklin — http://speakerdeck.com/jackfranklin — github.com/jackfranklin/talk-architecting-breaking- borders — http://javascriptplayground.com

    — http://refactoring.com/ — http://robots.thoughtbot.com/
  75. (Easy) Questions?