Programando orientado a interface

Se você programa em alguma linguagem de programação orientada a objeto, com certeza conhece os termos “Private”, “protected” e “public” e muito provavelmente sabe para que eles servem. Métodos ou membros públicos são aqueles que podem ser acessados por outras classes, os protegidos apenas pelos descendentes e os privados só possuem visibilidade local, ou seja, dentro da própria classe. Parece simples, porém, é muito comum encontrar programadores que parecem não seguir critério algum ao definir o nível de visibilidade dos membros de suas classes, ou então aplicam alguma metodologia aleatória para este fim. Propriedades que eram protegidas são publicadas durante o desenvolvimento de outras classes clientes, conforme a necessidade. Classes “amigáveis” (class friendly) são criadas para permitir acesso a funções protegidas. Práticas como essas acabam por criar uma arquitetura extremamente confusa, com componentes de difícil entendimento, difíceis de serem testados e expandidos. Qual seria então o melhor critério para evitar esse tipo de problema?
Ao desenhar uma classe devemos ter uma ideia bem clara de qual a responsabilidade dela, caso contrário, coloque em dúvida a necessidade de criá-la. O raciocínio é simples: se não sabemos o que a classe deve fazer, então não precisamos dela. Após a definição clara de qual é a responsabilidade da classe, levando em consideração a coesão e nível de acoplamento desejado, devemos pensar sobre a sua interface. Para entender melhor, basta imaginar como a classe deve ser vista por suas classes clientes, ou seja, as classes ou componentes que irão utilizá-las. Apenas métodos e propriedades que permitam acesso e manipulação de dados relacionados à responsabilidade da classe devem ser públicos. Você deve fazer isso não para impedir que outros acessem dados internos de suas classes, mas, principalmente, para garantir que elas sejam mais legíveis, inteligíveis e fáceis de usar. O ideal é que qualquer programador do mundo possa, apenas lendo os métodos públicos de sua classe, dizer qual a responsabilidade dela, e quais métodos chamar, e como chamá-los para conseguir usufruir de suas funcionalidades. Se você não se preocupar em publicar apenas o que for necessário, sua classe corre o risco de ficar confusa demais e difícil de utilizar.
Uma analogia com o mundo real pode ajudá-lo a entender melhor esse raciocínio: imagine um carro onde, junto com os pedais de freio e embreagem, tivessem outros controles estranhos, como um pedal pra regular o nível do óleo e outro para ativar e controlar a bomba de gasolina. Esse carro faria com que o condutor ficasse bem confuso, e tentasse regular o consumo de gasolina manualmente enquanto dirige (um absurdo, não?).
Voltando ao mundo dos bits, por exemplo, se sua classe possuir uma coleção de itens, seria bom deixar claro se ela é dona deles e apenas ela deve poder removê-los ou incluí-los em seu container. Para isso, não disponibilize em sua interface métodos que dão acesso direto a lista, procurando sempre usar o encapsulamento onde for necessário e disponibilizando um iterador.

Se ela exigir passagem de parâmetros de inicialização, providencie construtores personalizados, onde a classe cliente possa passar os parâmetros necessários. Esse tipo de design facilita a leitura e entendimento de quem a for utilizar.

Tenha sempre esse conceito em mente: as classes clientes visualizam apenas os métodos publicados, e devem – apenas se baseando no que enxergam – entender a responsabilidade e como usar os recursos da classe servidora. Algumas ferramentas muito importantes, como o TDD (desenvolvimento orientado a testes) são extremamente eficazes e – se usadas corretamente – funcionam automaticamente como guias forçando o desenvolvedor a escrever uma interface simples e fácil de usar. Pretendo escrever um artigo sobre esse tema relacionado ao TDD em breve. Até lá.
Muito bom! Parabéns!
Essas práticas ajudam muito os futuros herdeiros do código, pois nunca podemos nos esquecer que todo código um dia, se tiver sucesso, tornar-se-á legado de alguém.