5.2 Diminuição de acoplamento através de tipos de dados
5.2.4 Consequências
Com a aplicação deste refatoramento, diminui-se o acoplamento entre os módulos, uma vez que eles não estão mais conectados através de uma implementação (classe), mas sim através de um comportamento (TAD). Deste modo, qualquer classe que implemente aquele comportamento pode substituir a original.
Esta nova situação aumenta a possibilidade de reuso dos módulos. Além disso, facilita a manutenção já que modificações em um módulo não precisam atingir o outro, pois um módulo está conectado ao outro apenas através do TAD que provavelmente permanecerá inalterado.
Por outro lado, este refatoramento introduz o risco da multiplicação do número de TADs contidos no sistema, o que pode também dificultar o entendimento. Por esta razão é preciso definir com cuidado a interface externa do módulo, ou seja, aquilo que deve ser exposto por dele para que não sejam criados tipos desnecessários ou que diminuam o nível de encapsulamento do módulo. E além deste cuidado, a dica apresentada nas Condições de aplicação sobre como identificar a necessidade da criação de um TAD pode ajudar a evitar este efeito indesejado.
5.2.5 Exemplo
O exemplo de aplicação deste refatoramento considera um sistema completo e foi estudo de caso abordado neste trabalho.
Passos 1 e 2
O primeiro passo do refatoramento é identificar os módulos do sistema, onde “módulo” significa um agrupamento de classes responsável por uma ou mais funcionalidades. Os módulos do sistema foram identificados através de entrevista com pessoas que fizeram parte do desenvolvimento do software e que participam das atividades de manutenção do mesmo. A impossibilidade de realização destas entrevistas pode implicar na necessidade de investigação do código fonte para extrair as informaçõs necessárias à construção do grafo. As ligações entre estes módulos foram identificadas através da análise do código fonte. A partir destas informações, o grafo de dependências apresentado na Figura 5.7 foi criado.
RpcStuf f
Slot Sort
Li
Crypt LbStart AppManager
LiFile
Comparator LiParser LT HtmlTools CtawLib IPWorks
LBS
Compress
LbwServ Alfc
Figura 5.7 - Grafo de dependências entre os módulos do servidor LightBase.
Passos 3 e 4
Esta etapa do refatoramento objetiva melhorar o projeto do sistema. A eliminação de dependências que não fazem sentido ajuda a manter a integridade do sistema com os conceitos de modelagem OO e com o mundo real. Quanto mais próximo do mundo real estiver o sistema, mais fácil será entendê-lo.
Através da análise da funcionalidade dos módulos e do grafo de dependências da Figura 5.7 não é clara a razão para existir a dependência entre lbs e lbstart. O lbs é o módulo principal, responsável pelas funcionalidades do sistema. Já o módulo lbstart é responsável pela autenticação da cópia servidor, ou seja, quando o servidor inicia, a chave de ativação e o número de série da cópia do produto são verificados e validados pelo módulo.
O exame da ligação entre os dois módulos revela que o lbs apenas utiliza o lbstart no momento de inicialização do servidor. Sendo o lbs o módulo responsável pela inteligência da aplicação, não faz sentido que ele mantenha uma ligação com um módulo responsável por validações e verificações da licença da cópia do produto. Assim, esta ligação deve ser eliminada e a responsabilidade por esta verificação deve ser transferida para o módulo responsável pela inicialização do sistema: o lbwserv. Este é o responsável pelas inicializações necessárias para que o servidor execute adequadamente.
A relação entre os módulos lbs e lbstart é apenas um exemplo de relações que, semanticamente, não fazem sentido; no entanto, outras relações deste tipo podem ser encontradas na Figura 5.7.
A análise de cada conexão para verificar se o código que impõe aquela dependência é realmente utilizado ou se a relação é necessária ou pode ser substituída é muito importante na simplificação do código do sistema. Através desta atividade, “código morto” é eliminado do sistema. Este tipo de código não é utilizado, mas é deixado no sistema por esquecimento ou por outras razões, podendo ser responsável pelo aumento da complexidade do sistema, dificuldade na identificação de problemas e nas atividades de depuração.
Passos 5, 6 e 7
Para cada uma das dependências que restarem, identificar as classes de cada módulo que fazem parte da relação e criar TADs para diminuir o acoplamento entre os módulos.
No grafo da Figura 5.7, restam várias ligações entre os módulos, duas delas são analisadas a seguir.
Algumas classes neste exemplo representam abstrações de estruturas persistentes do sistema. Algumas destas estruturas detêm informações especiais que são armazenadas em estruturas chamadas slots. O módulo slot é responsável pelo armazenamento e pela recuperação destas informações especiais. O módulo lbs contém algumas classes que representam abstrações de estruturas persistentes e que têm informações especiais armazenadas em slots. Esta é a razão da dependência existente entre os módulos lbs e slot.
No entanto, ainda resta uma dependência que parte de slot para o módulo lbs. Isto ocorre porque, de acordo com a atual implementação, a classe slot precisa obter informações da classe persistente, por exemplo, tamanho do slot. Isto obriga que uma nova classe de tratamento de slot seja criada para cada classe persistente que necessite de informações armazenadas em slots. Estas dependências constituem um exemplo de dependência cíclica que não foi eliminada através da aplicação do refatoramento Eliminação de dependências
cíclicas. A razão para isto é que a dependência é realmente necessária e aquele refatoramento não propõe alternativas à modelagem apresentada. A forma de resolver esta dependência é a aplicação do refatoramento Diminuição de acoplamento através de tipos de dados.
O diagrama de classes da Figura 5.8 apresenta a relação existente entre as classes do módulo slot e do lbs. S lotM anager S lotS truct S lotB as eM anager S l otField Manag er Cam po B as e S lot LB S
Figura 5.8 - Detalhamento das conexões entre os módulos slot e lbs.
Esta solução apresenta vários problemas como a interdependência entre classes que dificulta o reuso e teste, bem como a interdependência entre os módulos do sistema. Além disso, pode-se verificar que a classe Base possivelmente apresenta autos índices de acoplamento e baixos índices de coesão. No entanto, a relação entre os dois módulos é a principal parte a ser considerada.
O refatoramento Diminuição de acoplamento através de tipos de dados propõe a criação de TADs para diminuir o acoplamento entre os módulos do sistema. Para o caso apresentado na Figura 5.8, o tipo SlotObject foi criado para representar a abstração de uma estrutura genérica que contem informações especiais armazenadas em slots. Abstrações que necessitem fazer uso desta facilidade devem prover algumas informações básicas que definem, assim, sua interface.
A Figura 5.9 apresenta o novo diagrama de classes após a introdução do TAD SlotObject.
S lotObjec tM anager Cam po B ase S lot LB S S lotM anager S lotS truct Slot Ob je ct
Figura 5.9 - Relação entre os módulos slot e lbs após a aplicação do refatoramento.
Deste modo, o módulo slot está acoplado não mais à classe Base ou Campo ou a qualquer outra implementação, mas sim, a qualquer classe que implemente a interface SlotObject. Já o módulo lbs está acoplado a qualquer classe que implemente a interface de tratamento de slots SlotManager e à interface SlotObject através de herança.
Para concluir, deve-se compilar, gerar e executar os testes funcionais e de sistema construídos com o intuito de verificar a corretude das modificações efetuadas.