sexta-feira, 16 de abril de 2010

Permitir que faça errado!!

Você já tomou uma bronca por ter feito uma chamada de um método em um lugar errado? (Ex.: gravar um log, abrir ou fechar uma conexão ou transação).
Geralmente quando tomamos uma bronca dessa, do arquiteto responsável por exemplo, abaixamos a cabeça e vamos arrumar o "erro". Mas hoje, quando me deparo esse tipo de coisa eu levanto a questão: O método só foi chamado do lugar errado por que a aplicação deixou que isso fosse feito.

Desenhar uma aplicação de forma que seja fácil fazer o que é certo e difícil fazer o errado é um grande desafio, mas o fato de ser difícil não significa que não deva ser tentado. Ter um conhecimento mais profundo de OO e das ferramentas que utilizamos com certeza nos ajudam a alcançar esse objetivo.

Por tanto, da próxima vez que você passar por esse tipo de situação independente do seu papel, do cara que esta dando ou recebendo a bronca, reflita sobre como esta desenhado a aplicação, isso pode fazer uma grande diferença.

Desvendando o Application Layer

Sabemos que o coração do DDD esta no domínio, dedicamos grande parte da nossa atenção a ele.
Mas gostaria de destacar o papel do application layer e tentar esclarecer algumas confusões sobre ele.

Se você já procurou sobre application layer na internet, que vou chamar aqui de camada de aplicação, com certeza deve ter encontrado várias definições e aplicabilidades diferentes sobre o mesmo, por exemplo, "Application Layer é o mesmo que Service Layer" ou até mesmo relacionar com tecnologias como Web Services e WCF.

Essa confusão de certa forma se justifica pelo fato de que, a responsabilidade da camada de aplicação é de coordenar (ou delegar) os trabalhos realizados pelo domínio, o que é muitas vezes encarado como um façade, o que não esta errado, mas é nessa comparação que começa os problemas, por que o service layer também pode ser um façade.

Devido a esses problemas de definições e comparações, como você não tem um Service Layer em todos os projetos, você pode encarar que talvez não precise de uma camada de aplicação, e é ai que ao meu ver chegamos no ápice do engano.

Para entender bem as diferenças entre eles é necessário destacar uma frase da definição do Evans sobre o application layer: "The tasks this layer is responsible for are meaningful to the business"

Ou seja, não é simplemente chamar métodos de objetos de domínio em uma ordem específica, mas coordenar as tarefas de forma significativa ao negócio. Se você vê semelhanças entre a camada de aplicação e o controller do MVC elas param na palavra coordenar, ok? A controller coordena as interações entre a View e a Model, não é disto que estamos tratamos nesse momento.

Nós, desenvolvedores, geralmente pensamos nas funcionalidades essencialmente como CRUD, fazemos isso por vários motivos, mas talvez o principal se refere a comodidades de interações com banco de dados. O problema desse pensamento é que para o negócio nem sempre o CRUD atende, o cliente não deleta um recebimento ele provavelmente faz um estorno, o cliente não faz um insert de ordem ele abre uma ordem de produção.

A função da camada de aplicação é expor operações realizadas pelo domínio de forma que façam sentido ao domínio, por tanto, se o seu domínio abre uma ordem de produção não faz sentido eu ter SaveProductionOrder() na minha camada de aplicação mas sim OpenProductionOrder().

Isso não quer dizer que os famosos métodos Save, Delete e similires não devam existir na sua camada de aplicação, devido ao fato de que, em alguns casos, não é possível determinar um termo de negócio para essas ações.

Outro ponto importante é a questão da leitura de dados, no DDD nós obtemos os dados através do repositório, faz sentido criar métodos no Application Layer para ler dados? Eu respondo, nenhum. Enquanto em um serviço nós geralmente o utilizamos para operações de leitura e/ou escrita, a camada de aplicação só coordena as operações realizadas pelo meu domínio, quando eu preciso ler alguma coisa eu peço direto para o repositório.

Você deve estar se perguntando: Mas eu preciso de um acesso único ao domínio, não preciso?
Essa busca por um caminho linear é herança do BOLOVO onde você tinha UI > BL > DL > BL > UI.
Essa idéia de que tudo tem que passar pelo domínio gera grandes transtornos para identificar as responsabilidades de cada coisa ou de até mesmo um alto acoplamento entre o domínio e outros recursos da minha aplicação, afinal, tudo passa pelo meu domínio.

No desenho apresentado pelo Evans vemos claramente que isso não é necessário e nem deve ser praticado. Se precisamos de uma funcionalidade que se encontra na camada de infraestrutura podemos acessar diretamente dessa camada.


Concluíndo, apesar das semelhanças que a camada de aplicação tenha com outras funcionalidades precisamos ter em mente que ela precisa estar totalmente comprometida com o negócio.

domingo, 4 de abril de 2010

Problema com códigos no post

Estou com problemas com o syntaxhighlighter, nisso exibir código aqui no blog esta um pouco complicado, estou tentando resolver esse problema, mas até lá vou disponibilizar os códigos para download.

Na sexta feira vou finalizar uma apresentação sobre DDD e vou publicar o código utilizado, nele tem exemplos de BDD e Domain Events.

Aguardem.

Testes unitário x TDD x BDD

Acompanhando os grupos de discussão eu percebo que ainda tem muita gente fazendo confusão entre testes unitários, TDD e BDD. Eu sei que a "sopa de letrinhas" não colabora, mas é fundamental entender as as diferenças entre eles para que você consiga usufluir dos seus benefícios.

Eu não vou ficar aqui dando as definições formais de cada um, abaixo segue alguns links onde você pode obter mais informações, mas vou me preocupar em destacar as diferenças entre eles.


http://pt.wikipedia.org/wiki/Teste_de_unidade
http://pt.wikipedia.org/wiki/Test_Driven_Development
http://pt.wikipedia.org/wiki/Behavior_Driven_Development

Quando estamos aplicando teste unitário, estamos testando um único trecho do nosso código, nada mais do que isso. Se o nosso teste faz mais do que isso ou ele é um teste de integração ou é qualquer outra coisa parecida mas não é teste unitário.

Isso quer dizer que testes de integração não importantes? De forma alguma, mas um dos problemas em se ter teste de integração sem testes unitários é que se o seu teste falhar como você irá descobrir o motivo? Lembrando que, dependendo do tipo de teste de integração que você esteja fazendo, outros fatores podem influenciar o resultado (fatores externos como banco de dados por exemplo).

Um dos fatores de resistência aos testes unitários é a mudança que ele causa no nosso código. Como escrevemos testes para que testem apenas um único trecho, precisamos desacoplar nossas classes e métodos para garantir que estamos testando apenas uma única coisa.

TDD é uma disciplina de desenvolvimento, o seu conceito é bem simples, você cria o testa, o teste falha, você faz funcionar e refatora caso necessário. O famoso red, green, refactoring.
Se você não desenvolve dessa forma você não esta utilizando TDD, isso não significa que você não esteja produzindo testes unitários, mas você não esta seguindo a disciplina de desenvolvimento.

Uma das desvantagens mais levantadas contra a disciplina contida no TDD é referente ao tempo: "Escrever testes e fazer falhar é muito demorado.". A parte ironica disso, é que não é uma reclamação dos gestores mas sim dos desenvolvedores.

BDD é uma evolução do TDD, a quem diz que o TDD foi mal interpretado e que na verdade o BDD sempre existiu.
Com o BDD não é apenas testar, o BDD tem como finalidade documentar o código através de testes feitos com base em especificações contruídas a partir de contextos.
Se você acha o desenvolvimento com TDD é demorado o BDD talvez não ajude a mudar esse conceito.

Bom, podemos ter teste unitário sem TDD e BDD, podemos desenvolver com TDD sem BDD e podemos escrever especificações conforme o BDD sem TDD, entretanto não podemos ter BDD ou TDD sem teste unitário.

Se você vai utilizar TDD ou BDD o mais importante é ter os testes escritos e utilizando as melhores práticas da mesma forma que você escreve o código do produto final, pois com certeza, testes mal escritos são difíceis de entender e manter atualizados.

Como você tem escrito seus testes?