OO: o que você aprendeu provavelmente está errado

Marcelo Camargo
Rung Developers
Published in
5 min readSep 12, 2017

Um dos conceitos mais deturpados e mal-interpretados de ciência da computação. O objetivo deste post não é acabar com a sua alegria, mas de mostrar que o que você aprendeu na faculdade sobre o paradigma ─ muito provavelmente ─ está errado.

INB4: Referindo-se à definição acadêmica, não à definição posteriormente banalizada pelo mercado.

Perdão pelas capivaras, mas gosto de inseri-las em todo artigo ou apresentação.

É comum que a maior parte das instituições universitárias utilizem linguagens como C++ ou Java para ensinar os conceitos de orientação a objetos ─ ou tentar ─ mas não é exatamente OO que é repassado, mas um modelo de programação baseado em um sistema de classes e mesclado ao paradigma imperativo. Meu objetivo neste artigo não é causar polêmica, mas desmistificar alguns conceitos e tentar explicar sobre o que realmente se trata orientação a objetos, e como a maior parte das linguagens modernas não satisfaz ao princípio do paradigma, mesmo usando a capacidade de ser OO como uma “vantagem”.

Quando surgiu OO?

O paradigma é antigo. A noção essencial moderna de orientação a objetos surgiu no final dos anos 50, mas teve seus conceitos amplamente definidos e representados por Alan Kay, e implementados como referência na linguagem Smalltalk, que até os dias atuais é atualizada e vista como referência do paradigma. No geral, o termo OO ainda é visto com grande ambiguidade, e é alvo de flamewars com uma certa frequência.

OO nao é sobre classes

Desculpe decepcioná-lo, mas uma linguagem não precisa possuir classes para ser OO. A linguagem Self introduziu um modelo baseado em prototypes, livre de classes, de maneira padrão. Um conceito que já podia anteriormente ser utilizado em Smalltalk desde os anos 80! Quer uma prova? JavaScript permite programação orientada a objetos de uma maneira ainda mais pura que Java, e o faz baseando-se em prototype-based-programming! Um outro plot-twist: Nem mesmo ES6 tem classes de verdade. O que você vê são abstrações sintáticas para o modelo padrão baseado em protótipos que é utilizado dentro da VM.

Mas o que é OO?

Segundo as definições do criador do termo, alguns conceitos precisam ser respeitados:

  • Tudo é um objeto: é sério. Tudo deve ser um objeto. Classes devem ser um objeto, números, valores primitivos, como strings e booleans e até mesmo seu cachorro deve ser um objeto.
  • Objetos se comunicam por passagem de mensagem: isso significa que objetos devem receber e despachar mensagens de ─ e para ─ outros objetos. Por exemplo, a operação simples 1 + 1. Trivial, não? Uma linguagem OO deve tratar o valor 1 como sendo um objeto, + como sendo uma mensagem e o outro valor como sendo outro objeto. Dessa maneira, a operação de soma seria uma mensagem repassada ao número, que retornaria outro objeto; no caso, outro número. Por essa razão, em Smalltalk, não há precedência de operadores, porque multiplicação e adição são mensagens repassadas ao objeto, e não operações primitivas. No caso, as estruturas como você conhece em outras linguagens ─ como if, for e while ─ não existem da mesma maneira que você vê em Java ou C++, mas você simula o comportamento delas usando mensagens.
  • Todo objeto é uma instância de uma classe: mas não necessariamente uma “classe” nos conceitos definidos em Java, mas de um molde, uma forma ─ e esta também deve ser um objeto. Isso não limita a programação baseada em protótipos.
  • Compartilhamento de comportamento: ou seja, o molde ─ a classe ─ carrega o comportamento compartilhado para os objetos. Por exemplo, as operações aritméticas seriam comportamentos/mensagens de instâncias de Number!
  • Ao iniciar, o controle é passado para o primeiro objeto: e o restante é tratado como mensagens. O primeiro objeto retém o controle.

Os conceitos de Alan Kay para OO também foram amplamente aproveitados para os conceitos de Carl Hewitt para Actors model e programação concorrente. Tim Budd propôs alguns adicionais à especificação de Alan Kay:

  • Objetos possuem sua própria memória, que consiste de outros objetos;
  • Adiciona-se o conceito de herança vertical para compartilhamento de comportamento.

Por que Java não satisfaz OO?

Talvez o ponto mais polêmico deste artigo. O primeiro princípio é inicialmente quebrado pelas definições de que tudo deve ser um objeto.

  • Classes não são objetos: no entanto, toda classe carrega uma instância da classe Class para descrevê-la. As classes por si são apenas abstrações. Até mesmo as classes deveriam poder ser criadas a partir de mensagens.
  • Existência de tipos primitivos: até mesmo os valores primitivos devem ser objetos. Java provê wrappers para esses tipos, como Integer para int, mas int, por si, não é um objeto e não recebe mensagens. A aritmética é nativa.
  • Existência de estruturas imperativas: por exemplo, if. true e false deveriam ser objetos ─ instâncias de Boolean ─ e deveriam poder receber chamadas para ifTrue e ifFalse para continuar as computações. O conceito atual de métodos de Java é baseado em nomes únicos em métodos, mas como é em Smalltalk? A classe Boolean possui os “métodos” ifTrue:ifFalse:, ifTrue: e ifFalse:. No caso, o despacho não ocorre baseado no nome do método, mas no que ele recebe! Algumas linguagens, como Swift e Objective-C suportam bem esse comportamento, e algumas o suportam com abstrações sintáticas, como Ruby. Note que o padrão Smalltalk 98 permite que algumas pseudo-mensagens ─ como ações condicionais ─ possam ser implementadas “nativamente”; e que não possam ser sobrecarregadas em runtime.

No entanto, um detalhe bastante importante é que, apesar de Java por si não tratar tudo como um objeto, a JVM, internamente, trata todos os primitivos como sendo objetos!

Legal! Quero ver isso na prática!

Há um tempo, eu e o Matheus Albuquerque criamos um repositório com o objetivo de implementar o mesmo algoritmo em diferentes linguagens e paradigmas, de LISP a Brainfuck, de Rust a COBOL! Nele vocês podem comparar a implementação de Java ou C#, por exemplo, com a de Smalltalk, e ver estrelinhas brilharem! O Renan Ranelli ─ nosso Milhouse ─ também tem um vídeo bem interessante e humano sobre a definição de OO “hipster”.

Por favor, não me matem…

Quando vocês aprendem OO na faculdade, no geral, estão aprendendo um modelo de programação baseado em classes para uma linguagem ─ ou grupo de linguagens ─ em específico, que herda e implementa ─ mas não em sua totalidade ou maior parte ─ os conceitos de OO. Os conceitos de polimorfismo, herança e visibilidade podem ser adicionados, mas não estão necessariamente e intrinsecamente ligados à definição amplamente aceita de OO. Meu objetivo não é causar tretas ou dizer que a linguagem não é o que diz ser, mas apontar falhas conceituais históricas e deixar o conceito original um pouco mais claro. Reclamações, favor falar com o Milton. Obrigado!

Referências e links úteis

--

--