Desenvolvimento
De Padawan a Jedi
por Rodrigo Allemand em Aug.10, 2009, em Desenvolvimento
Recentemente um desenvolvedor da minha equipe e eu estavamos conversando sobre como dar soluções bem feitas. Ele se queixava de demorar muito para achar uma solução, construindo e re-construindo por muitas vezes um determinado pedaço de código até chegar a uma solução realmente boa. Refactoring é a saida para um bom código, mas existem outos pontos de falha na sua maneira de programar.
O conhecimento hoje é uma jóia que está a apenas alguns cliques de todos nós. Hoje em dia se aprende desde a fazer arroz a até uma bomba nuclear. Mas como adquirir conhecimento na nossa área? Como programar melhor? Como otimizar o seu tempo de desenvolvimento? Muitas dessas respostas estão a disposição de todos os programadores desde o inicio do ano 2000, numa das melhores -senão a melhor – compilações de boas práticas para a área de desenvolvimento de software.
Trata-se do livro The Pragmatic Programmer, From Journeyman to Master, de Andrew Hunt e David Thomas. Eu já li o livro pelo menos umas duas vezes (falando nisso, preciso entregar o livro ao dono!) e recomendo a quem não leu ainda, seja ele junior ou sênior.
O livro traz uma série de dicas sobre como se tornar um bom programador. Segue um pequeno resumo.
- Preocupe-se em fazer um código bom
- Pense!! Critique o seu trabalho
- Dê opções, não dê desculpas.
- Conserte falhas ao encontrar a falha
- Seja um catalizador de mudanças
- Lembre-se o ‘porquê’ do projeto
- Faça da qualidade um requerimento
- Invista regularmente no seu portifólio de conhecimento
- Analise e critique o que você ouve e vê
- É o que você fala e COMO você fala
- DRY – Don’t Repeat Yourself
- Faça facil para ser reutilizavel
- Elimine efeitos entre coisas não relacionadas
- Não existem decisões finais
- Use traçantes para achar o alvo
- Prototipar para aprender
- Programe para o problema do domÃnio usando a linguagem do domÃnio
- Estime para evitar supresas
- Itere o cronograma com o código
- Deixe o conhecimento em arquivos textos
- Use o poder das linhas de comando
- Use BEM apenas um editor
- Sempre use um controlador de versão
- Resolva o problema, não a culpa
- Não entre em pânico ao debugar
- O problema normalmente não é no ’select’
- Não assuma algo, prove!
- Aprenda uma linguagem de manipulação de texto
- Excreva código que escreva código
- Não, você não pode escrever softwares perfeitos. Proteja o seu código.
- Desenhe soluções baseadas em contratos
- Pegue os problemas precocemente. Teste desde o inicio.
- Use asserções para prevenir o impossivel
- Use exceções apenas para o excepcional
- Termine o que começou
- Minimize acoplamentos entre módulos
- Configure! Não integre!
- Coloque abstração no código e detalhe no metadata
- Analise o workflow para melhorar a concorrências
- Desenhe usando serviços
- Sempre desenhe pensando em concorrência
- Separe a visão do modelo
- Desenhe e conheça o fluxo da informação
- Não programe por concidência
- Estime a complexidade dos seus códigos
- Teste as suas estimações em unidades reais
- Refatore frequentemente, agora e sempre!
- Desenvolva para os testes
- Teste o seu software, ou os usuários testarão
- Não use geradores de código que você não entenda o que foi gerado
- Não apenas leia os requisitos. Mergulhe neles. Escave eles!
- Trabalhe com um usuário para pensar como um usuário
- Abstrações sobrevivem mais do que os detalhes
- Crie um glossário de projeto
- Ache, pense e pese as ‘necessidades’
- Comece quando estiver pronto!
- Algumas coisas são melhores prontas do que descritas
- Não seja escravo da formalidade
- Ferramentas caras não produzem as melhores arquiteturas
- Organize o time por funcionalidades, e não por funções.
- Automatize o que puder ser automatizado.
- Teste frequentemente e automaticamente
- Só está pronto quando o teste roda com sucesso
- Use sabotadores para testar o seu teste
- Não teste apenas o código. Teste as situações do domÃnio
- Ache erros apenas uma vez
- Escreva documentos com os mesmos princÃpios que vc escreve código
- Não separe tanto a documentação do código
- Exceda a espectativa do seu cliente
- Assine o seu trabalho
PS: Qualquer duvida, só comentar que eu detalho os itens.
Comente e Recomende!!
DDD – Entidades e afins
por Rodrigo Allemand em Mar.03, 2009, em DDD, Desenvolvimento
A peça chave do DDD é a Entidade (Entity).
Entidade é um objeto com um significado para o domÃnio sendo modelado e que possui uma identidade.
No exemplo dado no decorrer da série de post, basicamente, estas seriam as nossas entidades. Repare que todas as classes possuem uma identidade (o campo ID de cada classe). Isso define uma Entidade: a sua identificação única!
Pensando em um modelo relacional, basicamente, cada entidade representa um registro de uma tabela e as suas referências e dependências. Mas preste a atenção: um modelo relacional é diferente de um modelo de entidades, já que existem diferenças em cada mundo. Veja, por exemplo, a tabela Workflow: não existe referencia a ela como uma classe, mas existe uma coleção, dentro da entidade de Status que referencia esta associação.
DTO x TO x VO x Entidade x Pojo x JavaBean
Vc já ouviu falar de DTO (Data Transfer Object), correto?
E de TO (Transfer Object)?
E de VO (Value Object)?
E de POJO (Plain Old Java Object)?
E de Java Bean?
Se vc acha que é tudo a mesma coisa, vc está enganado!
TO foi citado pelo grupo Core J2EE Patterns inicialmente e foi desenhado para ser usado quando aplicações precdisam se comunicar com EJBs, reduzindo a quantidade de métodos a serem chamados.
DTO segue um proncÃpio parecido, só não cita EJB e foi descrito por Martin Fowler.
Básicamente, TO e DTO são a mesma coisa, um monte de campos com um bando de métodos acessores (Get e Set) para trafegar informação entre dois “extremos”.
Fowler ainda vai adiante e escreve:
Data Transfer Object is one of those objects our mothers told us never to write. It’s often little more than a bunch of fields and the getters and setters for them. The value of this usually hateful beast is that it
result you need to reduce the number of calls, and that means that you need to transfer more data with each d to procall. One way to do this is to use lots of parameters. However, this is often awkwaronly a single value.often impossible with languages such as Java that return The solution Mels How It Works In many ways, amore than a bun
allows you to move several pieces of information over a network in a single call?a trick that’s essential for
tributed systems.
Já o padrão VO é como se fosse um DTO imutável, ou seja um objeto que mantem o seu valor no decorrer da sua vida. O número 5 sempre vai ser 5. Quando vc muda o 5 pra 6, ele deixa de ser o número 5 e vira o numero 6. Número neste caso é um objeto de valor, um é diferente do outro. Em Java, String, Date, todos os Number. Normalmente
Fowler define Value Object como:
A small simple object, like money or a date range, whose equality isn’t based on identity.
VO não tem identidade, tem valor!
Já o POJO, cunhado por Martin Fowler e cia, são objetos simples. São aqueles objetos que não enxtendem ou implementan ninguem. Não dependem de nenhuma atividade externa. São objetos simples que utilizam somente códigos “nativos de Java”.
E Java Bean? Bem, Java Bean é uma especificação! É ela que diz que as classes devem começar com letra maiúscula, os métodos em minúscula, os getX, setX e isX da vida..
Resumindo:
- Pojo são simples objetos puramente Java;
- JavaBean é uma especificação;
- DTO = TO = Objeto pra transferência de informação;
- VO é um DTO que mantem o seu estado
- Entidade é um objeto que tem uma identidade em um domÃnio.
Até!
Comente e Recomende!
Padrões de Projeto e Expressividade de Código
por Rodrigo Allemand em Mar.02, 2009, em Desenvolvimento
Quando eu comecei a vida de desenvolvedor, a minha idéia era que o divisor de águas era quem soubesse escrever “padrões de projeto”. Eu não estava completamente errado. Onde eu errei? Vamos lá…
Christopher Alexander, um renomado arquiteto italiano, uma vez citou:
Cadas padrão descreve um problema no nosso ambiente e o núcleo da sua solução, de tal forma que vc possa utilizar usar esta solução mais de um milhão de vezes, sem nunca faze-lo da mesma maneira.
Christopher Alexander não construia sistemas. Ele construia prédios, casas e cidades. Mas a citação acima se encaixa perfeitamente na definição de padrão de projeto para construção de sistemas! São soluções para um problema conhecido! Não adianta saber “fazer” um padrão de projeto. Vc precisa identificar o problema e achar a melhor solução para este problema, seja ela conforme o criador do padrão de projeto citou ou como você achar melhor. Basta que a definição do padrão seja seguida na sua implementação. Portanto, não grave como a sua classe deve ser para atender um determinado padrão, grave o que o padrão prega, o que ele se propõe a solucionar e os principios de design do padrão.
Outro grande problema encontrado é quanto a nomeção de classes. Quando se nomeia uma classe, deve-se deixar bem claro (porem sem termos um texto como nome) o que a classe faz e como ela foi idealizada. Não só com comentários, mas com os nomes claros, deixando-os entendÃveis a primeira vista.
Essa é outra motivação dos padrões. A nomeação é tão importante como a sua implementação. Não adianta vc definir um padrão extremamente bem se uma pessoa que vai desenvolver utilizando essa classe, não conseguir enchergar o que ela realmente faz.
Imagine que vc está entrando em um projeto agora e ao abrir o seu workspace, se depara com uma Classe chamada ConfiguracaoSingleton. Automaticamente vc saberá que se trata de uma instância única da configuração da aplicação.
Ter expressividade no seu código é 80% de um código bem feito! Se alguem entende o que vc se propoz a fazer, as possiveis correções e manutenções (ou até mesmo, usar o seu código como exemplo) fica muito mais facil.
Portanto nomeie bem seu código e saiba o-que-resolve-o-que.
Obs: Vale a pena entender o que é um Anti-pattern tambem!
Para exemplificar melhor, vamos descrever um dos padrões mais conhecidos, mais e mais exemplificados e mais mal-entendidos da história do desenvolvimento orientado a objeto: o Singleton!
O Singleton foi originalmente criado pelo renomado grupo Gang Of Four [GoF], formado por Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides. Sua definição é:
Garantir que uma classe tenha somente uma instância e fornecer um ponto global de acesso para a mesma.
Resumidamente, a motivação do Singleton é ter um ponto de acesso a uma intancia que seja unica para todo o sistema. As aplicações para este patterns são inúmeras: configuração, tratamento de informação compartilhada, parametrização, manter estado de um objeto, manter instancias de outros objetos que sejam statefull, etc. O qua vai guiar como contruir este objeto é a sua necessidade.
ATENÇÃO: Os códigos utilizados nestes exemplos são meramente ilustrativos.
Vamos ao exemplo mais conhecido de todos:
public class Singleton {
   private static Singleton instance = null;
   private Singleton() {
   }
   public Singleton getInstance(){
      if(instance == null)
         instance = new Singleton();
      return instance;
   }
}
Este sem dúvidas é o código mais conhecido como Singleton. Mas ai começam os problemas…
Se eu tiver em um sistema muito concorrido, pode acontecer de duas instancias serem criadas ao mesmo tempo. Se isso for realmente um problema, refatorando o código poderemos ter algo como:
public class Singleton {
private static Singleton instance = null;
private Singleton() {
}
public synchronized Singleton getInstance(){
if(instance == null)
instance = new Singleton();
return instance;
}
}
Sincronizando o método, podemos garantir que apenas uma chamada será processada a cada momento. Mas isso torna o código muito ruim, já que até mesmo depois da criação, todas as chamadas deverão ser sincronizadas e, conforme dito no problema 1, a sua concorrência é grande, o que implica em muitos acessos e uma baixa performance desse método.
Se isso for realmente um problema, para solucionar podemos fazer coisas do tipo:
public class Singleton {
   private static Singleton instance = null;
   private Singleton() {
   }
   public Singleton getInstance(){
      if(instance == null)
         synchronized (Singleton.class) {
            instance = new Singleton();
         }
      return instance;
   }
}
Beleza! com isso conseguimos garantir concorrência e performance, correto? Não, não não… sendo bem purista, ainda há uma possibilidade de haver uma concorrencia na linha 09 do último exemplo. Sim, é possÃvel sim (Calma, são apenas exemplos, rs)! Se isso for um problema, refatorando um pouco mais, podemos ter um código assim:
public class Singleton {
   private static Singleton instance = null;
   private Singleton() {
   }
   public Singleton getInstance(){
      synchronized (Singleton.class) {
         if(instance == null)
            synchronized (Singleton.class) {
               instance = new Singleton();
            }
      }
      return instance;
   }
}
Pronto! Temos um singleton!!!
Mas ainda temos um probleminha… E se o sistema tiver rolando em Cluster?! Se vc tiver mais de uma JVM, vão existir mais e uma instância do seu singleton, o que deixa de ser singleton!
Bem, perceberam que a ligação entre problema e solução não diz respeito a como codificar. Eu tenho vários exemplos de Singleton acima e até o momento eu não resolvi o meu problema, que é ter uma instância, que suporte concorrência, com performance e em um ambiente distribuido. E eu poderia fazer milhões de implementações diferentes para conseguir chegar ao meu objetivo!
Mas e se eu não me importasse de ter mais de uma instancia no Cluster? E se a minha concorrência fosse muito pequena a ponto de não atrapalhar a minha performance? Isso cabe a você!!! Como eu disse, conhecer o problema e dar a melhor solução possivel!
Existem todos os tipos de pessoas! Existem aqueles que pensam em uma solução, implementam um ou mais padrões sem ao menos conhecer o que está fazendo; como tambem existem aqueles que implementam vários padrões de projeto para um simples Hello World e mesmo assim, a implementação está errada!
Só para termos ideia, vou colocar mais um exemplo de Singleton. Neste eu utilizo o contexto de uma aplicação Web para individualizar a minha instancia.
public class Singleton {
   private static final String KEY = "singleton";
   private Singleton() {
   }
   public Singleton getInstance(ServletContext context){
      Object obj = null;
      obj = context.getAttribute(KEY);
      if(obj == null){
         synchronized (Singleton.class) {
            Singleton singleton = new Singleton();
            context.setAttribute(KEY, singleton);
            return singleton;
         }
      }
      return Singleton.class.cast(obj);
   }
}
Portanto, entender o seu problema, saber qual padrão de projeto aplicar e nomea-lo corretamente é o divisor de aguas.
Até!
Comente e Recomende!

