Rodrigo Allemand

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.

  1. Preocupe-se em fazer um código bom
  2. Pense!! Critique o seu trabalho
  3. Dê opções, não dê desculpas.
  4. Conserte falhas ao encontrar a falha
  5. Seja um catalizador de mudanças
  6. Lembre-se o ‘porquê’ do projeto
  7. Faça da qualidade um requerimento
  8. Invista regularmente no seu portifólio de conhecimento
  9. Analise e critique o que você ouve e vê
  10. É o que você fala e COMO você fala
  11. DRY – Don’t Repeat Yourself
  12. Faça facil para ser reutilizavel
  13. Elimine efeitos entre coisas não relacionadas
  14. Não existem decisões finais
  15. Use traçantes para achar o alvo
  16. Prototipar para aprender
  17. Programe para o problema do domínio usando a linguagem do domínio
  18. Estime para evitar supresas
  19. Itere o cronograma com o código
  20. Deixe o conhecimento em arquivos textos
  21. Use o poder das linhas de comando
  22. Use BEM apenas um editor
  23. Sempre use um controlador de versão
  24. Resolva o problema, não a culpa
  25. Não entre em pânico ao debugar
  26. O problema normalmente não é no ’select’
  27. Não assuma algo, prove!
  28. Aprenda uma linguagem de manipulação de texto
  29. Excreva código que escreva código
  30. Não, você não pode escrever softwares perfeitos. Proteja o seu código.
  31. Desenhe soluções baseadas em contratos
  32. Pegue os problemas precocemente. Teste desde o inicio.
  33. Use asserções para prevenir o impossivel
  34. Use exceções apenas para o excepcional
  35. Termine o que começou
  36. Minimize acoplamentos entre módulos
  37. Configure! Não integre!
  38. Coloque abstração no código e detalhe no metadata
  39. Analise o workflow para melhorar a concorrências
  40. Desenhe usando serviços
  41. Sempre desenhe pensando em concorrência
  42. Separe a visão do modelo
  43. Desenhe e conheça o fluxo da informação
  44. Não programe por concidência
  45. Estime a complexidade dos seus códigos
  46. Teste as suas estimações em unidades reais
  47. Refatore frequentemente, agora e sempre!
  48. Desenvolva para os testes
  49. Teste o seu software, ou os usuários testarão
  50. Não use geradores de código que você não entenda o que foi gerado
  51. Não apenas leia os requisitos. Mergulhe neles. Escave eles!
  52. Trabalhe com um usuário para pensar como um usuário
  53. Abstrações sobrevivem mais do que os detalhes
  54. Crie um glossário de projeto
  55. Ache, pense e pese as ‘necessidades’
  56. Comece quando estiver pronto!
  57. Algumas coisas são melhores prontas do que descritas
  58. Não seja escravo da formalidade
  59. Ferramentas caras não produzem as melhores arquiteturas
  60. Organize o time por funcionalidades, e não por funções.
  61. Automatize o que puder ser automatizado.
  62. Teste frequentemente e automaticamente
  63. Só está pronto quando o teste roda com sucesso
  64. Use sabotadores para testar o seu teste
  65. Não teste apenas o código. Teste as situações do domínio
  66. Ache erros apenas uma vez
  67. Escreva documentos com os mesmos princípios que vc escreve código
  68. Não separe tanto a documentação do código
  69. Exceda a espectativa do seu cliente
  70. Assine o seu trabalho

PS: Qualquer duvida, só comentar que eu detalho os itens.

Comente e Recomende!!

Deixe um comentário :, , mais...

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.

Diagrama de Classe extraido do Modelo

Diagrama de Classe extraido do Modelo

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!

Modelo de dados extraido do Diagrama de Classes

Modelo de dados extraido do Diagrama de Classes

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!

2 Comentários :, , , , , , , , , , mais...

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!

3 Comentários :, , , , mais...

Procurando por algo?

Use o campo abaixo para procurar por todo o site:

Ainda não achou? Deixe um comentário ou me mande um email que eu cuido disso!

Minhas indicações!

Alguns blogs que eu recomendo...