SlideShare uma empresa Scribd logo
1 de 240
Design de Código
qualidade a longo prazo
       Guilherme Silveira
       @guilhermecaelum
Como parar de escrever
o lixo do ano que vem
      Guilherme Silveira
      @guilhermecaelum
aka
“chega de código lixo”
      Guilherme Silveira
      @guilhermecaelum
- líder técnico
- líder técnico
- treinamentos
- líder técnico
- treinamentos
- online
guilherme.silveira@caelum.com.br




- líder técnico
- treinamentos
- online
guilherme.silveira@caelum.com.br
                                  @guilhermecaelum




- líder técnico
- treinamentos
- online
treinamento?
online.caelum.com.br
      trial hoje
(descontão no beta)
> 2.3 reviews por
     resposta
online.caelum.com.br
      trial hoje
(descontão no beta)
start!
o mais importante
   em um projeto é
escrever código bonito
o mais importante
  em um projeto é
escrever código bom
quem tem
um método zoado aí?
Implementation




   Design




 Architecture
architecture >=
architecture >=   design >=
architecture >=   design >=   implementation
Browser




Controller




Hibernate
Browser




Controller




   JPA
Browser




      Controller




JPA           file upload
Browser




      Controller




JPA           memory
Browser




      Controller

  ### cloud ###

JPA           memory
14 days and
14 days and
Cloud Computing
Implementation




   Design




 Architecture
IOC
IOC
DESIGN
IOC
                 Usando uma boa prática de design




Paulo Silveira
                 DESIGN
IOC
                 Usando uma boa prática de design




Paulo Silveira
                 DESIGN
    ARQUITETURA
IOC
                 Usando uma boa prática de design




Paulo Silveira
                 DESIGN    Mudamos a arquitetura e
                            economizamos $$$.



    ARQUITETURA
                                                     Sérgio Lopes
Architecture




   Design




Implementation
architecture <=
architecture <=   design <=
architecture <=   design <=   implementation
architecture <=   design <=   implementation



architecture >=
architecture <=   design <=   implementation



architecture >=   design >=
architecture <=   design <=   implementation



architecture >=   design >=   implementation
architecture <=   design <=   implementation



architecture >=   design >=   implementation



architecture =
architecture <=   design <=   implementation



architecture >=   design >=   implementation



architecture =    design =
architecture <=   design <=   implementation



architecture >=   design >=   implementation



architecture =    design =    implementation
design                             arquitetura



    java, ruby, scala, objective-c, c#
        servidores, firewalls etc
            implementação
existe
existe
nenhuma arquitetura
existe
nenhuma arquitetura
nenhum design
existe
nenhuma arquitetura
nenhum design
sem    implementação
existe   implementação
a única “coisa” que existe
   é a implementação.
os mais importantes =   os devs
o mais importante
  em um projeto é
escrever código bom
            bonito?
arquitetura é o mínimo
 se a arquitetura não é boa, problemão
o que sobra? design...
o que sobra? design...

interface ===> difícil de manter
o que sobra? design...

   interface ===> difícil de manter
implementation ===> difícil de manter
DESIGN




IMPLEMENTAÇÃO
DESIGN


             Como seu código se comunica?
            (design interface de comunicação)




IMPLEMENTAÇÃO
DESIGN


             Como seu código se comunica?
            (design interface de comunicação)




                Como seu código é executado?
                 (design da implementação)


IMPLEMENTAÇÃO
veremos   code
      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?
      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
for_att
ribute(
attr_na
  agora sim? mil fonte
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
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
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
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
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
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
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
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
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
conciso?
      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
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
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
muitos
 ifs?
Java?
 muitos
  ifs?
Java?   C++?
 muitos
  ifs?
Java?   C++?


C?
   muitos
    ifs?
Java?     C++?


C?
   muitos
    ifs?
        Basic?
Java?     C++?


C?
   muitos
    ifs?
           Ruby?
        Basic?
Clojure?
Java?     C++?


C?
   muitos
    ifs?
           Ruby?
        Basic?
Clojure?
Java?   C++?


C?
   muitos
    ifs?
Scala? Ruby?
      Basic?
Clojure?
Java?   C++?


C?
   muitos         This
                month’s

    ifs?          new
               language?
Scala? Ruby?
      Basic?
i like repeating myself
variáveis
zoadas?
Java?
variáveis
zoadas?
Java?   C++?
variáveis
zoadas?
Java?   C++?


C?
  variáveis
   zoadas?
Java?     C++?


C?
  variáveis
   zoadas?
        Basic?
Java?     C++?


C?
  variáveis
   zoadas?
           Ruby?
        Basic?
Clojure?
Java?     C++?


C?
  variáveis
   zoadas?
           Ruby?
        Basic?
Clojure?
Java?   C++?


C?
  variáveis
   zoadas?
Scala? Ruby?
      Basic?
Clojure?
Java?   C++?


C?
  variáveis       This
                month’s

   zoadas?        new
               language?
Scala? Ruby?
      Basic?
nova
nova linguagem
nova linguagem
novo
nova linguagem
novo mindset
nova linguagem
novo mindset
novo
nova linguagem
novo mindset
novo uso idiomático
nova linguagem
  novo mindset
  novo uso idiomático
mesmos
nova linguagem
  novo mindset
  novo uso idiomático
mesmos erros
complexidade invisivel



        def cached_attributes
          @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set
        end
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
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
entendeu?



        def cached_attributes
          @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set
        end
uma linha = conciso?
uma linha = bonito?
complexidade,
complexidade,   é natural
complexidade,        é natural
intenção invisível
complexidade,     é natural
intenção invisível é do mal
pegô?


        def cached_attributes
          @cached_attributes ||= columns.select { |c|
cacheable_column?(c) }.map { |col| col.name }.to_set
        end
conciso?



        def terere
          @cached_attributes ||= columns.select { |c|
cacheable_column?(c) }.map { |col| col.name }.to_set
        end
      def cached_attributes
        @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set
      end
      def cached_attributes
        @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set
      end




                  how frequently does flow control appear?
      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?
1 teste
cobertura = 100%
sua cobertura
   mentiu
pq?
      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?
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?
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?
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?
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?
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?
refatorar
 agora?
and now?


      def cached_attributes
        @cached_attributes ||= columns.select { |c| cacheable_column?(c) }
                                      .map { |col| col.name }
                                      .to_set
      end
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
,
dê   enter
        tarefa do bem
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
pela “concisão”
            menos toques no teclado zoaram meu código
      def cached_attributes
        @cached_attributes ||= 컬륨.걸라 { |c| 캐시_컬륨?(c) }.맵 { |컬| 컬.이름 }.투샛
      end
pela “concisão”
                                        menos teclas ainda!
   def cached_attributes
     @   ||=  .   { | |    ?(   ) }.   { |   |   .   }.
   end
pela “concisão”
                   menos teclas ainda!

   def cached_attributes
     @   ||=  .   { | |    ?(   ) }.   { |   |   .   }.
   end
pela “concisão”
                   menos teclas ainda!

   def cached_attributes
     @   ||=  .   { | |    ?(   ) }.   { |   |   .   }.
   end
não é fazer código bonito
não é fazer código bonito
é não fazer deixar   cocozinho
concisão = com o mínimo de
   palavras, deixar claro


               tarefa do bem
o que acontece?




       Client client = clients.lookup(15L);
       client.getName();
o que acontece?
                requisição remota?


       Client client = clients.lookup(15L);
       client.getName();
o que acontece?
                requisição remota?
                    EJB 2 hell!

       Client client = clients.lookup(15L);
       client.getName();
o que acontece?
                requisição remota?
                    EJB 2 hell!

       Client client = clients.lookup(15L);
       client.getName();
o que acontece?
                  requisição remota?
                      EJB 2 hell!

       Client client = clients.lookup(15L);
       client.getName();


            Quer ver uma mágica?
o que acontece?
                  requisição HTTP?
               inferno de “rest” proxy
                 aka active resource
       Client client = clients.lookup(15L);
       client.getName();
o que acontece se?




client.save

def save
    database.save(this)
end
o que acontece se?
      an HTTP remote request!?




client.save

def save
    database.save(this)
end
o que acontece se?
       an HTTP remote request!?
ClientRule.checkUniqueEnroll is invoked!?


client.save

def save
    database.save(this)
end
o que acontece se?
        an HTTP remote request!?
ClientRule.checkUniqueEnroll is invoked!?
     “invisible invocation(s)” pattern

client.save

def save
    database.save(this)
end
composition
composition is good
composition is good
  if invisible,
composition is good
  if invisible, is evil
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
quem escreveu?
meu amigo
 sérgio
  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);
  }
  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;

  }
  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;

  }
  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;
  }
  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;
  }
  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);;
  }
  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);;
  }
  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);;
  }
um “if if if if if if” dói
    (aka. sanduíche íche íche pattern)
ninguém acerta de primeira
esse dói?

select * from Contatos where a=b or (c=d && e=f)
             order by primeiro_campo
esse dói?

 select * from Contatos where a=b or (c=d && e=f)
              order by primeiro_campo




Maurício Aniche
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
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
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
sua cobertura
    mente
select * from Contatos where a=b or (c=d && e=f)
          order by primeiro_campo limit 2
select * from Contatos where a=b or (c=d && e=f)
          order by primeiro_campo limit 2
select * from Contatos where a=b or (c=d && e=f)
          order by primeiro_campo limit 2
Facinho...




select * from Contatos where a=b or (c=d && e=f)
          order by primeiro_campo limit 2
Facinho...




  select * from Contatos where a=b or (c=d && e=f)
            order by primeiro_campo limit 2




Martin Fowler
Facinho...




  select * from Contatos where a=b or (c=d && e=f)
            order by primeiro_campo limit 2
                 sql também é linguagem...




Martin Fowler
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
menos de 5 testes não garanto

mas a cobertura diz “100%”...


mentirosa                       ...
coverage 100% would be



      128 tests?
conscientizar-se da complexidade
               de nosso código




Jim Webber
conscientizar-se da complexidade
               de nosso código



                 não adianta esconder o spaguetti,
                          ele continua lá.




Jim Webber
conscientizar-se da complexidade
               de nosso código



                 não adianta esconder o spaguetti,
                          ele continua lá.

                     tem que deixar explícito!



Jim Webber
OO 101
se você tem que executar algo sempre
         que cria um Cliente?
se você tem que executar algosempre
            que cria um Cliente?
se você tem que executar algo   sempre
                que cria um Cliente?
declare dependência
     e código no
  CONSTRUTOR
declare dependência
     e código no
  CONSTRUTOR
mas e no Rails, Javabeans, Hibernate, etc?
java (the javabeans way)       rails (the ruby way)
dumb constructor dumb constructor
  getter+setter    attr_accessor
                    the scala way
             dumb constructor
                   val
java (the javabeans way)       rails (the ruby way)
dumb constructor dumb constructor
  public variable  public variable
                    the scala way
             dumb constructor
               public variable
O padrão de OO no mercado é a
  “orgia dos objetos” pattern.

 Todo mundo pega todo mundo.
Duvidou?

       Spring: CTRL+F static
Rails: ActiveRecord.methods.size
positioning
  code
a new scala project
vraptor + hibernate
modele REGRAS
Vamos refatorar?
no lugar ADEQUADO
post post post




Ah! Quebrou encapsulamento dá nisso!
post post post




Ah! Quebrou encapsulamento dá nisso!
post post post




Ah! Quebrou encapsulamento dá nisso!
post post post




Ah! Quebrou encapsulamento dá nisso!
post post post




Ah! Quebrou encapsulamento dá nisso!
Posso agulhar?




      post post post




Ah! Quebrou encapsulamento dá nisso!
no lugar ADEQUADO

se eu mudar, eu quebro... mas ai
         tudo bem!                 encapsulamento++
                                          demeter++
no lugar ADEQUADO

se eu mudar, eu quebro... mas ai
         tudo bem!                 encapsulamento++
                                          demeter++
arquitetura insuficiente
         ==>
       melhore
caso contrário
1. implementação existe,
        o resto é
      interpretação
2. código é complexo
2. código é complexo
      faça bunitu!
   não se preocupe
     com fofurice
3. esconder intenção
   não é simplificar
4. se é difícil de testar,
    é difícil de usar
5. deixe seus devs
aprender e melhorar
6. ao mudar linguagem
    verifique 3 vezes
      os princípios
7. melhore
7. refatore
7. refatore
toda hora
7. refactor
     toda hora
   para o melhor
não para o mais fofo
lembre-se

  pair-programming
brown bag refactoring
     code review
@guilhermecaelum
guilherme.silveira@caelum.com.br
    http://online.caelum.com.br




  te vejo lá
sobrou tempo?
  seu código
   hibernate
presentation code != domain code


           controller




                                       model



             view


if discussion.author==myself ||
    myself.roles[:moderator]
presentation code != domain code


          controller




                                           model


                               if discussion.author==myself
            view                   myself.roles[:moderator]

if mysel.canEdit(discussion)
esses ifs não ficam repetidos em várias views
abra *.jsp, *.erb, *.ssp, *.similares
 CTRL+F, if com algo != de boolean
CTRL+F, if com chamada != de boolean

Mais conteúdo relacionado

Destaque

Agile2011
Agile2011Agile2011
Agile2011Caelum
 
Como fabricar dinheiro: Otimizações de Sites e porque isso vai deixá-lo rico ...
Como fabricar dinheiro: Otimizações de Sites e porque isso vai deixá-lo rico ...Como fabricar dinheiro: Otimizações de Sites e porque isso vai deixá-lo rico ...
Como fabricar dinheiro: Otimizações de Sites e porque isso vai deixá-lo rico ...Caelum
 
Plataforma java: detalhes da JVM
Plataforma java: detalhes da JVMPlataforma java: detalhes da JVM
Plataforma java: detalhes da JVMCaelum
 
Google Android - WTJatai
Google Android - WTJataiGoogle Android - WTJatai
Google Android - WTJataiCaelum
 
Desafios de Performance Web - BrazilJS
Desafios de Performance Web - BrazilJSDesafios de Performance Web - BrazilJS
Desafios de Performance Web - BrazilJSCaelum
 
Porque você deveria usar CDI nos seus projetos Java! - JavaOne LA 2012 - Sérg...
Porque você deveria usar CDI nos seus projetos Java! - JavaOne LA 2012 - Sérg...Porque você deveria usar CDI nos seus projetos Java! - JavaOne LA 2012 - Sérg...
Porque você deveria usar CDI nos seus projetos Java! - JavaOne LA 2012 - Sérg...Caelum
 
Offline Web com Service Workers - Sérgio Lopes
Offline Web com Service Workers - Sérgio LopesOffline Web com Service Workers - Sérgio Lopes
Offline Web com Service Workers - Sérgio LopesCaelum
 
[QCon 2011] Por uma web mais rápida: técnicas de otimização de Sites
[QCon 2011] Por uma web mais rápida: técnicas de otimização de Sites[QCon 2011] Por uma web mais rápida: técnicas de otimização de Sites
[QCon 2011] Por uma web mais rápida: técnicas de otimização de SitesCaelum
 
Progressive Web Apps: o melhor da Web appficada
Progressive Web Apps: o melhor da Web appficadaProgressive Web Apps: o melhor da Web appficada
Progressive Web Apps: o melhor da Web appficadaCaelum
 

Destaque (9)

Agile2011
Agile2011Agile2011
Agile2011
 
Como fabricar dinheiro: Otimizações de Sites e porque isso vai deixá-lo rico ...
Como fabricar dinheiro: Otimizações de Sites e porque isso vai deixá-lo rico ...Como fabricar dinheiro: Otimizações de Sites e porque isso vai deixá-lo rico ...
Como fabricar dinheiro: Otimizações de Sites e porque isso vai deixá-lo rico ...
 
Plataforma java: detalhes da JVM
Plataforma java: detalhes da JVMPlataforma java: detalhes da JVM
Plataforma java: detalhes da JVM
 
Google Android - WTJatai
Google Android - WTJataiGoogle Android - WTJatai
Google Android - WTJatai
 
Desafios de Performance Web - BrazilJS
Desafios de Performance Web - BrazilJSDesafios de Performance Web - BrazilJS
Desafios de Performance Web - BrazilJS
 
Porque você deveria usar CDI nos seus projetos Java! - JavaOne LA 2012 - Sérg...
Porque você deveria usar CDI nos seus projetos Java! - JavaOne LA 2012 - Sérg...Porque você deveria usar CDI nos seus projetos Java! - JavaOne LA 2012 - Sérg...
Porque você deveria usar CDI nos seus projetos Java! - JavaOne LA 2012 - Sérg...
 
Offline Web com Service Workers - Sérgio Lopes
Offline Web com Service Workers - Sérgio LopesOffline Web com Service Workers - Sérgio Lopes
Offline Web com Service Workers - Sérgio Lopes
 
[QCon 2011] Por uma web mais rápida: técnicas de otimização de Sites
[QCon 2011] Por uma web mais rápida: técnicas de otimização de Sites[QCon 2011] Por uma web mais rápida: técnicas de otimização de Sites
[QCon 2011] Por uma web mais rápida: técnicas de otimização de Sites
 
Progressive Web Apps: o melhor da Web appficada
Progressive Web Apps: o melhor da Web appficadaProgressive Web Apps: o melhor da Web appficada
Progressive Web Apps: o melhor da Web appficada
 

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

O que você NÃO aprendeu sobre Programação Orientada a Objetos
O que você NÃO aprendeu sobre Programação Orientada a ObjetosO que você NÃO aprendeu sobre Programação Orientada a Objetos
O que você NÃO aprendeu sobre Programação Orientada a ObjetosDanilo Sato
 
Programação Orientada a Testes
Programação Orientada a TestesProgramação Orientada a Testes
Programação Orientada a TestesGregorio Melo
 
Introdução à Linguagem de programação Python
Introdução à Linguagem de programação PythonIntrodução à Linguagem de programação Python
Introdução à Linguagem de programação Pythondmmartins
 
Algoritmos e Estrutura de Dados - Aula 03
Algoritmos e Estrutura de Dados - Aula 03Algoritmos e Estrutura de Dados - Aula 03
Algoritmos e Estrutura de Dados - Aula 03thomasdacosta
 
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop Python
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop PythonIEEEweek 2017 @ DETI Univ. Aveiro - Workshop Python
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop PythonDiogo Gomes
 
Iteraveis e geradores em Python
Iteraveis e geradores em PythonIteraveis e geradores em Python
Iteraveis e geradores em PythonLuciano Ramalho
 
Ruby on rails gds 2011
Ruby on rails   gds 2011Ruby on rails   gds 2011
Ruby on rails gds 2011JogosUnisinos
 
Ruby - Criando código para máquinas e humanos
Ruby - Criando código para máquinas e humanosRuby - Criando código para máquinas e humanos
Ruby - Criando código para máquinas e humanosGregorio Kusowski
 
Introducao a Linguagem Kotlin
Introducao a Linguagem KotlinIntroducao a Linguagem Kotlin
Introducao a Linguagem KotlinCalebeMiquissene
 
Legibilidade do código
Legibilidade do códigoLegibilidade do código
Legibilidade do códigoFelipe Volpone
 
Criando Símbolos Otimizados para Projetos no InduSoft Web Studio
Criando Símbolos Otimizados para Projetos no InduSoft Web StudioCriando Símbolos Otimizados para Projetos no InduSoft Web Studio
Criando Símbolos Otimizados para Projetos no InduSoft Web StudioAVEVA
 
Estruturas de dados em Python
Estruturas de dados em PythonEstruturas de dados em Python
Estruturas de dados em PythonRicardo Paiva
 
A ferramenta ideal: uma questão de perspectiva.
A ferramenta ideal: uma questão de perspectiva.A ferramenta ideal: uma questão de perspectiva.
A ferramenta ideal: uma questão de perspectiva.Ricardo Valeriano
 
(2015-01-29/30) [WTA2015] Adaptatividade em Python (Tutorial)
(2015-01-29/30) [WTA2015] Adaptatividade em Python (Tutorial)(2015-01-29/30) [WTA2015] Adaptatividade em Python (Tutorial)
(2015-01-29/30) [WTA2015] Adaptatividade em Python (Tutorial)Danilo J. S. Bellini
 
As Novidades Do C# 4.0 - NetPonto
As Novidades Do C# 4.0 - NetPontoAs Novidades Do C# 4.0 - NetPonto
As Novidades Do C# 4.0 - NetPontoPaulo Morgado
 
Ruby on Rails (VERSAO COM LAYOUT CONSERTADO)
Ruby on Rails (VERSAO COM LAYOUT CONSERTADO)Ruby on Rails (VERSAO COM LAYOUT CONSERTADO)
Ruby on Rails (VERSAO COM LAYOUT CONSERTADO)Julio Betta
 

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

O que você NÃO aprendeu sobre Programação Orientada a Objetos
O que você NÃO aprendeu sobre Programação Orientada a ObjetosO que você NÃO aprendeu sobre Programação Orientada a Objetos
O que você NÃO aprendeu sobre Programação Orientada a Objetos
 
Programação Orientada a Testes
Programação Orientada a TestesProgramação Orientada a Testes
Programação Orientada a Testes
 
Introdução à Linguagem de programação Python
Introdução à Linguagem de programação PythonIntrodução à Linguagem de programação Python
Introdução à Linguagem de programação Python
 
Algoritmos e Estrutura de Dados - Aula 03
Algoritmos e Estrutura de Dados - Aula 03Algoritmos e Estrutura de Dados - Aula 03
Algoritmos e Estrutura de Dados - Aula 03
 
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop Python
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop PythonIEEEweek 2017 @ DETI Univ. Aveiro - Workshop Python
IEEEweek 2017 @ DETI Univ. Aveiro - Workshop Python
 
Minicurso Ruby on Rails
Minicurso Ruby on RailsMinicurso Ruby on Rails
Minicurso Ruby on Rails
 
Iteraveis e geradores em Python
Iteraveis e geradores em PythonIteraveis e geradores em Python
Iteraveis e geradores em Python
 
Object Oriented Programming
Object Oriented ProgrammingObject Oriented Programming
Object Oriented Programming
 
Ruby on rails gds 2011
Ruby on rails   gds 2011Ruby on rails   gds 2011
Ruby on rails gds 2011
 
Ruby - Criando código para máquinas e humanos
Ruby - Criando código para máquinas e humanosRuby - Criando código para máquinas e humanos
Ruby - Criando código para máquinas e humanos
 
JavaScript - A Linguagem
JavaScript - A LinguagemJavaScript - A Linguagem
JavaScript - A Linguagem
 
Introducao a Linguagem Kotlin
Introducao a Linguagem KotlinIntroducao a Linguagem Kotlin
Introducao a Linguagem Kotlin
 
Legibilidade do código
Legibilidade do códigoLegibilidade do código
Legibilidade do código
 
Criando Símbolos Otimizados para Projetos no InduSoft Web Studio
Criando Símbolos Otimizados para Projetos no InduSoft Web StudioCriando Símbolos Otimizados para Projetos no InduSoft Web Studio
Criando Símbolos Otimizados para Projetos no InduSoft Web Studio
 
Estruturas de dados em Python
Estruturas de dados em PythonEstruturas de dados em Python
Estruturas de dados em Python
 
Comecando tensorflow
Comecando tensorflowComecando tensorflow
Comecando tensorflow
 
A ferramenta ideal: uma questão de perspectiva.
A ferramenta ideal: uma questão de perspectiva.A ferramenta ideal: uma questão de perspectiva.
A ferramenta ideal: uma questão de perspectiva.
 
(2015-01-29/30) [WTA2015] Adaptatividade em Python (Tutorial)
(2015-01-29/30) [WTA2015] Adaptatividade em Python (Tutorial)(2015-01-29/30) [WTA2015] Adaptatividade em Python (Tutorial)
(2015-01-29/30) [WTA2015] Adaptatividade em Python (Tutorial)
 
As Novidades Do C# 4.0 - NetPonto
As Novidades Do C# 4.0 - NetPontoAs Novidades Do C# 4.0 - NetPonto
As Novidades Do C# 4.0 - NetPonto
 
Ruby on Rails (VERSAO COM LAYOUT CONSERTADO)
Ruby on Rails (VERSAO COM LAYOUT CONSERTADO)Ruby on Rails (VERSAO COM LAYOUT CONSERTADO)
Ruby on Rails (VERSAO COM LAYOUT CONSERTADO)
 

Mais de Caelum

Performance Web além do carregamento
Performance Web além do carregamentoPerformance Web além do carregamento
Performance Web além do carregamentoCaelum
 
Tudo que você precisa saber sobre picture e srcset
Tudo que você precisa saber sobre picture e srcsetTudo que você precisa saber sobre picture e srcset
Tudo que você precisa saber sobre picture e srcsetCaelum
 
Como o HTTP/2 vai mudar sua vida
Como o HTTP/2 vai mudar sua vidaComo o HTTP/2 vai mudar sua vida
Como o HTTP/2 vai mudar sua vidaCaelum
 
Métricas e a automatização do controle de qualidade
Métricas e a automatização do controle de qualidadeMétricas e a automatização do controle de qualidade
Métricas e a automatização do controle de qualidadeCaelum
 
HTTP/2, SPDY e Otimizações Web - Front In Maceió 2014 - Sérgio Lopes
HTTP/2, SPDY e Otimizações Web - Front In Maceió 2014 - Sérgio LopesHTTP/2, SPDY e Otimizações Web - Front In Maceió 2014 - Sérgio Lopes
HTTP/2, SPDY e Otimizações Web - Front In Maceió 2014 - Sérgio LopesCaelum
 
Design Responsivo - MobCamp 2014
Design Responsivo - MobCamp 2014Design Responsivo - MobCamp 2014
Design Responsivo - MobCamp 2014Caelum
 
Além do responsive design: a mudança de paradigma do design adaptativo e os m...
Além do responsive design: a mudança de paradigma do design adaptativo e os m...Além do responsive design: a mudança de paradigma do design adaptativo e os m...
Além do responsive design: a mudança de paradigma do design adaptativo e os m...Caelum
 
Por trás dos frameworks e além do reflection
Por trás dos frameworks e além do reflectionPor trás dos frameworks e além do reflection
Por trás dos frameworks e além do reflectionCaelum
 
Otimizações de Performance Web: Desafios do Mundo Mobile
Otimizações de Performance Web: Desafios do Mundo MobileOtimizações de Performance Web: Desafios do Mundo Mobile
Otimizações de Performance Web: Desafios do Mundo MobileCaelum
 
Introducao a inteligencia artificial na educacao
Introducao a inteligencia artificial na educacaoIntroducao a inteligencia artificial na educacao
Introducao a inteligencia artificial na educacaoCaelum
 
Otimizando o time to market - do zero a produção em poucas iterações
Otimizando o time to market - do zero a produção em poucas iteraçõesOtimizando o time to market - do zero a produção em poucas iterações
Otimizando o time to market - do zero a produção em poucas iteraçõesCaelum
 
All you need to know about JavaScript loading and execution in the browser - ...
All you need to know about JavaScript loading and execution in the browser - ...All you need to know about JavaScript loading and execution in the browser - ...
All you need to know about JavaScript loading and execution in the browser - ...Caelum
 
Design Responsivo por uma Web única
Design Responsivo por uma Web únicaDesign Responsivo por uma Web única
Design Responsivo por uma Web únicaCaelum
 
CDI e as ideias pro futuro do VRaptor
CDI e as ideias pro futuro do VRaptorCDI e as ideias pro futuro do VRaptor
CDI e as ideias pro futuro do VRaptorCaelum
 

Mais de Caelum (14)

Performance Web além do carregamento
Performance Web além do carregamentoPerformance Web além do carregamento
Performance Web além do carregamento
 
Tudo que você precisa saber sobre picture e srcset
Tudo que você precisa saber sobre picture e srcsetTudo que você precisa saber sobre picture e srcset
Tudo que você precisa saber sobre picture e srcset
 
Como o HTTP/2 vai mudar sua vida
Como o HTTP/2 vai mudar sua vidaComo o HTTP/2 vai mudar sua vida
Como o HTTP/2 vai mudar sua vida
 
Métricas e a automatização do controle de qualidade
Métricas e a automatização do controle de qualidadeMétricas e a automatização do controle de qualidade
Métricas e a automatização do controle de qualidade
 
HTTP/2, SPDY e Otimizações Web - Front In Maceió 2014 - Sérgio Lopes
HTTP/2, SPDY e Otimizações Web - Front In Maceió 2014 - Sérgio LopesHTTP/2, SPDY e Otimizações Web - Front In Maceió 2014 - Sérgio Lopes
HTTP/2, SPDY e Otimizações Web - Front In Maceió 2014 - Sérgio Lopes
 
Design Responsivo - MobCamp 2014
Design Responsivo - MobCamp 2014Design Responsivo - MobCamp 2014
Design Responsivo - MobCamp 2014
 
Além do responsive design: a mudança de paradigma do design adaptativo e os m...
Além do responsive design: a mudança de paradigma do design adaptativo e os m...Além do responsive design: a mudança de paradigma do design adaptativo e os m...
Além do responsive design: a mudança de paradigma do design adaptativo e os m...
 
Por trás dos frameworks e além do reflection
Por trás dos frameworks e além do reflectionPor trás dos frameworks e além do reflection
Por trás dos frameworks e além do reflection
 
Otimizações de Performance Web: Desafios do Mundo Mobile
Otimizações de Performance Web: Desafios do Mundo MobileOtimizações de Performance Web: Desafios do Mundo Mobile
Otimizações de Performance Web: Desafios do Mundo Mobile
 
Introducao a inteligencia artificial na educacao
Introducao a inteligencia artificial na educacaoIntroducao a inteligencia artificial na educacao
Introducao a inteligencia artificial na educacao
 
Otimizando o time to market - do zero a produção em poucas iterações
Otimizando o time to market - do zero a produção em poucas iteraçõesOtimizando o time to market - do zero a produção em poucas iterações
Otimizando o time to market - do zero a produção em poucas iterações
 
All you need to know about JavaScript loading and execution in the browser - ...
All you need to know about JavaScript loading and execution in the browser - ...All you need to know about JavaScript loading and execution in the browser - ...
All you need to know about JavaScript loading and execution in the browser - ...
 
Design Responsivo por uma Web única
Design Responsivo por uma Web únicaDesign Responsivo por uma Web única
Design Responsivo por uma Web única
 
CDI e as ideias pro futuro do VRaptor
CDI e as ideias pro futuro do VRaptorCDI e as ideias pro futuro do VRaptor
CDI e as ideias pro futuro do VRaptor
 

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

  • 1. Design de Código qualidade a longo prazo Guilherme Silveira @guilhermecaelum
  • 2. Como parar de escrever o lixo do ano que vem Guilherme Silveira @guilhermecaelum
  • 3. aka “chega de código lixo” Guilherme Silveira @guilhermecaelum
  • 4.
  • 6. - líder técnico - treinamentos
  • 7. - líder técnico - treinamentos - online
  • 9. guilherme.silveira@caelum.com.br @guilhermecaelum - líder técnico - treinamentos - online
  • 11. online.caelum.com.br trial hoje (descontão no beta)
  • 12. > 2.3 reviews por resposta
  • 13. online.caelum.com.br trial hoje (descontão no beta)
  • 15. o mais importante em um projeto é escrever código bonito
  • 16. o mais importante em um projeto é escrever código bom
  • 17. quem tem um método zoado aí?
  • 18. Implementation Design Architecture
  • 20. architecture >= design >=
  • 21. architecture >= design >= implementation
  • 24. Browser Controller JPA file upload
  • 25. Browser Controller JPA memory
  • 26. Browser Controller ### cloud ### JPA memory
  • 30. Implementation Design Architecture
  • 31. IOC
  • 33. IOC Usando uma boa prática de design Paulo Silveira DESIGN
  • 34. IOC Usando uma boa prática de design Paulo Silveira DESIGN ARQUITETURA
  • 35. IOC Usando uma boa prática de design Paulo Silveira DESIGN Mudamos a arquitetura e economizamos $$$. ARQUITETURA Sérgio Lopes
  • 36. Architecture Design Implementation
  • 38. architecture <= design <=
  • 39. architecture <= design <= implementation
  • 40. architecture <= design <= implementation architecture >=
  • 41. architecture <= design <= implementation architecture >= design >=
  • 42. architecture <= design <= implementation architecture >= design >= implementation
  • 43. architecture <= design <= implementation architecture >= design >= implementation architecture =
  • 44. architecture <= design <= implementation architecture >= design >= implementation architecture = design =
  • 45. architecture <= design <= implementation architecture >= design >= implementation architecture = design = implementation
  • 46. design arquitetura java, ruby, scala, objective-c, c# servidores, firewalls etc implementação
  • 51. existe implementação
  • 52. a única “coisa” que existe é a implementação.
  • 53. os mais importantes = os devs
  • 54. o mais importante em um projeto é escrever código bom bonito?
  • 55. arquitetura é o mínimo se a arquitetura não é boa, problemão
  • 56.
  • 57. o que sobra? design...
  • 58. o que sobra? design... interface ===> difícil de manter
  • 59. o que sobra? design... interface ===> difícil de manter implementation ===> difícil de manter
  • 61. DESIGN Como seu código se comunica? (design interface de comunicação) IMPLEMENTAÇÃO
  • 62. DESIGN Como seu código se comunica? (design interface de comunicação) Como seu código é executado? (design da implementação) IMPLEMENTAÇÃO
  • 63. veremos code
  • 64.       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?
  • 65.       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
  • 67. 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. 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. 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
  • 70. 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
  • 71. 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
  • 72. 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
  • 73. 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
  • 74. 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
  • 75. 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
  • 77.       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. 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
  • 79. 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
  • 81. Java? muitos ifs?
  • 82. Java? C++? muitos ifs?
  • 83. Java? C++? C? muitos ifs?
  • 84. Java? C++? C? muitos ifs? Basic?
  • 85. Java? C++? C? muitos ifs? Ruby? Basic?
  • 86. Clojure? Java? C++? C? muitos ifs? Ruby? Basic?
  • 87. Clojure? Java? C++? C? muitos ifs? Scala? Ruby? Basic?
  • 88. Clojure? Java? C++? C? muitos This month’s ifs? new language? Scala? Ruby? Basic?
  • 92. Java? C++? variáveis zoadas?
  • 93. Java? C++? C? variáveis zoadas?
  • 94. Java? C++? C? variáveis zoadas? Basic?
  • 95. Java? C++? C? variáveis zoadas? Ruby? Basic?
  • 96. Clojure? Java? C++? C? variáveis zoadas? Ruby? Basic?
  • 97. Clojure? Java? C++? C? variáveis zoadas? Scala? Ruby? Basic?
  • 98. Clojure? Java? C++? C? variáveis This month’s zoadas? new language? Scala? Ruby? Basic?
  • 99. nova
  • 105. nova linguagem novo mindset novo uso idiomático mesmos
  • 106. nova linguagem novo mindset novo uso idiomático mesmos erros
  • 107. complexidade invisivel         def cached_attributes           @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set         end
  • 108. 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
  • 109. 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
  • 110. entendeu?         def cached_attributes           @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set         end
  • 111. uma linha = conciso?
  • 112. uma linha = bonito?
  • 114. complexidade, é natural
  • 115. complexidade, é natural intenção invisível
  • 116. complexidade, é natural intenção invisível é do mal
  • 117. pegô?         def cached_attributes           @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set         end
  • 118. conciso?         def terere           @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set         end
  • 119.       def cached_attributes         @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set       end
  • 120.       def cached_attributes         @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set       end how frequently does flow control appear?
  • 121.       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?
  • 123. sua cobertura mentiu
  • 124. pq?
  • 125.       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. 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?
  • 127. 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?
  • 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 frequently does flow control appear?
  • 129. 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?
  • 130. 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?
  • 132. and now?       def cached_attributes         @cached_attributes ||= columns.select { |c| cacheable_column?(c) } .map { |col| col.name } .to_set       end
  • 133. 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
  • 134. ,
  • 135. enter tarefa do bem
  • 136. 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
  • 137. pela “concisão” menos toques no teclado zoaram meu código       def cached_attributes         @cached_attributes ||= 컬륨.걸라 { |c| 캐시_컬륨?(c) }.맵 { |컬| 컬.이름 }.투샛       end
  • 138. pela “concisão” menos teclas ainda!    def cached_attributes      @ ||= . { | | ?( ) }. { | | . }.    end
  • 139. pela “concisão” menos teclas ainda!    def cached_attributes      @ ||= . { | | ?( ) }. { | | . }.    end
  • 140. pela “concisão” menos teclas ainda!    def cached_attributes      @ ||= . { | | ?( ) }. { | | . }.    end
  • 141. não é fazer código bonito
  • 142. não é fazer código bonito é não fazer deixar cocozinho
  • 143. concisão = com o mínimo de palavras, deixar claro tarefa do bem
  • 144. o que acontece?        Client client = clients.lookup(15L); client.getName();
  • 145. o que acontece? requisição remota?        Client client = clients.lookup(15L); client.getName();
  • 146. o que acontece? requisição remota? EJB 2 hell!        Client client = clients.lookup(15L); client.getName();
  • 147. o que acontece? requisição remota? EJB 2 hell!        Client client = clients.lookup(15L); client.getName();
  • 148. o que acontece? requisição remota? EJB 2 hell!        Client client = clients.lookup(15L); client.getName(); Quer ver uma mágica?
  • 149. o que acontece? requisição HTTP? inferno de “rest” proxy aka active resource        Client client = clients.lookup(15L); client.getName();
  • 150. o que acontece se? client.save def save database.save(this) end
  • 151. o que acontece se? an HTTP remote request!? client.save def save database.save(this) end
  • 152. o que acontece se? an HTTP remote request!? ClientRule.checkUniqueEnroll is invoked!? client.save def save database.save(this) end
  • 153. o que acontece se? an HTTP remote request!? ClientRule.checkUniqueEnroll is invoked!? “invisible invocation(s)” pattern client.save def save database.save(this) end
  • 156. composition is good if invisible,
  • 157. composition is good if invisible, is evil
  • 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.     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.     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.     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.     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.     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.     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.     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.     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
  • 167.     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
  • 170.   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);   }
  • 171.   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;   }
  • 172.   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;   }
  • 173.   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;   }
  • 174.   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;   }
  • 175.   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);;   }
  • 176.   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);;   }
  • 177.   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);;   }
  • 178. um “if if if if if if” dói (aka. sanduíche íche íche pattern)
  • 179. ninguém acerta de primeira
  • 180. esse dói? select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo
  • 181. esse dói? select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo Maurício Aniche
  • 182. 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
  • 183. 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
  • 184. 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
  • 185. sua cobertura mente
  • 186. select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2
  • 187. select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2
  • 188. select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2
  • 189. Facinho... select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2
  • 190. Facinho... select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2 Martin Fowler
  • 191. Facinho... select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2 sql também é linguagem... Martin Fowler
  • 192. 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
  • 193. menos de 5 testes não garanto mas a cobertura diz “100%”... mentirosa ...
  • 194. coverage 100% would be 128 tests?
  • 195. conscientizar-se da complexidade de nosso código Jim Webber
  • 196. conscientizar-se da complexidade de nosso código não adianta esconder o spaguetti, ele continua lá. Jim Webber
  • 197. conscientizar-se da complexidade de nosso código não adianta esconder o spaguetti, ele continua lá. tem que deixar explícito! Jim Webber
  • 198. OO 101
  • 199. se você tem que executar algo sempre que cria um Cliente?
  • 200. se você tem que executar algosempre que cria um Cliente?
  • 201. se você tem que executar algo sempre que cria um Cliente?
  • 202. declare dependência e código no CONSTRUTOR
  • 203. declare dependência e código no CONSTRUTOR mas e no Rails, Javabeans, Hibernate, etc?
  • 204. java (the javabeans way) rails (the ruby way) dumb constructor dumb constructor getter+setter attr_accessor the scala way dumb constructor val
  • 205. java (the javabeans way) rails (the ruby way) dumb constructor dumb constructor public variable public variable the scala way dumb constructor public variable
  • 206. O padrão de OO no mercado é a “orgia dos objetos” pattern. Todo mundo pega todo mundo.
  • 207. Duvidou? Spring: CTRL+F static Rails: ActiveRecord.methods.size
  • 209. a new scala project vraptor + hibernate
  • 213. post post post Ah! Quebrou encapsulamento dá nisso!
  • 214. post post post Ah! Quebrou encapsulamento dá nisso!
  • 215. post post post Ah! Quebrou encapsulamento dá nisso!
  • 216. post post post Ah! Quebrou encapsulamento dá nisso!
  • 217. post post post Ah! Quebrou encapsulamento dá nisso!
  • 218. Posso agulhar? post post post Ah! Quebrou encapsulamento dá nisso!
  • 219. no lugar ADEQUADO se eu mudar, eu quebro... mas ai tudo bem! encapsulamento++ demeter++
  • 220. no lugar ADEQUADO se eu mudar, eu quebro... mas ai tudo bem! encapsulamento++ demeter++
  • 223. 1. implementação existe, o resto é interpretação
  • 224. 2. código é complexo
  • 225. 2. código é complexo faça bunitu! não se preocupe com fofurice
  • 226. 3. esconder intenção não é simplificar
  • 227. 4. se é difícil de testar, é difícil de usar
  • 228. 5. deixe seus devs aprender e melhorar
  • 229. 6. ao mudar linguagem verifique 3 vezes os princípios
  • 233. 7. refactor toda hora para o melhor não para o mais fofo
  • 234. lembre-se pair-programming brown bag refactoring code review
  • 235. @guilhermecaelum guilherme.silveira@caelum.com.br http://online.caelum.com.br te vejo lá
  • 236. sobrou tempo? seu código hibernate
  • 237. presentation code != domain code controller model view if discussion.author==myself || myself.roles[:moderator]
  • 238. presentation code != domain code controller model if discussion.author==myself view myself.roles[:moderator] if mysel.canEdit(discussion)
  • 239. esses ifs não ficam repetidos em várias views
  • 240. abra *.jsp, *.erb, *.ssp, *.similares CTRL+F, if com algo != de boolean CTRL+F, if com chamada != de boolean

Notas do Editor

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. 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
  26. ... 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
  27. 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
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n
  103. \n
  104. \n
  105. \n
  106. \n
  107. \n
  108. \n
  109. \n
  110. \n
  111. \n
  112. \n
  113. \n
  114. \n
  115. \n
  116. \n
  117. \n
  118. \n
  119. \n
  120. \n
  121. \n
  122. \n
  123. \n
  124. \n
  125. \n
  126. \n
  127. \n
  128. \n
  129. \n
  130. \n
  131. \n
  132. \n
  133. \n
  134. \n
  135. \n
  136. \n
  137. \n
  138. \n
  139. \n
  140. \n
  141. \n
  142. \n
  143. \n
  144. \n
  145. \n
  146. \n
  147. \n
  148. \n
  149. \n
  150. \n
  151. \n
  152. \n
  153. \n
  154. \n
  155. \n
  156. \n
  157. \n
  158. \n
  159. \n
  160. \n
  161. \n
  162. \n
  163. \n
  164. \n
  165. \n
  166. \n
  167. \n
  168. \n
  169. \n
  170. \n
  171. \n
  172. \n
  173. \n
  174. \n
  175. \n
  176. \n
  177. \n
  178. \n
  179. \n
  180. \n
  181. \n
  182. \n
  183. \n
  184. \n
  185. \n
  186. \n
  187. \n
  188. \n
  189. \n
  190. \n
  191. \n
  192. \n
  193. \n
  194. \n
  195. \n
  196. \n
  197. \n
  198. \n
  199. \n
  200. \n
  201. \n
  202. \n
  203. \n
  204. \n
  205. \n
  206. \n
  207. \n
  208. \n
  209. \n
  210. \n
  211. \n
  212. \n
  213. \n
  214. \n
  215. \n
  216. \n
  217. \n
  218. \n
  219. \n
  220. \n
  221. \n
  222. \n
  223. \n
  224. \n
  225. \n
  226. \n
  227. \n
  228. \n
  229. \n
  230. \n
  231. \n
  232. \n
  233. \n
  234. \n
  235. \n
  236. \n
  237. \n
  238. \n
  239. \n
  240. \n
  241. \n
  242. \n
  243. \n
  244. \n
  245. \n
  246. \n