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

Object Oriented Design

B71eb8af43555974c974ae0be19afa45?s=47 Li Ouyang
November 07, 2012

Object Oriented Design

An introduction to beautiful code. What is Object Oriented Programming. SOLID Principles.

B71eb8af43555974c974ae0be19afa45?s=128

Li Ouyang

November 07, 2012
Tweet

Transcript

  1. Object Oriented Design An Introduction to Beautiful Code Design Tuesday,

    November 6, 12
  2. Hello World @styliii styliii.com github.com/styliii Tuesday, November 6, 12

  3. Procedural Code collect data parse data if name is Li

    if name is not Li puts “Hi Li” puts “Bye” Tuesday, November 6, 12
  4. Procedural Code Tuesday, November 6, 12

  5. Procedural Code Data f1(x) f4(x) f3(x) f2(x) Tuesday, November 6,

    12
  6. Procedural Code Data f1(x) f4(x) f3(x) f2(x) Tuesday, November 6,

    12
  7. Procedural Code Data f1(x) f4(x) f3(x) f2(x) f5(x) Tuesday, November

    6, 12
  8. Procedural Code Data f1(x) f4(x) f3(x) f2(x) Tuesday, November 6,

    12
  9. Procedural Code Data f1(x) f4(x) f3(x) f2(x) Tuesday, November 6,

    12
  10. Procedural Code Data f1(x) f4(x) f3(x) f2(x) new f5(x) Tuesday,

    November 6, 12
  11. Object Oriented Code f1(x) f4(x) f3(x) f2(x) Data Tuesday, November

    6, 12
  12. Object Oriented Code f1(x) f4(x) f3(x) f2(x) Tuesday, November 6,

    12
  13. Object Oriented Code f1(x) f4(x) f3(x) f2(x) Tuesday, November 6,

    12
  14. Object Oriented Code Tuesday, November 6, 12

  15. History: Gang of Four Tuesday, November 6, 12

  16. Change Tuesday, November 6, 12

  17. Unhealthy Code rigid fragile - distant and seemingly unrelated code

    breaks after ever change immobility - code hopelessly entangled, you can’t reuse viscous - behaving badly is the most attractive alternative Tuesday, November 6, 12
  18. Dependencies “Dependency will kill your code. Design will save it.”

    Tuesday, November 6, 12
  19. SOLID Principles Single Responsibility Open/Closed Liskov Substitution Interface Segregation Dependency

    Inversion Tuesday, November 6, 12
  20. Single Responsibility A class should have one, and only one,

    reason to change. Tuesday, November 6, 12
  21. Open/Closed Software entities (classes, modules, functions, etc.) should be open

    for extension, but closed for modification. Tuesday, November 6, 12
  22. Liskov Substitution Objects in a program should be replaceable with

    instances of their subtypes without altering the correctness of that program. Tuesday, November 6, 12
  23. Interface Segregation Many client specific interfaces are better than one

    general purpose interface. Tuesday, November 6, 12
  24. Dependency Inversion Depend upon abstractions. Do not depend upon concretions.

    Tuesday, November 6, 12
  25. Dependency Inversion SOLID Single Responsibility Open/Closed Liskov Substitution Interface Segregation

    Tuesday, November 6, 12
  26. Dependency Inversion SOLID Single Responsibility Open/Closed Tuesday, November 6, 12

  27. Let’s Code! Tuesday, November 6, 12

  28. Let’s Code! require 'sqlite3' class Employer attr_accessor :name, :url, :about

    @@db ||= SQLite3::Database.new('jobs.db') @@db.results_as_hash = true def initialize(name="", url="", about="") @name = name @url = url @about = about end def insert_employer @@db.execute("INSERT INTO employers (name, url, about) VALUES (?, ?, ?)", [@name, @url, @about]) end Tuesday, November 6, 12
  29. SRP in Play require 'sqlite3' class Employer attr_accessor :name, :url,

    :about def initialize(name="", url="", about="") @name = name @url = url @about = about end end class Database @@db ||= SQLite3::Database.new('jobs.db') @@db.results_as_hash = true def insert_employer @@db.execute("INSERT INTO employers (name, url, about) VALUES (?, ?, ?)", [@name, @url, @about]) end end Tuesday, November 6, 12
  30. Make Database Class Work class Database @@db ||= SQLite3::Database.new('jobs.db') @@db.results_as_hash

    = true def insert_employer @@db.execute("INSERT INTO employers (name, url, about) VALUES (?, ?, ?)", [@name, @url, @about]) end end Tuesday, November 6, 12
  31. Make Database Class Work class Database @@db ||= SQLite3::Database.new('jobs.db') @@db.results_as_hash

    = true def insert_employer @@db.execute("INSERT INTO employers (name, url, about) VALUES (?, ?, ?)", [@name, @url, @about]) end end class Database attr_accessor :connection def initialize @connection = SQLite3::Database.new('jobs.db') self.connection.results_as_hash = true end def insert_employer self.connection.execute("INSERT INTO employers (name, url, about) VALUES (?, ?, ?)", [@name, @url, @about]) end end Tuesday, November 6, 12
  32. Abstract the Employer leftovers class Database attr_accessor :connection def initialize

    @connection = SQLite3::Database.new('jobs.db') self.connection.results_as_hash = true end def insert_employer self.connection.execute("INSERT INTO employers (name, url, about) VALUES (?, ?, ?)", [@name, @url, @about]) end end Tuesday, November 6, 12
  33. Abstract the Employer leftovers class Database attr_accessor :connection def initialize

    @connection = SQLite3::Database.new('jobs.db') self.connection.results_as_hash = true end def insert_employer self.connection.execute("INSERT INTO employers (name, url, about) VALUES (?, ?, ?)", [@name, @url, @about]) end end def insert_record(table, attribute_names, attributes) question_marks = Array.new(attribute_names.size, "?").join(", ") self.connection.execute("INSERT INTO #{table} (#{attribute_names.join(", ")}) VALUES (#{question_marks})", [attributes]) end Same As Tuesday, November 6, 12
  34. class Employer attr_accessor :name, :url, :about def initialize(name="", url="", about="")

    @name = name @url = url @about = about end end Our Employer Class Tuesday, November 6, 12
  35. Objects Interacting class Employer attr_accessor :name, :url, :about def initialize(name="",

    url="", about="") @name = name @url = url @about = about end end Tuesday, November 6, 12
  36. Objects Interacting class Employer attr_accessor :name, :url, :about def initialize(name="",

    url="", about="") @name = name @url = url @about = about end end def save Database.new.insert_record(table, attribute_names, attributes) end Tuesday, November 6, 12
  37. Objects Interacting class Employer attr_accessor :name, :url, :about def initialize(name="",

    url="", about="") @name = name @url = url @about = about end end def self.table @@table ||= "employers" end def save Database.new.insert_record(table, attribute_names, attributes) end Tuesday, November 6, 12
  38. Implement Save class Employer attr_accessor :name, :url, :about def initialize(name="",

    url="", about="") @name = name @url = url @about = about end end def self.table @@table ||= "employers" end def save Database.new.insert_record( table, attribute_names, attributes) end Tuesday, November 6, 12
  39. Implement Save class Employer attr_accessor :name, :url, :about def initialize(name="",

    url="", about="") @name = name @url = url @about = about end end def self.table @@table ||= "employers" end def save Database.new.insert_record( table, attribute_names, attributes) end self.class. Tuesday, November 6, 12
  40. Hardcode First class Employer attr_accessor :name, :url, :about def initialize(name="",

    url="", about="") @name = name @url = url @about = about end end def self.table @@table ||= "employers" end def save Database.new.insert_record( table, attribute_names, attributes) end self.class. Tuesday, November 6, 12
  41. Hardcode First class Employer attr_accessor :name, :url, :about def initialize(name="",

    url="", about="") @name = name @url = url @about = about end end def self.table @@table ||= "employers" end def save Database.new.insert_record( table, attribute_names, attributes) end self.class. attribute_names = ["name", "url", "about"] attributes = [self.name, self.url, self.about] Tuesday, November 6, 12
  42. Generalize Attributes class Employer attr_accessor :name, :url, :about end def

    self.table @@table ||= "employers" end def save attribute_names = self.instance_variables.map do |var| var.to_s.sub("@", "") end attributes = attribute_names.map do |att_name| self.send(att_name.to_sym) end Database.new.insert_record(self.class.table, attribute_names, attributes) end Tuesday, November 6, 12
  43. SRP for Methods too! class Employer def self.table @@table ||=

    "employers" end def save Database.new.insert_record(self.class.table, self.attribute_names, self.attributes) end def attribute_names self.instance_variables.map do |var| var.to_s.sub("@", "") end end def attributes attribute_names.map do |att_name| self.send(att_name.to_sym) end end end Tuesday, November 6, 12
  44. SRP for the Class require 'sqlite3' class Employer attr_accessor :name,

    :url, :about def initialize(name="", url="", about="") @name = name @url = url @about = about end def self.table @@table ||= "employers" end def save Database.new.insert_record(self.class.table, self.attribute_names, self.attributes) end end Tuesday, November 6, 12
  45. Modules module Attributable def attribute_names self.instance_variables.map do |var| var.to_s.sub("@", "")

    end end def attributes attribute_names.map do |att_name| self.send(att_name.to_sym) end end end Tuesday, November 6, 12
  46. Including the Module require 'sqlite3' require 'module' class Employer include

    Attributable attr_accessor :name, :url, :about def initialize(name="", url="", about="") @name = name @url = url @about = about end def self.table @@table ||= "employers" end def save Database.new.insert_record(self.class.table, self.attribute_names, self.attributes) end end Tuesday, November 6, 12
  47. What else? require 'sqlite3' require 'module' class Employer include Attributable

    attr_accessor :name, :url, :about def initialize(name="", url="", about="") @name = name @url = url @about = about end def self.table @@table ||= "employers" end def save Database.new.insert_record(self.class.table, self.attribute_names, self.attributes) end end Tuesday, November 6, 12
  48. Adding onto Module module Attributable def attribute_names self.instance_variables.map do |var|

    var.to_s.sub("@", "") end end def attributes attribute_names.map do |att_name| self.send(att_name.to_sym) end end end module Persistable def save Database.new.insert_record(self.class.table, self.attribute_names, self.attributes) end end Tuesday, November 6, 12
  49. Anything Else? require 'sqlite3' require 'module.rb' class Employer include Attributable,

    Persistable attr_accessor :name, :url, :about def initialize(name="", url="", about="") @name = name @url = url @about = about end def self.table @@table ||= "employers" end end Tuesday, November 6, 12
  50. Don’t Depend on Concretion Tuesday, November 6, 12

  51. Don’t Depend on Concretion class Employer attr_accessor :name, :url, :about

    def initialize(name="", url="", about="") @name = name @url = url @about = about end end Tuesday, November 6, 12
  52. Don’t Depend on Concretion class Employer attr_accessor :name, :url, :about

    def initialize(name="", url="", about="") @name = name @url = url @about = about end end def initialize(args={}) args.each do |key, value| self.send("#{key.to_sym}=", value) end end Same As Tuesday, November 6, 12
  53. Great Job :) require 'sqlite3' require 'module' class Employer include

    Attributable, Persistable attr_accessor :name, :url, :about def initialize(args = {}) args.each do |key, value| self.send("#{key.to_sym}=", value) end end def self.table @@table ||= "employers" end end Tuesday, November 6, 12
  54. SOLID Principles Single Responsibility Open/Closed Liskov Substitution Interface Segregation Dependency

    Inversion Tuesday, November 6, 12
  55. Resources Sandi Metz’s presentation on SOLID: http:/ /t.co/YqMiX7bq Diff between

    OO and Procedural Code: http:/ /www.youtube.com/watch? v=D8jZ0l_GwXQ Practical Object - Oriented Design in Ruby by Sandi Metz Source Code: https:/ /github.com/kcurtin/scrape_source https:/ /github.com/styliii/RubyJobScraper.git Books: Practical Object-Oriented Design in Ruby: An Agile Primer by Sandi Metz Pictures: http:/ /www.flickr.com/photos/yubacollege/4402710242/sizes/l/ http:/ /www.flickr.com/photos/dunechaser/6042984689/ http:/ /www.flickr.com/photos/ashclements/62704073/sizes/z/ Tuesday, November 6, 12