Tag: Desenvolvimento
DDD encapsula a minha Regra de Negócio
por Rodrigo Allemand em Oct.16, 2009, em DDD
Resolvi responder ao comentário do Diogo (no post Blindando o DomÃnio) em um post separado por achar que essa é a duvida mais frequente que eu vejo, seja em conversas informais, fóruns, palestras, etc.
Onde colocar as minhas regras de negócio?
A resposta é…. Depende! rs
Se você escolheu utilizar DDD no seu projeto é porque você conhece e já isolou o problema a ser resolvido que, por ser complexo, será baseado em um modelo, recebendo o foco e a prioridade necessárias para a solução deste domÃnio. Quando você isola este domÃnio, obviamente você deve encapsular tambem todas as regras de negócio dentro desse domÃnio.
Para exemplificar melhor vamos fazer a seguinte funcionalidade de exemplo no nosso dóminio.
Todos os pedidos com valor acima 1.000,00 e que são pagos com dinheiro em espécie são elegÃveis a um desconto de 10% por produto.
Claro que esta informação tem que ser passada para o usuário final do sistema, mas é responsabilidade do sistema checar se as informações passadas estão corretas. Você pode até colocar a regra de validação tambem na camada de apresentação ou dentro do seu banco de dados em forma de triggers (argh, rs!), mas de qualquer maneira o domÃnio tem que ter esta validação, já que um dos princÃpios do DDD é justamente poder trocar a camada de apresentação sem que o domÃnio seja alterado ou compartilhar o mesmo domÃnio entre interfaces/sistemas diferentes.
Portanto, segue a primeira afirmação:
Por mais que a sua camada de apresentação faça as regras necessárias para uma determinada funcionalidade, o seu domÃnio tambem deve, obrigatoriamente, fazer com que estas regras estejam presente internamente, tornando-o coeso da camada que ele comunica.
Vamos melhorar este exemplo mostrando como ficariam as entidades envolvidas nesta funcionalidade.
public class Pedido {
private List<ItemPedido> itens;
private BigDecimal precoTotal;
//Acessores omitidos
}
public class ItemPedido {
private Produto produto;
private BigDecimal precoVenda;
private BigDecimal desconto;
//Acessores omitidos
}
OBS.: Muitos podem perguntar porque a informação referente ao preço final é um atributo da classe e não um comportamento da entidade (um método que poderia somar todos os preços finais decrementando os descontos dados por cada produto, multiplicado pela quantidade de cada produto). Vamos pensar que o preço do Produto pode – e deve – variar e o sistema precisa manter a informação do preço de venda naquele momento, ok?
Eu encaro que esta regra de negócio deve estar em uma checagem no momento da inclusão, como por exemplo uma Specification destinada somente a esta regra. Lembro que, a Specification tem, neste caso, o intúito de validar uma informação e que ela não precisa ser necessariamente apenas uma única specification. Eu posso – e é até melhor – dividir a informação em várias Specifications, uma para cada regra de negócio que a minha funcionalidade exige.
Vamos pensar então que a minha classe ValidarDescontoDadoSpecification tem o seguinte código:
public class ValidarDescontoDadoSpecification
implements Specification<ItemPedido> {
public static final BigDecimal DESCONTO_MAXIMO_PGTO_DINHEIRO = 10;
public boolean isSatisfiedBy(ItemPedido item){
if(itemPedido.getFormaPagamento.equal(FormaPagamento.DINHEIRO){
BigDecimal descontoDado =
Calculadora.percentualEntre(
item.getPrecoVenda(),
item.getDesconto());
if(descontoDado.compareTo(DESCONTO_MAXIMO_PGTO_DINHEIRO) > 1){
//É necessário comunicar ao domÃnio o porque da falha
//Neste caso, leia mais sobre Notification
return false;
}
}
return true;
}
}
Pensando que você sempre salva o pedido, poderiamos ter uma outra Specification para isso, conforme abaixo:
public class PersistirPedidoSpecification
implements Specification<Pedido> {
public boolean isSatisfiedBy(Pedido pedido){
/*
As boas maneiras de aplicativos internet diz que
vc deve validar tudo de uma unica vez, rs
*/
boolean resultado = true;
//Validações referente ao Pedido
ValidarDescontoDadoSpecification spec =
new ValidarDescontoDadoSpecification();
for(ItemPedido item : pedido.getItens()){
if(!spec.isSatisfiedBy(item)){
/*
Lembre que a informação da falha deve ser feita
pela outra Specification, não por esta!
*/
resultado = false;
}
}
return resultado;
}
}
Assim, no final de tudo, nós poderiamos ter no repositório Pedidos, o seguinte código:
public class Pedidos{
public static void persistir(Pedido pedido){
PersistirPedidoSpecification spec
= new PersistirPedidoSpecification();
if(spec.isSatisfiedBy(pedido){
dao.salvar(pedido);
} else {
//Comunica a falha encontrada às outras camadas
}
}
}
Espero ter ajudado!!!
Abraço a todos!!!
Comente e Recomende!!
O Cliente tem sempre razão… o usuário nem sempre!
por Rodrigo Allemand em Sep.24, 2009, em Matodologia Agil
Muitas coisas fazem um projeto passar de sucesso a um completo fracasso, dentre eles uma equipe mau escolhida, um escopo não casado com os prazos, uma arquitetura ruim, etc. Mas um dos maiores problemas que eu vejo que pode transformar um “felizes para sempre” em um “problema para sempre” é o levantamento das necessidades e requisitos.
Mais uma vez, muitos podem ser os fatores que atrapalham um bom levantamento. Analistas inexperientes, hierarquias mau definidas, credibilidade da equipe, clima hostil com o cliente, falha de detalhamento – muito ou pouco, dependendo do caso, usuários indecisos, usar “o que já existe” como exemplo e o pior de todos: usuários “acostumados” com o erro.
Recentemente, estou trabalhando como bombeiro em um projeto que espelha muito do dito acima.
A proposta era redesenhar um sistema originalmente feito em Delphi, que já funcionava a alguns anos para uma estrutura web em Java que temos. Este sistema já tinha passado por diverss atualizações, transformando o código em uma bela macarronada
Por uma briga que se arrasta a gerações (rs), há um clima hostil entre o gerente de projetos e o cliente final (que não cabe a mim questionar, muito menos entender). Isso gerava muitas discursões (infinitas até) quando se queria definir algum ponto.
Dica 1:Quando o manifesto ágil diz para ter o cliente como parte da equipe não é so ter o cliente por perto, mas sim jogando no mesmo time.
Quando se senta para definir alguma coisa, quanto mais gente entendendo, melhor! Entendendo não significa estar falando ou questionando. Mas todas pessoas precisam ter o mesmo entendimento. Por muitas vezes na reunião, surgia uma pergunta que não tinha fundamento algum, como se a pessoa estivesse voando ou não entendendo nada do que estava acontecendo.
Dica 2: Nunca deixe uma duvida no ar. A reunião é justamente para atender as necessidades dos analistas. Preste atenção quando alguem fala para poder perguntar alguma coisa válida. E questione se não entender! Sempre!
Para piorar, o gerente teve uma das piores atitudes que se pode tomar em uma reunião de levantamento: proibir os analistas de perguntarem, fazendo ele um funil com o cliente. Esta atitude fez com que conceitos fossem perdidos e o pior, conceitos errados surgiram.
Dica 3: Para um projeto, hierarquias não devem existir. Claro que algumas vozes pesam mais do que outras mas no momento de levantamento, todos devem ser ouvidos.
Então começa a definição dos casos de uso. Envolvidos em conceitos errados, climinhas e muita briga, os analistas ‘copiaram’ as funcionalidades do sistema antigo sem propor nenhuma alteração. Na aprovação do documento de requisito (aqui nós temos esse passo, por enquanto, rs) o usuário reclamou de muita coisa que estava definida ali, dizendo que se fosse par ter a mesma coisa, que continuasse com o antigo.
Dica 4: O legado pode ser usado como exemplo, mas tente sempre surpreenda o cliente com alguma novidade. Pense no que pode melhorar o trabalho dele e proponha modificações, sempre embasadas em alguma teoria, por mais simples que seja.
Troca-se a equipe para dar mais força ao projeto. Com isso, o usuário já não acreditava na equipe anterior, achando que eles poderiam novamente fazer as besteiras feitas anteriormente.
Dica 5: Por mais que fosse necessária a colocação de mais recursos, nunca deixe a credibilidade da equipe em risco. Se você não acredita no vendedor, como vai comprar o produto?
A nova equipe começou a detalhar – novamente – as funcionalidades e as mesmas tiveram variações, fazendo com que coisas com pouco detalhe tivessem uma pontuação de ‘codificação’ errada diante de tantos detalhes e outras que realmente tinham um alto grau de dificuldade, com pontuações baixas diante da falta de detalhamento.
Dica 6: Detalhe somente o necessário. Incremento é justamente isso! Se Quando chegar o momento você aumentará o nivel de detalhe.
Dá pra sentir como foi a fase de desenvolvimento deste projeto, né?!
Fazendo uma analogia com a construção de uma casa, a reunião de apresentação dos requisitos e das datas de entrega foi mais ou menos assim.
Analista: (…) Então aqui nós teremos os 3 quartos necessários.
Usuário: Mas eu não preciso de 3 quartos. Eu preciso de 3 camas!
Analista: Sim mas nós colocamos 3 quartos distintos para uma melhor modularização. Sem contar que esse quarto maior aqui é uma suite.
Usuário: Mas nesse quarto aqui, alem de ser suite, ele precisa de uma cozinha.
Analista: Como assim uma cozinha? Já existe uma cozinha aqui, veja!
Usuário: Mas eu preciso de uma cozinha aqui porque na antiga casa eu tinha uma cozinha perto da cama.
Analista: Sim, mas agora nós temos quartose a cozinha em ambientes separados.
Usuário: (…) E onde está a minha janela dos fundos para eu entrar?
Analista: Agora nós temos uma porta aqui nos fundos.
Usuário: Está errado. Funcionava assim: eu entrava na casa, abria a janela, saia da casa, dava a volta na casa, entrava pela janela e acessava a parte dos fundos da casa.
Analista: Agora você não vai precisar fazer isso. Nós temos uma porta para que você entre diretamente por ela, já que o proposito é apenas entrar na casa.
Usuário: Não o proposito é entrar na casa pela janela. E janela não é porta. A porta é pra entrar pela frente, a janela é para entrar pelos fundos.
Dica 6: Para o usuário que está acostumado com o erro do software antigo (que para ele já é trivial “entrar por uma janela”), você precisa mostrar e provar para o usuário que se é para entrar, precisa ser por uma porta.
Como dizia meu avô…
Burro não aprende, burro acostuma.
Não faça do seu usuário um burro.
Comente e Recomende!
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!!