Qualidade de código - a qualidade que faz a diferença

1,315 views

Published on

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,315
On SlideShare
0
From Embeds
0
Number of Embeds
14
Actions
Shares
0
Downloads
33
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Esse é o gráfico de Requests/segundo do site da Caelum ao longo de duas semanas normais em Agosto/Setembro de 2010. Até que um belo dia acontece o lançamento da nova apostila de Rails 3 do curso RR-71 da Caelum...\n\n@sergio_caelum | Caelum | QCon São Paulo 2010\n
  • ... e, em apenas um instante, os acessos ao Site quintuplicam! \n\nEnviamos uma campanha em newsletter para milhares de inscritos, divulgamos no Blog com milhares de leitores e várias pessoas twitam. Tudo simultaneamente, em uma fria manhã de quinta-feira.\n\nComo lidar com esse tipo de pico? Como gerenciar os recursos computacionais necessários para segurar o tranco? E mais, sem desperdiçar recursos nem antes e nem depois; afinal o normal do site não é esse volume de acessos e o pico logo acaba.\n\nPodemos lançar por partes. Enviar a newsletter aos poucos para pequenos grupos. Divulgar no Blog apenas no dia seguinte. Mas piorar a experiência dos usuários por limitações técnicas? Perder aquele momento de marketing onde milhares e milhares de pessoas estão falando de você?\n\nVocê passa a vida toda desenvolvendo um produto e querendo que ele dê certo. E um belo dia ele estoura em sucesso. Como seu sistema reage? Ele capota ou segura o tranco naquele momento importantíssimo de crescimento? No fim de 2009, sem sabermos, o portal da revista InfoExame fez uma matéria citando nossas apostilas abertas. Foi uma correria para downloads, muitos e muitos acessos no site. Imagine não aguentar o tranco em um momento tão especial e com tanta visibilidade como esse?\n\n@sergio_caelum | Caelum | QCon São Paulo 2010\n
  • A solução rápida e fácil? Cloud computing e computação elástica\n\n@sergio_caelum | Caelum | QCon São Paulo 2010\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Qualidade de código - a qualidade que faz a diferença

    1. 1. Design de Códigoqualidade a longo prazo Guilherme Silveira @guilhermecaelum
    2. 2. Como parar de escrevero lixo do ano que vem Guilherme Silveira @guilhermecaelum
    3. 3. aka“chega de código lixo” Guilherme Silveira @guilhermecaelum
    4. 4. - líder técnico
    5. 5. - líder técnico- treinamentos
    6. 6. - líder técnico- treinamentos- online
    7. 7. guilherme.silveira@caelum.com.br- líder técnico- treinamentos- online
    8. 8. guilherme.silveira@caelum.com.br @guilhermecaelum- líder técnico- treinamentos- online
    9. 9. treinamento?
    10. 10. online.caelum.com.br trial hoje(descontão no beta)
    11. 11. > 2.3 reviews por resposta
    12. 12. online.caelum.com.br trial hoje(descontão no beta)
    13. 13. start!
    14. 14. o mais importante em um projeto éescrever código bonito
    15. 15. o mais importante em um projeto éescrever código bom
    16. 16. quem temum método zoado aí?
    17. 17. Implementation Design Architecture
    18. 18. architecture >=
    19. 19. architecture >= design >=
    20. 20. architecture >= design >= implementation
    21. 21. BrowserControllerHibernate
    22. 22. BrowserController JPA
    23. 23. Browser ControllerJPA file upload
    24. 24. Browser ControllerJPA memory
    25. 25. Browser Controller ### cloud ###JPA memory
    26. 26. 14 days and
    27. 27. 14 days and
    28. 28. Cloud Computing
    29. 29. Implementation Design Architecture
    30. 30. IOC
    31. 31. IOCDESIGN
    32. 32. IOC Usando uma boa prática de designPaulo Silveira DESIGN
    33. 33. IOC Usando uma boa prática de designPaulo Silveira DESIGN ARQUITETURA
    34. 34. IOC Usando uma boa prática de designPaulo Silveira DESIGN Mudamos a arquitetura e economizamos $$$. ARQUITETURA Sérgio Lopes
    35. 35. Architecture DesignImplementation
    36. 36. architecture <=
    37. 37. architecture <= design <=
    38. 38. architecture <= design <= implementation
    39. 39. architecture <= design <= implementationarchitecture >=
    40. 40. architecture <= design <= implementationarchitecture >= design >=
    41. 41. architecture <= design <= implementationarchitecture >= design >= implementation
    42. 42. architecture <= design <= implementationarchitecture >= design >= implementationarchitecture =
    43. 43. architecture <= design <= implementationarchitecture >= design >= implementationarchitecture = design =
    44. 44. architecture <= design <= implementationarchitecture >= design >= implementationarchitecture = design = implementation
    45. 45. design arquitetura java, ruby, scala, objective-c, c# servidores, firewalls etc implementação
    46. 46. existe
    47. 47. existenenhuma arquitetura
    48. 48. existenenhuma arquiteturanenhum design
    49. 49. existenenhuma arquiteturanenhum designsem implementação
    50. 50. existe implementação
    51. 51. a única “coisa” que existe é a implementação.
    52. 52. os mais importantes = os devs
    53. 53. o mais importante em um projeto éescrever código bom bonito?
    54. 54. arquitetura é o mínimo se a arquitetura não é boa, problemão
    55. 55. o que sobra? design...
    56. 56. o que sobra? design...interface ===> difícil de manter
    57. 57. o que sobra? design... interface ===> difícil de manterimplementation ===> difícil de manter
    58. 58. DESIGNIMPLEMENTAÇÃO
    59. 59. DESIGN Como seu código se comunica? (design interface de comunicação)IMPLEMENTAÇÃO
    60. 60. DESIGN Como seu código se comunica? (design interface de comunicação) Como seu código é executado? (design da implementação)IMPLEMENTAÇÃO
    61. 61. veremos code
    62. 62.       def _read_attribute(attr_name)        attr_name = attr_name.to_s        attr_name = self.class.primary_key if attr_name == id        value = @attributes[attr_name]        unless value.nil?          if column = column_for_attribute(attr_name)            if unserializable_attribute?(attr_name, column)              unserialize_attribute(attr_name)            else              column.type_cast(value)            end          else            value          end        end      end fonte pequena?
    63. 63.       def _read_attribute(attr_name)        attr_name = attr_name.to_s        attr_name = self.class.primary_key if attr_name == id        value = @attributes[attr_name]        unless value.nil?          if column = column_for_attribute(attr_name)            if unserializable_attribute?(attr_name, column)              unserialize_attribute(attr_name)            else              column.type_cast(value)            end          else            value          end        end      end agora sim? fonte 16
    64. 64. for_attribute(attr_na agora sim? mil fonte
    65. 65. 23...      def _read_attribute(attr_name)        attr_name = attr_name.to_s        attr_name = self.class.primary_key if attr_name == id        value = @attributes[attr_name]        unless value.nil?          if column = column_for_attribute(attr_name)            if unserializable_attribute?(attr_name, column)              unserialize_attribute(attr_name)            else              column.type_cast(value)            end          else            value          end        end      end
    66. 66. 23...      def _read_attribute(attr_name)        attr_name = attr_name.to_s        attr_name = self.class.primary_key if attr_name == id        value = @attributes[attr_name]        unless value.nil?          if column = column_for_attribute(attr_name)            if unserializable_attribute?(attr_name, column)              unserialize_attribute(attr_name)            else              column.type_cast(value)            end          else            value          end        end      end
    67. 67. mas e se... 23...      def _read_attribute(attr_name)        attr_name = attr_name.to_s        attr_name = self.class.primary_key if attr_name == id        value = @attributes[attr_name]        unless value.nil?          if column = column_for_attribute(attr_name)            if unserializable_attribute?(attr_name, column)              unserialize_attribute(attr_name)            else              column.type_cast(value)            end          else            value          end        end      end
    68. 68. mas eese... mas se... 23...      def _read_attribute(attr_name)        attr_name = attr_name.to_s        attr_name = self.class.primary_key if attr_name == id        value = @attributes[attr_name]        unless value.nil?          if column = column_for_attribute(attr_name)            if unserializable_attribute?(attr_name, column)              unserialize_attribute(attr_name)            else              column.type_cast(value)            end          else            value          end        end      end
    69. 69. mas eese... mas ese... 23... mas se...      def _read_attribute(attr_name)        attr_name = attr_name.to_s        attr_name = self.class.primary_key if attr_name == id        value = @attributes[attr_name]        unless value.nil?          if column = column_for_attribute(attr_name)            if unserializable_attribute?(attr_name, column)              unserialize_attribute(attr_name)            else              column.type_cast(value)            end          else            value          end        end      end
    70. 70. mas eese... mas ese... 23... mas ese... mas se...      def _read_attribute(attr_name)        attr_name = attr_name.to_s        attr_name = self.class.primary_key if attr_name == id        value = @attributes[attr_name]        unless value.nil?          if column = column_for_attribute(attr_name)            if unserializable_attribute?(attr_name, column)              unserialize_attribute(attr_name)            else              column.type_cast(value)            end          else            value          end        end      end
    71. 71. mas eese... mas ese... 23... mas ese... mas ese... mas se...      def _read_attribute(attr_name)        attr_name = attr_name.to_s        attr_name = self.class.primary_key if attr_name == id        value = @attributes[attr_name]        unless value.nil?          if column = column_for_attribute(attr_name)            if unserializable_attribute?(attr_name, column)              unserialize_attribute(attr_name)            else              column.type_cast(value)            end          else            value          end        end      end
    72. 72. mas eese... mas ese... 23... mas ese... mas ese... mas se...      def _read_attribute(attr_name)        attr_name = attr_name.to_s        attr_name = self.class.primary_key if attr_name == id        value = @attributes[attr_name]        unless value.nil?          if column = column_for_attribute(attr_name)            if unserializable_attribute?(attr_name, column)              unserialize_attribute(attr_name)            else              column.type_cast(value)            end          else            value          end        end      end
    73. 73. mas eese... mas ese... 23... mas ese... mas ese... mas ese... mas se...      def _read_attribute(attr_name)        attr_name = attr_name.to_s        attr_name = self.class.primary_key if attr_name == id        value = @attributes[attr_name]        unless value.nil?          if column = column_for_attribute(attr_name)            if unserializable_attribute?(attr_name, column)              unserialize_attribute(attr_name)            else              column.type_cast(value)            end          else            value          end        end      end
    74. 74. conciso?
    75. 75.       def _read_attribute(attr_name)        attr_name = attr_name.to_s        attr_name = self.class.primary_key if attr_name == id        value = @attributes[attr_name]        unless value.nil?          if column = column_for_attribute(attr_name)            if unserializable_attribute?(attr_name, column)              unserialize_attribute(attr_name)            else              column.type_cast(value)            end          else            value          end        end      end
    76. 76. o fluxo é COMPLEXO      def _read_attribute(attr_name)        attr_name = attr_name.to_s        attr_name = self.class.primary_key if attr_name == id        value = @attributes[attr_name]        unless value.nil?          if column = column_for_attribute(attr_name)            if unserializable_attribute?(attr_name, column)              unserialize_attribute(attr_name)            else              column.type_cast(value)            end          else            value          end        end      end
    77. 77. o fluxo éSEMANTICA não há COMPLEXO      def _read_attribute(attr_name)        attr_name = attr_name.to_s        attr_name = self.class.primary_key if attr_name == id        value = @attributes[attr_name]        unless value.nil?          if column = column_for_attribute(attr_name)            if unserializable_attribute?(attr_name, column)              unserialize_attribute(attr_name)            else              column.type_cast(value)            end          else            value          end        end      end
    78. 78. muitos ifs?
    79. 79. Java? muitos ifs?
    80. 80. Java? C++? muitos ifs?
    81. 81. Java? C++?C? muitos ifs?
    82. 82. Java? C++?C? muitos ifs? Basic?
    83. 83. Java? C++?C? muitos ifs? Ruby? Basic?
    84. 84. Clojure?Java? C++?C? muitos ifs? Ruby? Basic?
    85. 85. Clojure?Java? C++?C? muitos ifs?Scala? Ruby? Basic?
    86. 86. Clojure?Java? C++?C? muitos This month’s ifs? new language?Scala? Ruby? Basic?
    87. 87. i like repeating myself
    88. 88. variáveiszoadas?
    89. 89. Java?variáveiszoadas?
    90. 90. Java? C++?variáveiszoadas?
    91. 91. Java? C++?C? variáveis zoadas?
    92. 92. Java? C++?C? variáveis zoadas? Basic?
    93. 93. Java? C++?C? variáveis zoadas? Ruby? Basic?
    94. 94. Clojure?Java? C++?C? variáveis zoadas? Ruby? Basic?
    95. 95. Clojure?Java? C++?C? variáveis zoadas?Scala? Ruby? Basic?
    96. 96. Clojure?Java? C++?C? variáveis This month’s zoadas? new language?Scala? Ruby? Basic?
    97. 97. nova
    98. 98. nova linguagem
    99. 99. nova linguagemnovo
    100. 100. nova linguagemnovo mindset
    101. 101. nova linguagemnovo mindsetnovo
    102. 102. nova linguagemnovo mindsetnovo uso idiomático
    103. 103. nova linguagem novo mindset novo uso idiomáticomesmos
    104. 104. nova linguagem novo mindset novo uso idiomáticomesmos erros
    105. 105. complexidade invisivel        def cached_attributes          @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set        end
    106. 106. complexidade invisivel        def cached_attributes          @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set        end Mateus, programador do cão
    107. 107. complexidade invisivel        def cached_attributes          @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set        end Ahn? Mateus, programador do cão
    108. 108. entendeu?        def cached_attributes          @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set        end
    109. 109. uma linha = conciso?
    110. 110. uma linha = bonito?
    111. 111. complexidade,
    112. 112. complexidade, é natural
    113. 113. complexidade, é naturalintenção invisível
    114. 114. complexidade, é naturalintenção invisível é do mal
    115. 115. pegô?        def cached_attributes          @cached_attributes ||= columns.select { |c|cacheable_column?(c) }.map { |col| col.name }.to_set        end
    116. 116. conciso?        def terere          @cached_attributes ||= columns.select { |c|cacheable_column?(c) }.map { |col| col.name }.to_set        end
    117. 117.       def cached_attributes        @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set      end
    118. 118.       def cached_attributes        @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set      end how frequently does flow control appear?
    119. 119.       def cached_attributes        @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set      end how many tests do I need? how frequently does flow control appear?
    120. 120. 1 testecobertura = 100%
    121. 121. sua cobertura mentiu
    122. 122. pq?
    123. 123.       def cached_attributes        @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set      end Text how frequently does flow control appear?
    124. 124. how many ifs?      def cached_attributes        @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set      end Text how frequently does flow control appear?
    125. 125. how many ifs?      def cached_attributes        @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set      end Text how frequently does flow control appear?
    126. 126. how many ifs? how many fors?      def cached_attributes        @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set      end Text how frequently does flow control appear?
    127. 127. how many ifs? how many fors?      def cached_attributes        @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set      end Text how frequently does flow control appear?
    128. 128. how many ifs? how many fors?      def cached_attributes        @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set      end Text how many tests do I need? how frequently does flow control appear?
    129. 129. refatorar agora?
    130. 130. and now?      def cached_attributes        @cached_attributes ||= columns.select { |c| cacheable_column?(c) } .map { |col| col.name } .to_set      end
    131. 131. and now? how frequently does flow control appear?      def cached_attributes        @cached_attributes ||= columns.select { |c| cacheable_column?(c) } .map { |col| col.name } .to_set      end
    132. 132. ,
    133. 133. dê enter tarefa do bem
    134. 134. pela “concisão” menos toques no teclado zoaram meu código      def cached_attributes        @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set      end
    135. 135. pela “concisão” menos toques no teclado zoaram meu código      def cached_attributes        @cached_attributes ||= 컬륨.걸라 { |c| 캐시_컬륨?(c) }.맵 { |컬| 컬.이름 }.투샛      end
    136. 136. pela “concisão” menos teclas ainda!   def cached_attributes     @ ||= . { | | ?( ) }. { | | . }.   end
    137. 137. pela “concisão” menos teclas ainda!   def cached_attributes     @ ||= . { | | ?( ) }. { | | . }.   end
    138. 138. pela “concisão” menos teclas ainda!   def cached_attributes     @ ||= . { | | ?( ) }. { | | . }.   end
    139. 139. não é fazer código bonito
    140. 140. não é fazer código bonitoé não fazer deixar cocozinho
    141. 141. concisão = com o mínimo de palavras, deixar claro tarefa do bem
    142. 142. o que acontece?       Client client = clients.lookup(15L); client.getName();
    143. 143. o que acontece? requisição remota?       Client client = clients.lookup(15L); client.getName();
    144. 144. o que acontece? requisição remota? EJB 2 hell!       Client client = clients.lookup(15L); client.getName();
    145. 145. o que acontece? requisição remota? EJB 2 hell!       Client client = clients.lookup(15L); client.getName();
    146. 146. o que acontece? requisição remota? EJB 2 hell!       Client client = clients.lookup(15L); client.getName(); Quer ver uma mágica?
    147. 147. o que acontece? requisição HTTP? inferno de “rest” proxy aka active resource       Client client = clients.lookup(15L); client.getName();
    148. 148. o que acontece se?client.savedef save database.save(this)end
    149. 149. o que acontece se? an HTTP remote request!?client.savedef save database.save(this)end
    150. 150. o que acontece se? an HTTP remote request!?ClientRule.checkUniqueEnroll is invoked!?client.savedef save database.save(this)end
    151. 151. o que acontece se? an HTTP remote request!?ClientRule.checkUniqueEnroll is invoked!? “invisible invocation(s)” patternclient.savedef save database.save(this)end
    152. 152. composition
    153. 153. composition is good
    154. 154. composition is good if invisible,
    155. 155. composition is good if invisible, is evil
    156. 156.     private String getIdentifierName(Class<?> cls) {        if (!identifierNames.containsKey(cls)) {            String name = null;            if (cls.isAnnotationPresent(Identifier.class)) {                Identifier identifier = (Identifier) cls.getAnnotation(Identifier.class);                if (identifier.name() != null && !"".equals(identifier.name().trim())) {                    name = identifier.name();                }            }            if (name == null) {                name = cls.getName().substring(cls.getName().lastIndexOf(.) + 1);            }            identifierNames.put(cls, name);            return name; 9 quebras de fluxo        }        return identifierNames.get(cls); 5 testes    } 3 negações
    157. 157.     private String getIdentifierName(Class<?> cls) {        if (!identifierNames.containsKey(cls)) {            String name = null;            if (cls.isAnnotationPresent(Identifier.class)) {                Identifier identifier = (Identifier) cls.getAnnotation(Identifier.class);                if (identifier.name() != null && !"".equals(identifier.name().trim())) {                    name = identifier.name();                }            }            if (name == null) {                name = cls.getName().substring(cls.getName().lastIndexOf(.) + 1);            }            identifierNames.put(cls, name);            return name; 9 quebras de fluxo        }        return identifierNames.get(cls); 5 testes    } 3 negações
    158. 158.     private String getIdentifierName(Class<?> cls) {        if (!identifierNames.containsKey(cls)) {            String name = null;            if (cls.isAnnotationPresent(Identifier.class)) {                Identifier identifier = (Identifier) cls.getAnnotation(Identifier.class);                if (identifier.name() != null && !"".equals(identifier.name().trim())) {                    name = identifier.name();                }            }            if (name == null) {                name = cls.getName().substring(cls.getName().lastIndexOf(.) + 1);            }            identifierNames.put(cls, name);            return name; 9 quebras de fluxo        }        return identifierNames.get(cls); 5 testes    } 3 negações
    159. 159.     private String getIdentifierName(Class<?> cls) {        if (!identifierNames.containsKey(cls)) {            String name = null;            if (cls.isAnnotationPresent(Identifier.class)) {                Identifier identifier = (Identifier) cls.getAnnotation(Identifier.class);                if (identifier.name() != null && !"".equals(identifier.name().trim())) {                    name = identifier.name();                }            }            if (name == null) {                name = cls.getName().substring(cls.getName().lastIndexOf(.) + 1);            }            identifierNames.put(cls, name);            return name; 9 quebras de fluxo        }        return identifierNames.get(cls); 5 testes    } 3 negações
    160. 160.     private String getIdentifierName(Class<?> cls) {        if (!identifierNames.containsKey(cls)) {            String name = null;            if (cls.isAnnotationPresent(Identifier.class)) {                Identifier identifier = (Identifier) cls.getAnnotation(Identifier.class);                if (identifier.name() != null && !"".equals(identifier.name().trim())) {                    name = identifier.name();                }            }            if (name == null) {                name = cls.getName().substring(cls.getName().lastIndexOf(.) + 1);            }            identifierNames.put(cls, name);            return name; 9 quebras de fluxo        }        return identifierNames.get(cls); 5 testes    } 3 negações
    161. 161.     private String getIdentifierName(Class<?> cls) {        if (!identifierNames.containsKey(cls)) {            String name = null;            if (cls.isAnnotationPresent(Identifier.class)) {                Identifier identifier = (Identifier) cls.getAnnotation(Identifier.class);                if (identifier.name() != null && !"".equals(identifier.name().trim())) {                    name = identifier.name();                }            }            if (name == null) {                name = cls.getName().substring(cls.getName().lastIndexOf(.) + 1);            }            identifierNames.put(cls, name);            return name; 9 quebras de fluxo        }        return identifierNames.get(cls); 5 testes    } 3 negações
    162. 162.     private String getIdentifierName(Class<?> cls) {        if (!identifierNames.containsKey(cls)) {            String name = null;            if (cls.isAnnotationPresent(Identifier.class)) {                Identifier identifier = (Identifier) cls.getAnnotation(Identifier.class);                if (identifier.name() != null && !"".equals(identifier.name().trim())) {                    name = identifier.name();                }            }            if (name == null) {                name = cls.getName().substring(cls.getName().lastIndexOf(.) + 1);            }            identifierNames.put(cls, name);            return name; 9 quebras de fluxo        }        return identifierNames.get(cls); 5 testes    } 3 negações
    163. 163.     private String getIdentifierName(Class<?> cls) {        if (!identifierNames.containsKey(cls)) {            String name = null;            if (cls.isAnnotationPresent(Identifier.class)) {                Identifier identifier = (Identifier) cls.getAnnotation(Identifier.class);                if (identifier.name() != null && !"".equals(identifier.name().trim())) {                    name = identifier.name();                }            }            if (name == null) {                name = cls.getName().substring(cls.getName().lastIndexOf(.) + 1);            }            identifierNames.put(cls, name);            return name; 9 quebras de fluxo        }        return identifierNames.get(cls); 5 testes    } 3 negações
    164. 164.     private String getIdentifierName(Class<?> cls) {        if (!identifierNames.containsKey(cls)) {            String name = null;            if (cls.isAnnotationPresent(Identifier.class)) {                Identifier identifier = (Identifier) cls.getAnnotation(Identifier.class);                if (identifier.name() != null && !"".equals(identifier.name().trim())) {                    name = identifier.name();                }            }            if (name == null) {                name = cls.getName().substring(cls.getName().lastIndexOf(.) + 1);            }            identifierNames.put(cls, name);            return name; 9 quebras de fluxo        }        return identifierNames.get(cls); 5 testes    } 3 negações
    165. 165.     private String getIdentifierName(Class<?> cls) {        if (!identifierNames.containsKey(cls)) {            String name = null;            if (cls.isAnnotationPresent(Identifier.class)) {                Identifier identifier = (Identifier) cls.getAnnotation(Identifier.class);                if (identifier.name() != null && !"".equals(identifier.name().trim())) {                    name = identifier.name();                }            }            if (name == null) {                name = cls.getName().substring(cls.getName().lastIndexOf(.) + 1);            }            identifierNames.put(cls, name);            return name; 9 quebras de fluxo        }        return identifierNames.get(cls); 5 testes    } 3 negações
    166. 166. quem escreveu?
    167. 167. meu amigo sérgio
    168. 168.   private String getIdentifierName(Class<?> cls) {      if (!identifierNames.containsKey(cls)) {          String name = null;          if (cls.isAnnotationPresent(Identifier.class)) {              Identifier identifier = (Identifier) cls.getAnnotation(Identifier.class);              if (identifier.name() != null && !"".equals(identifier.name().trim())) {                  name = identifier.name();              }          }          if (name == null) {              name = cls.getName().substring(cls.getName().lastIndexOf(.) + 1);          }          identifierNames.put(cls, name);          return name;      }      return identifierNames.get(cls);  }
    169. 169.   private String getIdentifierName(Class<?> cls) {      if (identifierNames.containsKey(cls)) {       return identifierNames.get(cls);      }      String name = null;      if (cls.isAnnotationPresent(Identifier.class)) {          Identifier identifier = (Identifier) cls.getAnnotation(Identifier.class);          if (identifier.name() != null && !"".equals(identifier.name().trim())) {              name = identifier.name();          }      }      if (name == null) {          name = cls.getName().substring(cls.getName().lastIndexOf(.) + 1);      }      identifierNames.put(cls, name);      return name;  }
    170. 170.   private String getIdentifierName(Class<?> cls) {      if (identifierNames.containsKey(cls)) {       return identifierNames.get(cls);      }      String name = null;      Identifier identifier = (Identifier) cls.getAnnotation(Identifier.class);      if (identifier != null && identifier.name() != null && !"".equals(identifier.name().trim()          name = identifier.name();      }      if (name == null) {          name = cls.getName().substring(cls.getName().lastIndexOf(.) + 1);      }      identifierNames.put(cls, name);      return name;  }
    171. 171.   private String getIdentifierName(Class<?> cls) {      if (identifierNames.containsKey(cls)) {       return identifierNames.get(cls);      }      String name = null;      Identifier identifier = (Identifier) cls.getAnnotation(Identifier.class);      if (identifier != null && identifier.name() != null && !"".equals(identifier.name().trim()          name = identifier.name();      }      if (name == null) {          name = cls.getName().substring(cls.getName().lastIndexOf(.) + 1);      }      return cache(cls, name);  }  private String cache(Class<?> cls, String value) {   identifierNames.put(cls, name); return value;  }
    172. 172.   private String getIdentifierName(Class<?> cls) {      if (identifierNames.containsKey(cls)) {       return identifierNames.get(cls);      }      Identifier identifier = (Identifier) cls.getAnnotation(Identifier.class);      if (identifier == null || identifier.name() == null || "".equals(identifier.name().trim())       return cache(cls, cls.getName().substring(cls.getName().lastIndexOf(.) + 1));    }      return cache(cls, identifier.name()); }  private String cache(Class<?> cls, String value) {   identifierNames.put(cls, name); return value;  }
    173. 173.   private String getIdentifierName(Class<?> cls) {      if (identifierNames.containsKey(cls)) {       return identifierNames.get(cls);      }      Identifier identifier = (Identifier) cls.getAnnotation(Identifier.class);      if (identifier == null || identifier.name() == null || "".equals(identifier.name().trim())       return cache(cls, nameFor(cls));    }      return cache(cls, identifier.name()); }  private String cache(Class<?> cls, String value) {   identifierNames.put(cls, name); return value;  }  private String nameFor(Class<?> cls) { return cls.getName().substring(cls.getName().lastIndexOf(.) + 1);;  }
    174. 174.   private String getIdentifierName(Class<?> cls) {      if (identifierNames.containsKey(cls)) { 3 quebras de fluxo            } return identifierNames.get(cls); 0 negações      Identifier identifier = (Identifier) cls.getAnnotation(Identifier.class);      if (identifier == null || nullOrEmpty(identifier.name())) {       return cache(cls, nameFor(cls));    }      return cache(cls, identifier.name()); }  private static boolean nullOrEmpty(String value) { 2 quebras de fluxo  } return value == null || “”.equals(value.trim()); 0 negações  private String cache(Class<?> cls, String value) {   identifierNames.put(cls, name); return value;  }  private String nameFor(Class<?> cls) { return cls.getName().substring(cls.getName().lastIndexOf(.) + 1);;  }
    175. 175.   private String getIdentifierName(Class<?> cls) {      if (identifierNames.containsKey(cls)) { 3 quebras de fluxo            } return identifierNames.get(cls); 0 negações      Identifier identifier = (Identifier) cls.getAnnotation(Identifier.class);      if (identifier == null || nullOrEmpty(identifier.name())) {       return cache(cls, nameFor(cls));    }      return cache(cls, identifier.name()); }  private static boolean nullOrEmpty(String value) { 2 quebras de fluxo  } return value == null || “”.equals(value.trim()); 0 negações  private String cache(Class<?> cls, String value) {   identifierNames.put(cls, name); return value;  }  private String nameFor(Class<?> cls) { return cls.getName().substring(cls.getName().lastIndexOf(.) + 1);;  }
    176. 176. um “if if if if if if” dói (aka. sanduíche íche íche pattern)
    177. 177. ninguém acerta de primeira
    178. 178. esse dói?select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo
    179. 179. esse dói? select * from Contatos where a=b or (c=d && e=f) order by primeiro_campoMaurício Aniche
    180. 180. esse dói? select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo Como você testaria isso?Maurício Aniche
    181. 181. esse dói? select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo Como você testaria isso? mock.assert(_.select(“select from ...”))?Maurício Aniche
    182. 182. esse dói? select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo Como você testaria isso? mock.assert(_.select(“select from ...”))? 1 teste?Maurício Aniche
    183. 183. sua cobertura mente
    184. 184. select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2
    185. 185. select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2
    186. 186. select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2
    187. 187. Facinho...select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2
    188. 188. Facinho... select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2Martin Fowler
    189. 189. Facinho... select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2 sql também é linguagem...Martin Fowler
    190. 190. Facinho... select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2 sql também é linguagem... mina gata hein...Martin Fowler
    191. 191. menos de 5 testes não garantomas a cobertura diz “100%”...mentirosa ...
    192. 192. coverage 100% would be 128 tests?
    193. 193. conscientizar-se da complexidade de nosso códigoJim Webber
    194. 194. conscientizar-se da complexidade de nosso código não adianta esconder o spaguetti, ele continua lá.Jim Webber
    195. 195. conscientizar-se da complexidade de nosso código não adianta esconder o spaguetti, ele continua lá. tem que deixar explícito!Jim Webber
    196. 196. OO 101
    197. 197. se você tem que executar algo sempre que cria um Cliente?
    198. 198. se você tem que executar algosempre que cria um Cliente?
    199. 199. se você tem que executar algo sempre que cria um Cliente?
    200. 200. declare dependência e código no CONSTRUTOR
    201. 201. declare dependência e código no CONSTRUTORmas e no Rails, Javabeans, Hibernate, etc?
    202. 202. java (the javabeans way) rails (the ruby way)dumb constructor dumb constructor getter+setter attr_accessor the scala way dumb constructor val
    203. 203. java (the javabeans way) rails (the ruby way)dumb constructor dumb constructor public variable public variable the scala way dumb constructor public variable
    204. 204. O padrão de OO no mercado é a “orgia dos objetos” pattern. Todo mundo pega todo mundo.
    205. 205. Duvidou? Spring: CTRL+F staticRails: ActiveRecord.methods.size
    206. 206. positioning code
    207. 207. a new scala projectvraptor + hibernate
    208. 208. modele REGRAS
    209. 209. Vamos refatorar?
    210. 210. no lugar ADEQUADO
    211. 211. post post postAh! Quebrou encapsulamento dá nisso!
    212. 212. post post postAh! Quebrou encapsulamento dá nisso!
    213. 213. post post postAh! Quebrou encapsulamento dá nisso!
    214. 214. post post postAh! Quebrou encapsulamento dá nisso!
    215. 215. post post postAh! Quebrou encapsulamento dá nisso!
    216. 216. Posso agulhar? post post postAh! Quebrou encapsulamento dá nisso!
    217. 217. no lugar ADEQUADOse eu mudar, eu quebro... mas ai tudo bem! encapsulamento++ demeter++
    218. 218. no lugar ADEQUADOse eu mudar, eu quebro... mas ai tudo bem! encapsulamento++ demeter++
    219. 219. arquitetura insuficiente ==> melhore
    220. 220. caso contrário
    221. 221. 1. implementação existe, o resto é interpretação
    222. 222. 2. código é complexo
    223. 223. 2. código é complexo faça bunitu! não se preocupe com fofurice
    224. 224. 3. esconder intenção não é simplificar
    225. 225. 4. se é difícil de testar, é difícil de usar
    226. 226. 5. deixe seus devsaprender e melhorar
    227. 227. 6. ao mudar linguagem verifique 3 vezes os princípios
    228. 228. 7. melhore
    229. 229. 7. refatore
    230. 230. 7. refatoretoda hora
    231. 231. 7. refactor toda hora para o melhornão para o mais fofo
    232. 232. lembre-se pair-programmingbrown bag refactoring code review
    233. 233. @guilhermecaelumguilherme.silveira@caelum.com.br http://online.caelum.com.br te vejo lá
    234. 234. sobrou tempo? seu código hibernate
    235. 235. presentation code != domain code controller model viewif discussion.author==myself || myself.roles[:moderator]
    236. 236. presentation code != domain code controller model if discussion.author==myself view myself.roles[:moderator]if mysel.canEdit(discussion)
    237. 237. esses ifs não ficam repetidos em várias views
    238. 238. abra *.jsp, *.erb, *.ssp, *.similares CTRL+F, if com algo != de booleanCTRL+F, if com chamada != de boolean

    ×