Orientação a objetos é ruim… E eu também acho!

Recentemente topei com esse vídeo no Youtube:

Esse é um exemplo de como pensar a respeito de Análise de Sistemas ou, de como entender o que um sistema realmente é! Esqueça a briga entre a preferência de linguagens de programação ou de sistemas opeacionais mais “adorados”… Esse tipo de pensamento “filosófico” te diz o que você está, de fato, fazendo ao obedecer regras pré-concebidas cegamente.

Um resumo do vídeo, para aqueles que não têm fluencia em inglês suficiente poderia ser:

Todo software é um conjunto de comportamentosestados. Os comportamentos são os algoritmos, funções ou precedimentos que manipulam ou usam dados (estados) para realizar uma tarefa… Existe, claramente, uma quase simbiose entre os dois: Uma função depende de dados e dados precisam ser manipulados por funções. Um não existe sem o outro. Mas, essas são coisas diferentes. Dados, por si só, são contidos em estruturas (variáveis, constantes, “structs”) e não contém quaisquer operações intrinsecas. Funções, por outro lado, precisam manipular dados, mas são, essencialmente, instruções que devem ser executadas em sequência (faça isso, faça aquilo…).

Não é de espantar que alguém tenha pensado em misturar essas duas coisas diferentes numa abstração conveniente chamada de objeto. Isso permite encapsular os estados usados por um conjunto de comportamentos num único container… Claro que essa abstração é útil, mas enfrenta um problema: Estados compartilhados!

Ao encapsular estados e comportamentos temos que lidar com os casos em que dois ou mais objetos precisam, de tempos em tempos, lidar com o mesmo estado para fazer algo útil. Existem algumas maneiras de fazermos isso… Do ponto de vista puramente procedural, podemos criar estados globais, violando o conceito de orientação a objetos (onde todo estado está encapsulado num objeto). Do ponto de vista orientado à objetos, podemos criar um objeto intermediário, criado ad hoc (um outro termo para “gambiarra”!). Note que estamos falando de objetos, não de classes… Assim, ao criar esse objeto “controlador”, criamos uma hierarquia de troca de “mensagens” entre objetos.

O método do objeto intermediário funciona, mas cria mais problemas: O que acontece se precisarmos trocar “mensagens” entre objetos que não têm um intermediário? A resposta poderia ser: Criar outro intermediário! Só que isso tende a gerar um código macarrônico, povoado de objetos auxiliares que nada têm haver com a filosofia do encapsulamento. Essa filosofia surgiu, em primeiro lugar, da ideia de que devemos encapsular comportamentos específicos associados com estados específicos, gerando a abstração de um “objeto”… O que se faz ao criar objetos auxiliares para troca de “mensagens” é adicionar comportamentos e estados que não estão presentes no modelo original do sistema… E isso gera abstrações ainda mais estranhas (MVC é um exemplo! O que vai em “model”? E em “view”? E em “controller”? Há como isolá-los realmente?).

Dessa forma, acabamos tendo um sistema povoado de mais objetos auxiliares do que essenciais. Isso é particularmente visível em sistemas desenvolvidos em Java, por exemplo…

Stack trace de um programa em Java
Stack trace parcial de um programa em Java

Esse stack trace genérico é mais ou menos a regra em aplicações Java, especialmente se você lida com servidores de aplicação do tipo JBoss ou servidores de containers como o Tomcat. Dê uma olhada num stack trace real de uma aplicação java pra ver só…

O que o autor do vídeo está advocando (e eu também, mas de forma menos “erudita”) é que a programação orientada a objetos tende a criar uma monstruosidade que é tudo menos “gerenciável”. A desculpa pela adoção da orientação a objetos é que ela permite que os sistemas sejam mais facilmente “mantíveis” do que aqueles implementados em forma procedural. O que é patentemente falso! Isso acontece porque as abstrações (que, em si, é uma boa ideia) têm que ser aplicadas, inclusive, nas gambiarras que você usa para fazer com que seus códigos funcionem, jogando os princípios da OO na privada e dando descarga… Sem contar que você precisará nomear cada uma dessas classes e criar uma abstração adequada para que o código faça sentido. Dadas as diferenças sutis entre os objetos auxiliares e à paciência que se esgota facilmente na codificação, essa é uma tarefa quase que impossível…

Do vídeo eu só não concordo com a alegação de que não há grandes problemas de performance quando se lida com OO… Quanto ao resto, o sujeito tem minha total atenção e apreço…

Anúncios