Successfully reported this slideshow.
Your SlideShare is downloading. ×

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

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad

Check these out next

1 of 240 Ad
Advertisement

More Related Content

Similar to Qualidade de código - a qualidade que faz a diferença (20)

Advertisement

More from Caelum (14)

Recently uploaded (20)

Advertisement

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

  1. 1. Design de Código qualidade a longo prazo Guilherme Silveira @guilhermecaelum
  2. 2. Como parar de escrever o 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 tem um método zoado aí?
  17. 17. Implementation Design Architecture
  18. 18. architecture >=
  19. 19. architecture >= design >=
  20. 20. architecture >= design >= implementation
  21. 21. Browser Controller Hibernate
  22. 22. Browser Controller JPA
  23. 23. Browser Controller JPA file upload
  24. 24. Browser Controller JPA 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. IOC DESIGN
  32. 32. IOC Usando uma boa prática de design Paulo Silveira DESIGN
  33. 33. IOC Usando uma boa prática de design Paulo Silveira DESIGN ARQUITETURA
  34. 34. IOC Usando uma boa prática de design Paulo Silveira DESIGN Mudamos a arquitetura e economizamos $$$. ARQUITETURA Sérgio Lopes
  35. 35. Architecture Design Implementation
  36. 36. architecture <=
  37. 37. architecture <= design <=
  38. 38. architecture <= design <= implementation
  39. 39. architecture <= design <= implementation architecture >=
  40. 40. architecture <= design <= implementation architecture >= design >=
  41. 41. architecture <= design <= implementation architecture >= design >= implementation
  42. 42. architecture <= design <= implementation architecture >= design >= implementation architecture =
  43. 43. architecture <= design <= implementation architecture >= design >= implementation architecture = design =
  44. 44. architecture <= design <= implementation architecture >= design >= implementation architecture = design = implementation
  45. 45. design arquitetura java, ruby, scala, objective-c, c# servidores, firewalls etc implementação
  46. 46. existe
  47. 47. existe nenhuma arquitetura
  48. 48. existe nenhuma arquitetura nenhum design
  49. 49. existe nenhuma arquitetura nenhum design sem 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 manter implementation ===> difícil de manter
  58. 58. DESIGN IMPLEMENTAÇÃ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_att ribute( 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áveis zoadas?
  89. 89. Java? variáveis zoadas?
  90. 90. Java? C++? variáveis zoadas?
  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 linguagem novo
  100. 100. nova linguagem novo mindset
  101. 101. nova linguagem novo mindset novo
  102. 102. nova linguagem novo mindset novo uso idiomático
  103. 103. nova linguagem novo mindset novo uso idiomático mesmos
  104. 104. nova linguagem novo mindset novo uso idiomático mesmos 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, é natural intenção invisível
  114. 114. complexidade, é natural intençã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 teste cobertura = 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.save def save database.save(this) end
  149. 149. o que acontece se? an HTTP remote request!? client.save def save database.save(this) end
  150. 150. o que acontece se? an HTTP remote request!? ClientRule.checkUniqueEnroll is invoked!? client.save def save database.save(this) end
  151. 151. o que acontece se? an HTTP remote request!? ClientRule.checkUniqueEnroll is invoked!? “invisible invocation(s)” pattern client.save def 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_campo Maurí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 2 Martin 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 garanto mas a cobertura diz “100%”... mentirosa ...
  192. 192. coverage 100% would be 128 tests?
  193. 193. conscientizar-se da complexidade de nosso código Jim 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 CONSTRUTOR mas 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 static Rails: ActiveRecord.methods.size
  206. 206. positioning code
  207. 207. a new scala project vraptor + hibernate
  208. 208. modele REGRAS
  209. 209. Vamos refatorar?
  210. 210. no lugar ADEQUADO
  211. 211. post post post Ah! Quebrou encapsulamento dá nisso!
  212. 212. post post post Ah! Quebrou encapsulamento dá nisso!
  213. 213. post post post Ah! Quebrou encapsulamento dá nisso!
  214. 214. post post post Ah! Quebrou encapsulamento dá nisso!
  215. 215. post post post Ah! Quebrou encapsulamento dá nisso!
  216. 216. Posso agulhar? post post post Ah! Quebrou encapsulamento dá nisso!
  217. 217. no lugar ADEQUADO se eu mudar, eu quebro... mas ai tudo bem! encapsulamento++ demeter++
  218. 218. no lugar ADEQUADO se 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 devs aprender 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. refatore toda hora
  231. 231. 7. refactor toda hora para o melhor não para o mais fofo
  232. 232. lembre-se pair-programming brown bag refactoring code review
  233. 233. @guilhermecaelum guilherme.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 view if 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 boolean CTRL+F, if com chamada != de boolean

Editor's Notes

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

×