O que é Design Modular em programação ?

Willyan Guimarães
experienceCode
Published in
4 min readMar 2, 2023
Photo by Priamo Mendez on Unsplash

Existem diversas formas pelas quais podemos construir uma aplicação e uma delas é subdividir um sistema em pequenas partes. Um design que segue esses princípios é chamado design modular.

Módulos de uma aplicação qualquer e suas interações (dependências)

Em design modular esses pequenos componentes são chamadas módulos. Podemos entendê-los de várias formas: classes, subsistemas, serviços, APIs, microsserviços.

No mundo ideal (irreal) os módulos não devem possuir qualquer dependência com outros. Infelizmente o mundo ideal é inalcançável. Módulos chamam outros módulos e de uma forma ou de outra são construídos para trabalharem juntos.

Módulo regras de negócio existe por si só, mas depende do módulo de banco de dados

Por exemplo, os parâmetros de uma função criam uma dependência desta para o código que a chama. Se em algum momento os parâmetros mudarem, todas as chamadas a essa assinatura precisarão ser modificadas.

Método validaCadastroUsuario() mudou, fazendo com que seus chamadores tenham mais argumentos a enviar

Em design modular o objetivo é minimizar a dependência entre módulos. E para gerenciar dependências podemos dizer que módulos contém duas partes: interface e implementação.

Basicamente a interface apresenta o que módulo pode fazer sem dizer como, escondendo a complexidade existente. E a implementação é a concretização das promessas feitas pela interface.

Um módulo bem escrito e pensado possui interface simples mesmo que sua funcionalidade seja complexa, ou seja, mantém a simplicidade para seus usuários.

As medidas de tamanho da interface e suas respectivas funcionalidades codificadas na implementação juntas poderiam descrever a “profundidade de um módulo”.

O tamanho da interface é representado horizontalmente. O tamanho da implementação é representado verticalmente.

Na imagem acima, pode ser visto dois módulos diferentes. O primeiro módulo(a esquerda) é considerado profundo (deep module) e o segundo definido como “raso” (shallow module).

Módulos profundos são aqueles que proveem muitas funcionalidades através de interfaces simples. Em termos de complexidade de sistemas o custo de um módulo é a sua interface. Assim, quanto mais grande ela é mais complexidade impõe a um sistema.

Um bom exemplo de módulo profundo é o mecanismo de I/O provido pelo sistema operacional Linux. As cinco operações abaixo são as únicas necessárias para fazer chamadas de sistema para I/O do SO.

Módulos rasos são aqueles que possuem interfaces relativamente complexas em comparação com a funcionalidade que fornecem. Com isso, ao invés de trazer benefícios em seu uso trazem complexidade adicional ao sistema.

Um bom (mau) exemplo de módulo raso é a API de IO da linguagem Java. Veja o código abaixo:

Os objetos fileStream e bufferedStreamnunca são usados pois FileInputStreamnão possibilita escrita de dados. BufferedInputStream só tem a função de adicionar buffering ao fileStream. Por fim, só a partir de ObjectInputStreamé possível trabalhar lendo e escrevendo dados.

Este cenário mostra uma certa complexidade descenecessária na configuração do uso das interfaces da biblioteca. Se por acaso no desenvolvimento de uma funcionalidade BufferedInputStreamnão for criado o processo de buffering não será habilitado e o I/O ficará lento.

Conclusão

Utilizar design modular possibilita construir partes de um sistema de forma mais simples e independente.

Módulos são compostos por interface e implementação.

Um bom módulo é aquele que é profundo, isto é, possui uma interface simples mas relevantes funcionalidades. Essa abordagem possibilita esconder complexidade do resto do sistema e faz com que usuários precisem entender apenas a abstração da interface e nenhum outro detalhe de sua implementação.

“O Código é o projeto.”

Este texto foi inspirado no quarto capítulo do livro “A Philosophy of Software Design”.´

Referências

--

--