Conceitos de Orientação a Objetos – Parte 3 de 6

Agora a parte 3 da série Conceitos de Orientação a Objetos, com Daniel Moreira Yokohama:

Encapsulamento

Alguns métodos não conseguem por si só resolverem sua responsabilidade sem que algumas informações sejam previamente informadas. Uma pesquisa no Google não pode retornar valores se não receber algo por que buscar. Um pedido não é capaz de incluir produtos em si sem saber quais produtos o cliente quer adquirir. Estas informações podem ser encontradas espalhadas pelo sistema de acordo com o estado dos objetos na memória no momento em que o método é acionado. Porém, quando um método depende desse tipo de informação seu funcionamento é arriscado, pois as informações que procura podem não estar lá.

A forma mais segura de fazer com que o método funcione de forma segura é entregá-lo prontamente todas as informações que ele necessita para fazer o que precisa ser feito. Um método que envia um e-mail para o cliente, informando o status de sua compra, não tem garantias de que vá funcionar se tiver que procurar sozinho todas as informações (que cliente, qual status), ou irá funcionar com limitações pois, por mais que ele saiba procurar pelos dados em um banco, não será capaz de cumprir o mesmo propósito se em determinadas entregas a loja contratar um serviço de frete terceirizado que administra o status separadamente.

Encapsulamento é um conjunto de pequenas regras que tornam seus objetos mais íntegros. E uma destas regras é a de deixar o método se resolver por si só fazendo tudo o que ele tem que fazer e nada além disso. Invés de procurar pelo cliente no banco de dados, ele recebe os dados do cliente através de parâmetros e deixa que a busca pelos dados do cliente seja feita por outro objeto que possua essa responsabilidade (método).

Outra regrinha do encapsulamento, é que os objetos devem ser responsáveis por si. Soberanos na administração de si mesmos. Por exemplo, se um objeto pessoa tem um atributo idade, o objeto pessoa deve saber administrar essa propriedade para que, se um objeto externo tente atribuir um valor inválido (como -1, por exemplo) o próprio objeto pessoa saiba se defender. Isto torna a inteligência do objeto centralizada em um único lugar, nele mesmo, o que fará com que sua administração seja independente dos outros objetos que compõem a arquitetura do sistema.

Exceções

Digamos então que o objeto pessoa receba um valor inválido para ser atribuído na propriedade Idade. Como tratar este problema? O Objeto pessoa pode ignorar a ordem. OU exibir uma mensagem na tela. Mas e se for imprenscindível para o objeto externo saber que a atribuição tenha ocorrido com sucesso? E se o sistema estiver rodando num serviço windows e não existir uma tela para exibir a mensagem?

O conceito de tratamento de exceções estruturadas não é necessariamente parte da orientação a objetos, mas ele foi muito bem vindo no panorama atual de desenvolvimento de software. Uma exception é uma situação inesperada que é arremeçada por um método invocado, direcionada para o método que o invocou.

Por exemplo: o motorista do caminhão não encontrou ninguém no endereço que o cliente informou, que pudesse receber a encomenda. Ele então lança a exceção para seu superior imediato, o método que o invocou, seu supervisor. O supervisor olhará para a exception e verá se trata-se de um problema que ele tenha autonomia para resolver. Se não tiver ele repassa ela para o próximo superior da pilha. O método que o invocou. O gerente de contas da loja vai verificar que passou o endereço do cliente errado e corrigí-lo ou concluir que não possui o endereço correto e acionar o cliente para se informar a respeito.

Ao resolver o problema, todos são acionados novamente até que o motorista tente fazer uma nova entrega.

Assim funciona o tratamento de exceções na OOP. Seus métodos podem receber exceptions que descrevem situações inesperadas. Se não houver implementação de tratamento para elas, eles a lançam (throw) para o método que os chamou, até chegar no topo da pilha (no caso, o núcleo do sistema) resultando em um erro, que irá interromper todo o sistema.

Por isso é importante identificar que tipos de situações inesperadas um método pode resolver. Um método que tenta se conectar ao banco, por exemplo, pode receber uma exception dizendo que o banco não está no ar. Se o banco não está no ar, e a responsabilidade dele é se conectar ao banco, então é responsabilidade dele tratar esta exception sem repassá-la ao método que o chamou. Mas se um método que precisa enviar um e-mail receber uma exception descrevendo erro de divisão por zero, isso não é problema do método em questão. Ele não precisa tratá-lo. Ele repassa para o método que o chamou até que se torne claro para alguém (através de uma mensagem de erro no sistema) que algum método deixou de fazer o tratamento antes de chegar no método que envia os e-mails.