O que você NÃO aprendeu sobre Programação Orientada a Objetos

4,604 views

Published on

Slides da minha palestra na RubyConf BR 2013

Ruby é uma linguagem orientada a objetos, porém a maneira como aprendemos orientação a objetos geralmente foca no "O que?" e pouco no "Por quê?". Aprendemos o que é herança, polimorfismo, as diferenças entre classes e objetos, mas não discutimos questões mais relevantes como: o que caracteriza um bom design OO? Quais as vantagens e desvantagens de usar herança? Como OO me ajuda a resolver problemas do dia a dia? Nesta palestra vamos abordar estas e outras questões de design e modelagem OO através de exemplos. Pretendo desbancar alguns mitos - como modelar OO é modelar o mundo real - assim como compartilhar alguns princípios para ajudar você e seu time a melhorar a qualidade do código da sua aplicação Ruby.

Published in: Technology
3 Comments
40 Likes
Statistics
Notes
No Downloads
Views
Total views
4,604
On SlideShare
0
From Embeds
0
Number of Embeds
77
Actions
Shares
0
Downloads
138
Comments
3
Likes
40
Embeds 0
No embeds

No notes for slide

O que você NÃO aprendeu sobre Programação Orientada a Objetos

  1. 1. O que você NÃO aprendeu sobre Orientação a Objetos Danilo Sato @dtsato
  2. 2. Danilo Sato @dtsato - www.dtsato.com Desenvolvedor, Arquiteto, Coach, DevOps, Treinador
  3. 3. Como aprendemos OO?
  4. 4. Orientação a Objetos é: Herança + Polimorfismo + Encapsulamento
  5. 5. Orientação a Objetos é: Modelar o Mundo Real
  6. 6. “A execução de um programa é considerada um modelo físico, simulando o comportamento de uma parte real ou imaginária do mundo." -- Kristen Nygaard
  7. 7. “Programação orientada a objetos é uma péssima ideia, que só poderia ter nascido na Califórnia." -- Edsger W. Dijkstra
  8. 8. “Programação orientada a objetos é uma péssima ideia, que só poderia ter nascido na Califórnia." -- Edsger W. Dijkstra
  9. 9. “Na Ciência da Computação, arrogância é medida em nano-Dijkstras" -- Alan Kay
  10. 10. Inventou o termo “Orientação a Objetos”
  11. 11. Inventou o termo “Orientação a Objetos” Smalltalk
  12. 12. Células
  13. 13. Inventou o termo “Orientação a Objetos”
  14. 14. Inventou o termo “Orientação a Objetos” “OO significa passagem de mensagem, retenção local, proteção e ocultação do estado de um processo, e associação tardia de tudo"
  15. 15. Inventou o termo “Orientação a Objetos” “OO significa passagem de mensagem, retenção local, proteção e ocultação do estado de um processo, e associação tardia de tudo" “A grande ideia é passagem de mensagem"
  16. 16. Inventou o termo “Orientação a Objetos” “OO significa passagem de mensagem, retenção local, proteção e ocultação do estado de um processo, e associação tardia de tudo" “A grande ideia é passagem de mensagem" “OO é um modelo computacional, não um paradigma de programação"
  17. 17. “...(Erlang) é a única linguagem orientada a objetos e talvez eu tenha sido prematuro em dizer o que era orientação a objetos" -- Joe Armstrong
  18. 18. Orientação a Objetos: Programa? Linguagem? Paradigma? Modelo Computacional?
  19. 19. Orientação a Objetos: Programa? Linguagem? Paradigma? Modelo Computacional? Ninguém Concorda
  20. 20. Esta palestra é sobre oo
  21. 21. Esta palestra Não é sobre oo
  22. 22. Esta palestra é sobre DESIGNDESIGN
  23. 23. O que é ?DESIGN
  24. 24. DESIGN Código==
  25. 25. DESIGN Código== Estrutura Organização Flexibilidade Testabilidade Legibilidade Coesão Acoplamento Dependências
  26. 26. BOM reduz o custo da mudança DESIGN
  27. 27. DESIGN
  28. 28. Hipótese da stamina do DESIGN
  29. 29. Funcionalidades Tempo
  30. 30. Funcionalidades Tempo Sem Design
  31. 31. Funcionalidades Tempo Bom Design Sem Design
  32. 32. Funcionalidades Tempo Bom Design Sem Design Onde o design se paga
  33. 33. 2004!
  34. 34. Design foi esquecido Rails
  35. 35. Design foi esquecido Rails Model View Controller Helper Mailer ...
  36. 36. Model View Controller
  37. 37. Zero Design Design Ágil Up-front Design
  38. 38. DESIGN É BOM Design “ativo”
  39. 39. DESIGN É BOM Design “passivo”
  40. 40. DESIGN É BOM Design ágil == Design evolutivo
  41. 41. DESIGN É BOM Design ágil == Design evolutivo
  42. 42. TUDO É UM OBJETO!
  43. 43. TUDO É UM OBJETO?
  44. 44. TUDO É UM OBJETO? class?
  45. 45. TUDO É UM OBJETO? if? class?
  46. 46. TUDO É UM OBJETO? while? if? class?
  47. 47. Smalltalk
  48. 48. WARNING! O código que você está prestes a ler foi escrito com o propósito educacional. Não faça isso em casa ou coloque código parecido em produção.
  49. 49. class TrueClass def if_true(is_true, otherwise: -> {}) is_true.call end def if_false(is_false, otherwise: -> {}) otherwise.call end end class FalseClass def if_true(is_true, otherwise: -> {}) otherwise.call end def if_false(is_false, otherwise: -> {}) is_false.call end end Condições
  50. 50. 2.0.0 > (2 > 1).if_true -> { 2.0.0?> puts "sim" 2.0.0?> }, otherwise: -> { 2.0.0?> puts "não" 2.0.0?> } sim => nil 2.0.0 > (1 > 2).if_true -> { 2.0.0?> puts "sim" 2.0.0?> }, otherwise: -> { 2.0.0?> puts "não" 2.0.0?> } não => nil Condições
  51. 51. class Proc def while_true(&blk) self.call.if_true -> { blk.call while_true(&blk) } end end 2.0.0?> i = 0 2.0.0?> -> {i < 3}.while_true do 2.0.0?> puts i 2.0.0?> i += 1 2.0.0?> end 0 1 2 => nil Loops
  52. 52. Herança
  53. 53. Herança “É um”
  54. 54. Ave Pato Pinguim + voa() + voa() + voa()
  55. 55. class Bird def fly puts "flap, flap, flap" end end class Penguin < Bird def fly raise "I don't know how to fly" end end flock = [Bird.new, Bird.new, Bird.new] flock.each { |bird| bird.fly } # >> flap, flap, flap # >> flap, flap, flap # >> flap, flap, flap
  56. 56. class Bird def fly puts "flap, flap, flap" end end class Penguin < Bird def fly raise "I don't know how to fly" end end flock = [Penguin.new, Penguin.new, Penguin.new] flock.each { |bird| bird.fly } # ~> -:9:in `fly': I don't know how to fly (RuntimeError) # ~> from -:14:in `block in <main>' # ~> from -:14:in `each'
  57. 57. Princípio de Substituição de Liskov Se S é um subtipo de T, então os objetos do tipo T podem ser substituídos pelos objetos de tipo S em qualquer lugar do programa
  58. 58. Isto não é uma ave.Isto não é uma ave.
  59. 59. Herança “É um”
  60. 60. Herança “É um”
  61. 61. Herança
  62. 62. Herança ?
  63. 63. Herança
  64. 64. class Book < ActiveRecord::Base def initialize(attributes = nil, options = {}) super @my_cache = {} end def number_of_pages @my_cache[:number_of_pages] ||= 10000 end end Book.create( :title => "Lord of the Rings").number_of_pages # => 10000 Book.find_by( :title => "Lord of the Rings").number_of_pages # ~> -:8:in `number_of_pages': undefined method `[]' for nil:NilClass (NoMethodError)
  65. 65. class Book < ActiveRecord::Base def after_initialize @my_cache = {} end def number_of_pages @my_cache[:number_of_pages] ||= 10000 end end Book.create( :title => "Lord of the Rings").number_of_pages # => 10000 Book.find_by( :title => "Lord of the Rings").number_of_pages # => 10000
  66. 66. Herança: Preciso entender o que a(s) classe(s) Pai faz(em)!
  67. 67. class Deck < Array def initialize suits = %w(S H C D) indexes = %w(A 2 3 4 5 6 7 8 9 10 J Q K) cards = indexes.product(suits) super(cards) end def draw(n) self.pop(n) end end deck = Deck.new deck.shuffle!.draw(5) # => [["6", "H"], ["Q", "H"], ["3", "C"], ["6", "S"], ["K", "C"]] deck << ["A", "S"] << ["A", "S"] deck.count { |card| card[0] == "A"} # => 6 aces?
  68. 68. Não use herança se não usar todo o comportamento do(s) pais(s)
  69. 69. Herança é perigoso
  70. 70. Herança é perigoso
  71. 71. Herança é perigoso
  72. 72. Herança é perigoso
  73. 73. Herança é perigoso
  74. 74. Use Herança quando há especialização
  75. 75. Prefira hierarquias rasas
  76. 76. BigDecimal RationalComplexFloatInteger Fixnum Bignum Numeric
  77. 77. Agregação e composição
  78. 78. Agregação Composição “Tem um”
  79. 79. Agregação
  80. 80. Agregação
  81. 81. Agregação
  82. 82. composição
  83. 83. composição
  84. 84. composição
  85. 85. class Deck def initialize suits = %w(S H C D) indexes = %w(A 2 3 4 5 6 7 8 9 10 J Q K) @cards = indexes.product(suits) end def count(&blk); @cards.count(&blk) end def <<(card) @cards << card unless @cards.include?(card) self end end deck = Deck.new deck << ["A", "S"] << ["A", "S"] deck.count { |card| card[0] == "A"} # => 4
  86. 86. Prefira composição ao invés de Herança
  87. 87. Delegação
  88. 88. Delegação
  89. 89. require 'forwardable' class Deck extend Forwardable def_delegator :@cards, :pop, :draw def_delegators :@cards, :count def initialize suits = %w(S H C D) indexes = %w(A 2 3 4 5 6 7 8 9 10 J Q K) @cards = indexes.product(suits) end def <<(card) @cards << card unless @cards.include?(card) self end end deck = Deck.new deck.draw(5) # => [["Q", "D"], ["K", "S"], ["K", "H"], ["K", "C"], ["K", "D"]]
  90. 90. polimorfismo
  91. 91. polimorfismo
  92. 92. polimorfismo
  93. 93. 1. Herança
  94. 94. 1. Herança 2. Duck Typing
  95. 95. 1. Herança 2. Duck Typing 3. Mixins
  96. 96. permite separar abstração da concretização
  97. 97. permite separar “O que” do “Como”
  98. 98. Princípio “Open-Closed” Entidades de software como classes, módulos e funções devem ser abertas para extensão, mas fechadas para modificação -- Bertrand Meyer
  99. 99. MITO: Modelar OO é modelar o mundo real
  100. 100. Actor Ghost Pacman center, direction + collidesWith(Actor) + advance(millis) + getNextDirection()
  101. 101. Actor Ghost Strategy Pacman Strategy MovementStrategy + getNextDirection()
  102. 102. Actor Random Strategy UserControl Strategy MovementStrategy + getNextDirection()
  103. 103. Actor Random Strategy UserControl Strategy MovementStrategy + getNextDirection() TargetChasing Strategy + getTarget()
  104. 104. o design evolui Conforme o entendimento do domínio evolui
  105. 105. [ ] Metallica (10) [ ] Iron Maiden (5) [ ] AC/DC (15) [ ] ... [ ] Black Album (5) [ ] Master of Puppets (5) [ ] Killers (5) [ ] ... [x] Rock (50) [ ] Clássico (100) [ ] Jazz (80) Filtros Artista Album Estilo
  106. 106. class Song < ActiveRecord::Base searchable do string :title string :album { album.title } string :artist { album.artist.name } ... end def self.build_with_filters(p={}) search = Sunspot.new_search(Song) search.build do title = with(:title, p[:title]) if p[:title].present? artist = with(:artist, p[:artist]) if p[:artist].present? album = with(:album, p[:album]) if p[:album].present? ... facet :artist, exclude: artist facet :album, exclude: album end search end end
  107. 107. class Song < ActiveRecord::Base ... def self.build_with_filters(p={}) search = Sunspot.new_search(Song) if p[:artist] to_reject = p[:artist_album].map do |artist_album| JSON.parse(artist_album)['album'] end p[:album].reject! do |element| to_reject.include?(element) end p[:album] = [{}] if p[:album].empty? end search.build do ... end search end end
  108. 108. o domínio não é música
  109. 109. o domínio é busca
  110. 110. require 'forwadable' module Search class SongDocument extend Forwardable def_delegators :@song, :title def initialize(song) @song = song end def album @song.album.title end def artist @song.artist.name end ... end end
  111. 111. module Search class SongDocument def self.search_filters(p={}) [ Search::OptionalFilter.new(:artist, p), Search::AlbumFilter.new(:artist, :artist_album, p), Search::OptionalFilter.new(:title, p) ] end def self.build_with_filters(filters, p={}) Sunspot.new_search(Song).tap do |search| filters.each do |filter| filter.apply_to(search) end Search::Faceter.new(filters, p).apply_to(search) end end end end
  112. 112. Busca Música Document Filter Facet Indexer Song Album Artist
  113. 113. Contextos Delimitados Busca Música Document Filter Facet Indexer Song Album Artist
  114. 114. Mapa de Contextos Busca Música
  115. 115. “Todos os modelos estão errados, alguns modelos são úteis" -- George Box
  116. 116. MITO: Modelar OO é modelar o mundo real
  117. 117. MITO: Modelar OO é modelar o mundo real
  118. 118. Resumindo...
  119. 119. OO é passagem de mensagem
  120. 120. Herança agregação Composição delegação polimorfismo
  121. 121. DESIGN É BOM Zero Design Design Ágil Up-front Design Design ágil == Design evolutivo
  122. 122. DESIGN É BOM Zero Design Design Ágil Up-front Design Design ágil == Design evolutivo
  123. 123. Não modele o mundo real
  124. 124. modele o seu domínio
  125. 125. aprenda o seu domínio
  126. 126. evolua o seu domínio
  127. 127. se divirta!
  128. 128. Obrigado! Danilo Sato @dtsato - www.dtsato.com Desenvolvedor, Arquiteto, Coach, DevOps, Treinador
  129. 129. Referências • “Practical Object-Oriented Design in Ruby” Sandi Metz • “Domain-Driven Design: Tackling Complexity in the Heart of Software” Eric Evans • “Analysis Patterns: Reusable Object Models” Martin Fowler • “Patterns of Enterprise Application Architecture” Martin Fowler • “Design Patterns: Elements of Reusable Object-Oriented Software” Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides • “Growing Object-Oriented Software, Guided by Tests” Steve Freeman , Nat Pryce • “Object-Oriented Software Construction” Bertrand Meyer Livros:

×