sexta-feira, maio 02, 2008

Inversão de Dependências

A forte dependência entre classes (ou componentes) é o principal vilão de uma boa arquitetura de software! Evidentemente, não existe uma arquitetura completamente desacoplada, pois desta forma os objetos não poderíam trocar mensagens uns com os outros. A idéia é minimizar a existência destas dependências, e inserir no modelo apenas dependências bem planejadas. Particularmente, costumo chamar estas dependências bem planejadas de dependências saudáveis, afinal de contas, trazem muitos benefícios para o sistema como um todo.


No post Princípios Fundamentais do Processo Unificado, apresento o conceito Processo Centrado em Arquitetura. Resumidamente, o processo de desenvolvimento é guiado pela evolução da arquitetura, e o arquiteto preocupa-se em estabelecer um alto grau de modularidade para facilitar a expansão e a manutenção do sistema. Com módulos bem planejados, e dependências saudáveis entre eles, minimizamos três propriedades internas indesejáveis: Rigidez, Fragilidade, e Imobilidade. Vale a pena dar um pulo naquele post para entender cada uma destas três propriedades.


OK, vamos ao que realmente interessa: Como modelar apenas dependências saudáveis? Resposta bate-pronto: Utilizando interfaces para a inversão de dependências! Interface é uma definição parcial de algum conceito do domínio tratado por sua arquitetura. Certamente é a maior aliada do arquiteto de software! Vamos apelar para a UML para entender como inverter dependências.



O esquema acima poderia ser parte integrante da arquitetura de um comércio eletrônico, onde pedidos são armezenados na base de dados. É natural pensar que um objeto da classe Pedido envie mensagens para um objeto da classe MSSQL. Entretando, a dependência existente a partir de Pedido para MSSQL é indesejável. Algumas consequências podem ser observadas:

  • O negócio passa a depender da tecnologia. Como sabemos, a tecnologia está em constante evolução, e cada mudança tecnológica potencialmente provoca uma mudança nas classes de negócio, como a classe Pedido neste exemplo. Regras de negócio tendem a ser mais estáveis ao longo do tempo.

  • A arquitetura assume que, invariavelmente, o armazenamento dos dados será realizado por um banco de dados. É importante lembrarmos que o armezenamento baseado no sistema de arquivos vem ganhando algum destaque, e mostra bom desempenho.

  • Caso a classe de acesso aos dados tenha sido desenvolvida para trabalhar com um banco de dados específico (MSSQL neste exemplo), então a classe de negócio deverá ser constantemente modificada para cobrir eventuais novos provedores de dados (MySQL por exemplo).

  • Cria um acoplamento que dificulta testes unitários.


Como alternativa, poderíamos fazer com que a classe Pedido dependesse de uma interface que teria por objetivo prímário desacoplar o negócio das questões de armezenamento e recuperação dos dados.



Repare que, neste momento, a dependência é invertida, e todos os pontos negativos citados são removidos da arquitetura! Porém, o objeto de negócio ainda precisa enviar a mensagem para o objeto que manipula a base de dados. Como realizar isso nesta nova arquitetura? Simples! Interfaces não existem em tempo de execução, apenas objetos. Desta forma, o lugar da interface é ocupado pelo objeto de alguma classe que realiza esta interface. Podemos ter uma classe para MSSQL, outra para MySQL, uma terceira para FileSystem, e assim por diante.


Visualizar a inversão de dependência é ainda mais fácil quando tratamos com componentes, e não classes, como segue.



No próximo diagrama a dependência é invertida com o advento da interface.



A notação caixa-preta torna tudo ainda mais evidente, como segue:



E, novamente, a inversão da dependência:




É isso aí pessoal, espero ter colaborado com mais essa! Até a próxima, abraços!

4 comentários:

Chester disse...

Boa, eu sabia que você voltaria a postar um dia desses... :) Muito bom o artigo, keep up!

Otavio Ferreira disse...

Grande Chester,
Finalmente voltei a escrever aqui, estava com saudades de tudo isso!
Obrigado pelo comentário, abraços.

Anônimo disse...

Otávio, você já viu como o Rails abstrai o modelo de dados?
Tem tudo a ver com não depender da tecnologia, leia: banco de dados.

Otavio Ferreira disse...

Olá Narwen, que bom te ver por aqui!
Então, não tenho desenvolvido com Rails, pelo menos não por enquanto... Espero que a oportunidade apareça.
Se você puder enviar um comentário descrevendo este modelo brevemente seria muito bacana!
Obrigado, beijos.

 
> blogblogs.com.br