SlideShare une entreprise Scribd logo
1  sur  160
Design de Código
qualidade a longo prazo
       Guilherme Silveira
       @guilhermecaelum
Design de código: qualidade que faz a diferença, qcon 2011
o difícil de um projeto
 é implementar bem
Implementação




   Design




 Arquitetura
Implementação




   Design




 Arquitetura
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
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
design                             arquitetura



    java, ruby, scala, objective-c, c#
        servidores, firewalls etc
            implementação
(s
arquitetura toda bem definida é muito bonita...
arquitetura toda bem definida é muito bonita...
       mas nem sempre é fácíl entender
A única coisa que existe
  é a implementação
o difícil de um projeto
 é implementar bem
Interpreto o código através de como
                  ele se comunica.


ver através dos olhos
      de design
ver através dos olhos
    da arquitetura
         Interpreto o código através de como
        partes do sistema influenciam outras. e
            caracteristicas que nascem disso
várias maneiras
de ver o código
design := uma
   interpretação

arquitetura := outra
   interpretação
não posso falar de arquitetura ou de design
      sem falar de implementação
.
arquitetura é o mínimo
se a arquitetura não atende, não há conversa
o que sobra é pensarmos no design...

de interface ===> dificil manutenção
 de código ===> dificil manutenção
veremos   código
      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
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
variáveis
         zoadas?

Nico Steppat
variáveis
         zoadas?
               Non. Nonca vi.




Nico Steppat
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
entendeu?

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


            mas essa linha não cabe nem em slide!!!!!

                           vergonha
quantos fors tem aqui?


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


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


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




                                                   for
quantos fors tem aqui?


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



                                              UMA LINHA
                                                for
quantos fors tem aqui?


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



                                              UMA LINHA
                                                for
                                                   if
quantos fors tem aqui?


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



                                              UMA LINHA
                                                 for
                                                for
                                                   if
quantos fors tem aqui?


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



                                              UMA LINHA
                                                 for
                                                  for
                                                for
                                                   if
quantos fors tem aqui?


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



                                              UMA LINHA
                                                 for
                                                  for
                                                for
                                                 oops... if
                                                   if
quantos fors tem aqui?


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



                                              UMA LINHA
                                                 for
                                                  for
                                                for
                                                 oops... if
                                                   if



                                                         Mein Gott. Coisa assim nonca vi!
QUANTOS TESTES PRECISA?


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


     def cached_attributes
       @cached_attributes ||= columns.select { |c| cacheable_column?(c) }
                                     .map { |col| col.name }
                                     .to_set
     end
,
dê   enter
        tarefa do bem
menos palavras zoou seu código
                  um enter não mata

        def cached_attributes
          @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set
        end
concisão = com o mínimo de
   palavras, deixar claro


               tarefa do bem
concisão =
baixar o nível =
concisão = eu tô bem
baixar o nível = ˆo b3w




     especialista em linguagem de programação miguxês
cliente.a
cliente.a




      meta-aspecto-meta-aspecto
            programador
cliente.a


Quer ver uma mágica?




                       meta-aspecto-meta-aspecto
                             programador
cliente.a
acontece o método b, c, d, e, f, ...




 Quer ver uma mágica?




                        meta-aspecto-meta-aspecto
                              programador
cliente.a
    acontece o método b, c, d, e, f, ...




     Quer ver uma mágica?


Meta meta meta meta programming.




                            meta-aspecto-meta-aspecto
                                  programador
       # Deletes the records according to the <tt>:dependent</tt> option.
       def delete_records(records, method)
         if method == :destroy
           records.each { |r| r.destroy }
           update_counter(-records.length) unless inverse_updates_counter_cache?
         else
           keys = records.map { |r| r[reflection.association_primary_key] }
           scope = scoped.where(reflection.association_primary_key => keys)

           if method == :delete_all
             update_counter(-scope.delete_all)
           else
             update_counter(-scope.update_all(reflection.foreign_key => nil))
           end
         end
       end
quem escreveu?
meu amigo
 sérgio
       # Deletes the records according to the <tt>:dependent</tt> option.
       def delete_records(records, method)
         if method == :destroy
           records.each { |r| r.destroy }
           update_counter(-records.length) unless inverse_updates_counter_cache?
         else
           keys = records.map { |r| r[reflection.association_primary_key] }
           scope = scoped.where(reflection.association_primary_key => keys)

           if method == :delete_all
             update_counter(-scope.delete_all)
           else
             update_counter(-scope.update_all(reflection.foreign_key => nil))
           end
         end
       end
um “if if if if if if” dói
    (aka. sanduíche íche íche pattern)
ninguém acerta de primeira

            É vital refatorar!
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
O objetivo não é usar outro, ou
 esconder o controle de fluxo.
Quebre ele em dois. Mais faceis de
            entender
O objetivo não é usar outro, ou
 esconder o controle de fluxo.
Quebre ele em dois. Mais faceis de
            entender
teste é moda, é positivo, é importante,
        e garante várias coisas
mas
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
dá para fazer lógica sem fazer lógica? não dá!
menos de 5 testes não garanto

mas a cobertura diz “100%”...


mentirosa                       ...
de verdade, não assim:

 - teste sem assert
 - teste verifica que uma string é passada
 - teste “salva”
Um código é dificil de entender
         pois tem fluxos.
São os fluxos que deixam ele dificil.
tarefa do bem



fluxo “invisíveis”,   TESTE
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
tarefa do bem
 para trabalhar com algo complexo
não se deve fingir que ele não existe
 mas ensinar a resolver o problema
esconder o complexo é
    julgar alguem incapaz

a complexidade continuará lá...
    agora com um gargalo
pior ainda, quem usa ele, vai usar mal usado
   pois não sabe o que esta acontecendo
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?
construtor não faz nada
atributos públicos (get/set/attr)
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
Lição de Casa?

 Apague um getter e um setter.
Um atributo. Controle o escopo.
  Veja a caca que já está feita...
relacionamentos



 classe Clientes?
relacionamentos

@OneToMany
List<Usuario> clientes;
+ 10 metodos

        classe Clientes?
relacionamentos
                          has_many :clientes, :class => Us
                          +10 metodos
@OneToMany
List<Usuario> clientes;
+ 10 metodos

        classe Clientes?
classe Clientes
classe Clientes


public Clientes getClientes() {
  return new Clientes(this.clientes);
}
classe Clientes
                            def clientes
                             Clientes.new(super)
                            end

public Clientes getClientes() {
  return new Clientes(this.clientes);
}
classe Clientes
                            def clientes
                             Clientes.new(super)
                            end

public Clientes getClientes() {
  return new Clientes(this.clientes);
}

              + encapsulamento
a questao da web nao ser OO
              a web eh outra coisa
          o outro sistema é outra coisa




CLIENTE
a questao da web nao ser OO
              a web eh outra coisa
          o outro sistema é outra coisa




CLIENTE
a questao da web nao ser OO
              a web eh outra coisa
          o outro sistema é outra coisa




CLIENTE
a questao da web nao ser OO
              a web eh outra coisa
          o outro sistema é outra coisa




CLIENTE                                   BANCO
a questao da web nao ser OO
              a web eh outra coisa
          o outro sistema é outra coisa




CLIENTE                                   BANCO
invisivel (esconder) ou
  clara e bem definida
frameworks
component based   escondem a web...
frameworks
component based      escondem a web...



           Mas e se minha preocupação é fazer um
           sistema otimizado para a web? (keynote
                         do sérgio)
frameworks
component based      escondem a web...



           Mas e se minha preocupação é fazer um
           sistema otimizado para a web? (keynote
                         do sérgio)




                         booooo!
AR mistureba. menos camadas :)

                   modelo
                   domínio
                                         banco
                   modelo
                    banco
                   queries
                    inserts
todo mundo tem
  acesso a tudo

                  ESCOPO
adiciona uma camda :(. entra o controle de escopo. :)



                                                   banco



      modelo do
       domínio




     ESCOPO                  ESCOPO
adiciona uma camda :(. entra o controle de escopo. :)


                              modelo
                               banco               banco

                              queries
                              inserts
      modelo do
       domínio




     ESCOPO                  ESCOPO
como moldar nosso sistema entao?
modele REGRAS
Qualquer coisa que eu
  mudar, quebra...
Qualquer coisa que eu
  mudar, quebra...
Qualquer coisa que eu
  mudar, quebra...
Qualquer coisa que eu
  mudar, quebra...
Qualquer coisa que eu
  mudar, quebra...
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++
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
sem arquitetura
   adequada
não há conversa
o código existe
o resto, é interpretação
código é complicado
esconder o complicado
   não é simplificar
se é difícil de testar,
o código tem débito
@guilhermecaelum
http://www.caelum.com.br
http://online.caelum.com.br




obrigado

Contenu connexe

Similaire à Design de código: qualidade que faz a diferença, qcon 2011

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
 
Iteraveis e geradores em Python
Iteraveis e geradores em PythonIteraveis e geradores em Python
Iteraveis e geradores em PythonLuciano Ramalho
 
Estruturas de dados em Python
Estruturas de dados em PythonEstruturas de dados em Python
Estruturas de dados em PythonRicardo Paiva
 
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
 
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 funcional tipada: uma introdução
Programação funcional tipada: uma introduçãoProgramação funcional tipada: uma introdução
Programação funcional tipada: uma introduçãoArthur Xavier
 
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
 

Similaire à Design de código: qualidade que faz a diferença, qcon 2011 (11)

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
 
Iteraveis e geradores em Python
Iteraveis e geradores em PythonIteraveis e geradores em Python
Iteraveis e geradores em Python
 
Estruturas de dados em Python
Estruturas de dados em PythonEstruturas de dados em Python
Estruturas de dados em Python
 
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
 
Fundamentos de C#
Fundamentos de C#Fundamentos de C#
Fundamentos de C#
 
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 funcional tipada: uma introdução
Programação funcional tipada: uma introduçãoProgramação funcional tipada: uma introdução
Programação funcional tipada: uma introdução
 
Object Oriented Programming
Object Oriented ProgrammingObject Oriented Programming
Object Oriented Programming
 
Python Class
Python ClassPython Class
Python Class
 
Unidade7 1
Unidade7 1Unidade7 1
Unidade7 1
 
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
 

Plus 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
 
Desafios de Performance Web - BrazilJS
Desafios de Performance Web - BrazilJSDesafios de Performance Web - BrazilJS
Desafios de Performance Web - BrazilJSCaelum
 
Performance na web: o modelo RAIL e outras novidades
Performance na web: o modelo RAIL e outras novidadesPerformance na web: o modelo RAIL e outras novidades
Performance na web: o modelo RAIL e outras novidadesCaelum
 
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
 
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
 
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
 
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
 
Wsrest 2013
Wsrest 2013Wsrest 2013
Wsrest 2013Caelum
 
Design Responsivo por uma Web única
Design Responsivo por uma Web únicaDesign Responsivo por uma Web única
Design Responsivo por uma Web únicaCaelum
 
Os Caminhos de uma Estratégia Mobile
Os Caminhos de uma Estratégia MobileOs Caminhos de uma Estratégia Mobile
Os Caminhos de uma Estratégia MobileCaelum
 
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
 

Plus de Caelum (20)

Performance Web além do carregamento
Performance Web além do carregamentoPerformance Web além do carregamento
Performance Web além do carregamento
 
Desafios de Performance Web - BrazilJS
Desafios de Performance Web - BrazilJSDesafios de Performance Web - BrazilJS
Desafios de Performance Web - BrazilJS
 
Performance na web: o modelo RAIL e outras novidades
Performance na web: o modelo RAIL e outras novidadesPerformance na web: o modelo RAIL e outras novidades
Performance na web: o modelo RAIL e outras novidades
 
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
 
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
 
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
 
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 - ...
 
Wsrest 2013
Wsrest 2013Wsrest 2013
Wsrest 2013
 
Design Responsivo por uma Web única
Design Responsivo por uma Web únicaDesign Responsivo por uma Web única
Design Responsivo por uma Web única
 
Os Caminhos de uma Estratégia Mobile
Os Caminhos de uma Estratégia MobileOs Caminhos de uma Estratégia Mobile
Os Caminhos de uma Estratégia Mobile
 
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...
 

Design de código: qualidade que faz a diferença, qcon 2011

  • 1. Design de Código qualidade a longo prazo Guilherme Silveira @guilhermecaelum
  • 3. o difícil de um projeto é implementar bem
  • 4. Implementação Design Arquitetura
  • 5. Implementação Design Arquitetura
  • 6. IOC
  • 8. IOC Usando uma boa prática de design Paulo Silveira DESIGN
  • 9. IOC Usando uma boa prática de design Paulo Silveira DESIGN ARQUITETURA
  • 10. IOC Usando uma boa prática de design Paulo Silveira DESIGN Mudamos a arquitetura e economizamos $$$. ARQUITETURA Sérgio Lopes
  • 12. DESIGN Como seu código se comunica? (design interface de comunicação) IMPLEMENTAÇÃO
  • 13. DESIGN Como seu código se comunica? (design interface de comunicação) Como seu código é executado? (design da implementação) IMPLEMENTAÇÃO
  • 14. design arquitetura java, ruby, scala, objective-c, c# servidores, firewalls etc implementação
  • 15. (s
  • 16. arquitetura toda bem definida é muito bonita...
  • 17. arquitetura toda bem definida é muito bonita... mas nem sempre é fácíl entender
  • 18. A única coisa que existe é a implementação
  • 19. o difícil de um projeto é implementar bem
  • 20. Interpreto o código através de como ele se comunica. ver através dos olhos de design
  • 21. ver através dos olhos da arquitetura Interpreto o código através de como partes do sistema influenciam outras. e caracteristicas que nascem disso
  • 23. design := uma interpretação arquitetura := outra interpretação
  • 24. não posso falar de arquitetura ou de design sem falar de implementação
  • 25. .
  • 26. arquitetura é o mínimo se a arquitetura não atende, não há conversa
  • 27. o que sobra é pensarmos no design... de interface ===> dificil manutenção de código ===> dificil manutenção
  • 28. veremos código
  • 29.       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?
  • 30.       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
  • 31. 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
  • 32. 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
  • 33. 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
  • 34. 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
  • 35. 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
  • 36. 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
  • 37. 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
  • 38. 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
  • 39. 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
  • 41.       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
  • 42. 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
  • 43. 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
  • 44. variáveis zoadas? Nico Steppat
  • 45. variáveis zoadas? Non. Nonca vi. Nico Steppat
  • 46. complexidade invisivel         def cached_attributes           @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set         end
  • 47. 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
  • 48. 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
  • 49. entendeu?         def cached_attributes           @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set         end
  • 50. entendeu?       def cached_attributes         @cached_attributes ||= columns.select { |c| cheable_column?(c) }.map { |col| col.name }.to_set       end mas essa linha não cabe nem em slide!!!!! vergonha
  • 51. quantos fors tem aqui?       def cached_attributes         @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set       end
  • 52. quantos fors tem aqui?       def cached_attributes         @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set       end
  • 53. quantos fors tem aqui?       def cached_attributes         @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set       end for
  • 54. quantos fors tem aqui?       def cached_attributes         @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set       end UMA LINHA for
  • 55. quantos fors tem aqui?       def cached_attributes         @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set       end UMA LINHA for if
  • 56. quantos fors tem aqui?       def cached_attributes         @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set       end UMA LINHA for for if
  • 57. quantos fors tem aqui?       def cached_attributes         @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set       end UMA LINHA for for for if
  • 58. quantos fors tem aqui?       def cached_attributes         @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set       end UMA LINHA for for for oops... if if
  • 59. quantos fors tem aqui?       def cached_attributes         @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set       end UMA LINHA for for for oops... if if Mein Gott. Coisa assim nonca vi!
  • 60. QUANTOS TESTES PRECISA?       def cached_attributes         @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set       end
  • 61. e agora?      def cached_attributes        @cached_attributes ||= columns.select { |c| cacheable_column?(c) } .map { |col| col.name } .to_set      end
  • 62. ,
  • 63. enter tarefa do bem
  • 64. menos palavras zoou seu código um enter não mata         def cached_attributes           @cached_attributes ||= columns.select { |c| cacheable_column?(c) }.map { |col| col.name }.to_set         end
  • 65. concisão = com o mínimo de palavras, deixar claro tarefa do bem
  • 67. concisão = eu tô bem baixar o nível = ˆo b3w especialista em linguagem de programação miguxês
  • 69. cliente.a meta-aspecto-meta-aspecto programador
  • 70. cliente.a Quer ver uma mágica? meta-aspecto-meta-aspecto programador
  • 71. cliente.a acontece o método b, c, d, e, f, ... Quer ver uma mágica? meta-aspecto-meta-aspecto programador
  • 72. cliente.a acontece o método b, c, d, e, f, ... Quer ver uma mágica? Meta meta meta meta programming. meta-aspecto-meta-aspecto programador
  • 73.        # Deletes the records according to the <tt>:dependent</tt> option.        def delete_records(records, method)          if method == :destroy            records.each { |r| r.destroy }            update_counter(-records.length) unless inverse_updates_counter_cache?          else            keys = records.map { |r| r[reflection.association_primary_key] }            scope = scoped.where(reflection.association_primary_key => keys)            if method == :delete_all              update_counter(-scope.delete_all)            else              update_counter(-scope.update_all(reflection.foreign_key => nil))            end          end        end
  • 76.        # Deletes the records according to the <tt>:dependent</tt> option.        def delete_records(records, method)          if method == :destroy            records.each { |r| r.destroy }            update_counter(-records.length) unless inverse_updates_counter_cache?          else            keys = records.map { |r| r[reflection.association_primary_key] }            scope = scoped.where(reflection.association_primary_key => keys)            if method == :delete_all              update_counter(-scope.delete_all)            else              update_counter(-scope.update_all(reflection.foreign_key => nil))            end          end        end
  • 77. um “if if if if if if” dói (aka. sanduíche íche íche pattern)
  • 78. ninguém acerta de primeira É vital refatorar!
  • 79. esse dói? select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo
  • 80. esse dói? select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo Maurício Aniche
  • 81. 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
  • 82. 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
  • 83. 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
  • 84. O objetivo não é usar outro, ou esconder o controle de fluxo. Quebre ele em dois. Mais faceis de entender
  • 85. O objetivo não é usar outro, ou esconder o controle de fluxo. Quebre ele em dois. Mais faceis de entender
  • 86. teste é moda, é positivo, é importante, e garante várias coisas
  • 87. mas
  • 88. sua cobertura mente
  • 89. select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2
  • 90. select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2
  • 91. select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2
  • 92. Facinho... select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2
  • 93. Facinho... select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2 Martin Fowler
  • 94. Facinho... select * from Contatos where a=b or (c=d && e=f) order by primeiro_campo limit 2 sql também é linguagem... Martin Fowler
  • 95. 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
  • 96. dá para fazer lógica sem fazer lógica? não dá!
  • 97. menos de 5 testes não garanto mas a cobertura diz “100%”... mentirosa ...
  • 98. de verdade, não assim: - teste sem assert - teste verifica que uma string é passada - teste “salva”
  • 99. Um código é dificil de entender pois tem fluxos. São os fluxos que deixam ele dificil.
  • 100. tarefa do bem fluxo “invisíveis”, TESTE
  • 101. conscientizar-se da complexidade de nosso código Jim Webber
  • 102. conscientizar-se da complexidade de nosso código não adianta esconder o spaguetti, ele continua lá. Jim Webber
  • 103. conscientizar-se da complexidade de nosso código não adianta esconder o spaguetti, ele continua lá. tem que deixar explícito! Jim Webber
  • 104. tarefa do bem para trabalhar com algo complexo não se deve fingir que ele não existe mas ensinar a resolver o problema
  • 105. esconder o complexo é julgar alguem incapaz a complexidade continuará lá... agora com um gargalo
  • 106. pior ainda, quem usa ele, vai usar mal usado pois não sabe o que esta acontecendo
  • 107. se você tem que executar algo sempre que cria um Cliente?
  • 108. se você tem que executar algosempre que cria um Cliente?
  • 109. se você tem que executar algo sempre que cria um Cliente?
  • 110. declare dependência e código no CONSTRUTOR
  • 111. declare dependência e código no CONSTRUTOR mas e no Rails, Javabeans, Hibernate, etc?
  • 112. construtor não faz nada atributos públicos (get/set/attr)
  • 113. O padrão de OO no mercado é a “orgia dos objetos” pattern. Todo mundo pega todo mundo.
  • 114. Duvidou? Spring: CTRL+F static Rails: ActiveRecord.methods.size
  • 115. Lição de Casa? Apague um getter e um setter. Um atributo. Controle o escopo. Veja a caca que já está feita...
  • 118. relacionamentos has_many :clientes, :class => Us +10 metodos @OneToMany List<Usuario> clientes; + 10 metodos classe Clientes?
  • 120. classe Clientes public Clientes getClientes() { return new Clientes(this.clientes); }
  • 121. classe Clientes def clientes Clientes.new(super) end public Clientes getClientes() { return new Clientes(this.clientes); }
  • 122. classe Clientes def clientes Clientes.new(super) end public Clientes getClientes() { return new Clientes(this.clientes); } + encapsulamento
  • 123. a questao da web nao ser OO a web eh outra coisa o outro sistema é outra coisa CLIENTE
  • 124. a questao da web nao ser OO a web eh outra coisa o outro sistema é outra coisa CLIENTE
  • 125. a questao da web nao ser OO a web eh outra coisa o outro sistema é outra coisa CLIENTE
  • 126. a questao da web nao ser OO a web eh outra coisa o outro sistema é outra coisa CLIENTE BANCO
  • 127. a questao da web nao ser OO a web eh outra coisa o outro sistema é outra coisa CLIENTE BANCO
  • 128. invisivel (esconder) ou clara e bem definida
  • 129. frameworks component based escondem a web...
  • 130. frameworks component based escondem a web... Mas e se minha preocupação é fazer um sistema otimizado para a web? (keynote do sérgio)
  • 131. frameworks component based escondem a web... Mas e se minha preocupação é fazer um sistema otimizado para a web? (keynote do sérgio) booooo!
  • 132. AR mistureba. menos camadas :) modelo domínio banco modelo banco queries inserts todo mundo tem acesso a tudo ESCOPO
  • 133. adiciona uma camda :(. entra o controle de escopo. :) banco modelo do domínio ESCOPO ESCOPO
  • 134. adiciona uma camda :(. entra o controle de escopo. :) modelo banco banco queries inserts modelo do domínio ESCOPO ESCOPO
  • 135. como moldar nosso sistema entao?
  • 137. Qualquer coisa que eu mudar, quebra...
  • 138. Qualquer coisa que eu mudar, quebra...
  • 139. Qualquer coisa que eu mudar, quebra...
  • 140. Qualquer coisa que eu mudar, quebra...
  • 141. Qualquer coisa que eu mudar, quebra...
  • 143. post post post Ah! Quebrou encapsulamento dá nisso!
  • 144. post post post Ah! Quebrou encapsulamento dá nisso!
  • 145. post post post Ah! Quebrou encapsulamento dá nisso!
  • 146. post post post Ah! Quebrou encapsulamento dá nisso!
  • 147. post post post Ah! Quebrou encapsulamento dá nisso!
  • 148. Posso agulhar? post post post Ah! Quebrou encapsulamento dá nisso!
  • 149. no lugar ADEQUADO se eu mudar, eu quebro... mas ai tudo bem! encapsulamento++ demeter++
  • 150. no lugar ADEQUADO se eu mudar, eu quebro... mas ai tudo bem! encapsulamento++ demeter++
  • 151. presentation code != domain code controller model view if discussion.author==myself || myself.roles[:moderator]
  • 152. presentation code != domain code controller model if discussion.author==myself view myself.roles[:moderator] if mysel.canEdit(discussion)
  • 153. esses ifs não ficam repetidos em várias views
  • 154. abra *.jsp, *.erb, *.ssp, *.similares CTRL+F, if com algo != de boolean CTRL+F, if com chamada != de boolean
  • 155. sem arquitetura adequada não há conversa
  • 156. o código existe o resto, é interpretação
  • 158. esconder o complicado não é simplificar
  • 159. se é difícil de testar, o código tem débito

Notes de l'éditeur

  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. \n
  26. \n
  27. \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