Skip to content

Instantly share code, notes, and snippets.

@douglasselias
Last active March 5, 2024 01:15
Show Gist options
  • Save douglasselias/366817038ec74d012467ee46d1bdf4c9 to your computer and use it in GitHub Desktop.
Save douglasselias/366817038ec74d012467ee46d1bdf4c9 to your computer and use it in GitHub Desktop.

LucasAyabe

mas ou o título é muito click bait

Não entendo porque é clickbait, se eu estivesse apenas falando minha opinião e não apresentasse nenhuma referência para apoiar meu argumento, ai sim seria clickbait.

mas não apresentou muitos argumentos sobre os motivos que levam a isso, cada parágrafo apresenta um efeito, sem realmente mostrar que a OOP é a causa dele

Confesso que dissertação nunca foi meu forte. É exatamente esse tipo de comentário que ajuda eu saber onde preciso melhorar na minha argumentação. Outro efeito é que ajuda na discussão sobre o tema. Seu comentário foi o que mais se aprofundou no tema.

Sobre os motivos para se ignorar a POO, a performance realmente é algo importante, mas assim, claramente não se utiliza OO por conta da performance, se performance fosse o argumento mais importante de todos, a gente não utilizaria outro paradigma que não fosse procedural, ou quem sabe abandonar tudo isso e voltar pro assembly não-estruturado.

Nos links que coloquei sobre performance, ficou bem claro que a troca de paradigma resultou em melhor performance. Então sim, OO foi a causa. Surge a questão: você está trocando a performance pelo quê? Qual o benefício de usar OO que supera ter o benefício de performance?

No vídeo Performance Excuses Debunked Casey Muratori lista alguns argumentos que defendem que performance não é tão importante. Como contra-argumento ele mostra que várias empresas grandes de software chegam ao ponto de reescrever toda a infraestrutura da aplicação deles por causa de má performance. Então, cedo ou tarde você vai precisar se preocupar com performance, a questão é quando.

Daquela lista, eu conheço o Elegant Objects, e apesar de eu gostar bastante das opiniões dele, e algumas coisas realmente estarem mais alinhadas com os princípios, claramente o que ele quer é uma forma diferente de FP, e não de OOP,

Segue a definição dele sobre Elegant Objects:

Elegant Objects (EO) is an object-oriented programming paradigm that renounces traditional techniques like null, getters-and-setters, code in constructors, mutable objects, static methods, annotations, type casting, implementation inheritance, data objects, etc.

Ou seja, é sim um forma diferente de programar OO seguindo alguns conceitos da progração funcional.

Livros sobre como lidar com procedural legado realmente existem, um dos melhores livros de PHP que eu já li fala exatamente sobre esse tema, inclusive a solução que ele propõe é a aplicação de um tom mais OO com design patterns

Interessante, depois vou ver se consigo dar uma lida. No entanto você apenas citou um, no meu caso eu citei uns três.

Não se discute muito mais sobre problemas de procedural, porque os problemas já são bem conhecidos, falta de encapsulamento, mecanismos de abstração tendem a ser mais pobres em linguagens que só suportam esse paradigma, estado global, estado mutável sem controle, spagetti code, e etc.

Não deveria ter mais livros, e de décadas diferentes, sobre os problemas de programação procedural? Por que falta de encapsulamento é ruim? Quais mecanismos de abstração? O que seria extamente estado mutável sem controle? O que é spaghetti code? Quais características dele OO resolve?

Sobre a questão da evolução das linguagens, eu não diria que Erlang é uma linguagem lá muito moderna, ela é bem antiga até para falar a verdade, moderno nesse contexto provavelmente seria o Elixir.

Correto, foi erro meu na hora de escrever. Era para ser Elixir mesmo.

Apesar disso, eu tenho uma boa explicação para isso, a FP vem se popularizando muito nos últimos tempos, então o natural é que as linguagens evoluam na direção de ir adotando mais recursos desse paradigma, foi exatamente o que aconteceu com a OO. O motivo é simplesmente que elas evoluem na direção das ferramentas que podem adicionar algo a mais para elas, Java já implementa muitas coisas de OO, não tem muito mais de OO que implementar ali, logo o caminho natural seria ver como ele poderia se beneficiar de outros paradigmas. Até porque isso reflete até a maneira que nós programamos no dia-a-dia

No geral eu concordo. No entanto eu não vejo linguagens não-OO adotando conceitos OO.

você não disse que o ponto dos defensores era que OO é a única solução para esses problemas, o ponto é que esses seriam campos onde ela seria uma solução efetiva, não é sobre ser melhor ou pior que outras soluções.

Independe se eles defendem que é ou não a única solução, o fato é que eles afirmam que OO é boa para projetos grandes e complexos. Daí, quando alguém critica OO eles usam esse argumento, e que não daria pra mostrar como OO ajuda nesses pontos, devido a não ser possível dar um exemplo não trivial. Então, por que OO seria uma solução efetiva para projetos grandes e complexos?

Aqui a gente chega no seu primeiro exemplo de código, nesse ponto eu achei o artigo meio desonesto, se você olhar no repositório essa é a versão 1 do código, sendo que elas vão até a versão 11.

O código da versão 11 é o resultado final da refatoração que o Martin Fowler faz no livro. Ou seja, versão 1 e 11 são equivalentes em seu funcionamento. Alguém poderia dizer que eu peguei a versão 11 só para tentar provar meu ponto. Porque seria uma diferença muito maior de linhas de código e número de arquivos.

Você não pode dizer o mesmo da versão 11. Claro que ainda tem mais arquivos e LoC (Linhas de Código), mas essa não é a única métrica que importa, se não, não existiriam recursos de abstração na maioria das linguagens, e se o único benefício disso (abstração) fosse reúso de código, então a OOP seria o melhor paradigma de todos, já que nada vence herança múltipla + polimorfismo em termos de reúso de código, o problema são as outras coisas que vem disso.

Concordo que LoC não é a única métrica que importa, mas qual benefício foi adquirido por criar mais classes, conceitos (abstrações) e arquivos sendo que poderia ser um simples arquivo de menos de 60 linhas? Se alguém que não conhece o projeto fosse dar manutenção, não seria mais fácil ele ler um arquivo de 60 linhas ao invés de vários arquivos e classes, igual na versão 11?

Não vou falar muito sobre legibilidade pois em muitos casos isso tende a ser meio subjetivo, eu por exemplo acho muito mais simples ler um reduce do que um for hoje em dia para qualquer operação em arrays.

Concordo que legibilidade varia de pessoa pra pessoa e também vários fatores como tempo de experiência e familiaridade com a linguagem. Por isso que no final do post eu falo que se você ignorar OO seu código fica mais simples.

Pelo seu código a gente consegue ver uma área onde a OOP realmente se destaca que é o polimorfismo, o seu código teria problemas para evoluir caso novos tipos de código fossem adicionados, e aquele switch só cresceria (e ficaria mais complexo) ao longo do tempo, com OO, isso seria uma aplicação simples do OCP do SOLID.

Qual o problem de um switch case grande? Quais problemas exatamente eu teria?

Sobre padrões de projeto, isso existe em qualquer lugar, são simplesmente as soluções mais comuns que as pessoas tem para qualquer coisa, coleções de padrões existem até para áreas fora da programação como o design.

Já abordei isso no meu post:

O único propósito dos padrões de projeto é corrigir deficiências na linguagem, especialmente C++ e Java.

Só que o seu código não simplificou em nada o código original, inclusive depender uma função sendUpdate, meio que tem quase o mesmo efeito de implementar um padrão observer é só que é uma solução mais prática e menos robusta.

Porque não simplificou? E porque menos robusta? Já respondi isso em outro comentário, vou colocar aqui também:

Na minha versão eu removi dois arquivos e um design pattern e no geral simplifiquei a estrutura e reduzi o número de linhas de código. Agora tudo fica centralizado na função updateGame. Além disso, otimizei a lógica de colisão com as frutas, ao invés de iterar por todas as frutas pra verificar a colisão, eu criei um dicionário com as coordenadas x e y da fruta como id. Assim ao invés de ser O(n), fica O(1).

O seu código piorou o original, ele faz literalmente a mesma coisa que o original, só que ao invés de separar cada ação que vai alterar o estado da aplicação numa função (o que seria um bom senso até em programação procedural), você colapsou todas as funções dentro de um switch gigante, o que só aumenta a complexidade do código ao invés de diminuir.

Só porque está tudo numa função grande isso aumenta a complexidade? Mesmo que esteja orgnizado por cases?

Juntar tudo em uma única função tem os seus méritos, mas nesse caso nem ajuda muito, pois agora quem for ler o código onde ela foi usada, vai ter que procurar em qual ponto de uma função enorme, que nem é pura, que aquele comando está sendo tratado, ao invés de simplesmente procurar no módulo que lida com ele.

Por que não daria pra usar um Ctrl+F no código pra achar o case que você precisa?

O encapsulamento provido pelo uso de objetos é uma das melhores formas de lidar com dados mutáveis, pois você consegue restringir as formas com que ele pode ser modificado, o que é algo muito útil para softwares empresariais que precisam de políticas fortes que assegurem as regras de negócio da aplicação. Claro que todo paradigma permite que você reforce regras de negócio, tal como um if e status code no procedural, ou uma result monad em FP, mas só a OO consegue fazer esse tipo de validação a nível de dado para todas as operações que envolvem ele.

Poderia elaborar mais? Talvez dar alguns exemplos.

Pois, por mais que FP seja incrível, o tipo de polimorfismo que ela oferece só resolve metade do Expression problem (https://en.wikipedia.org/wiki/Expression_problem), o modelo de subtyping da OO resolve a outra metade, e esse é um problema justamente pois não tem como resolver os dois lados ao mesmo tempo.

Achei que você estivesse familiarizado com a solução do 'problema' de expressão, visto que você conhece sobre o assunto. Nessa pergunta do Stack Overflow tem uns gists com código em Clojure, Haskell e Scala que resolvem o problema.

Por isso que problemas onde a OO é melhor, geralmente são problemas onde você consegue abstrair uma estrutura hierarquica entre os objetos.

Poderia dar exemplos desses problemas?

Herança, graças as classes abstratas, é uma ótima forma de pegar boas abstrações que emergirem de uma codebase, e centralizar elas num lugar só, de modo a tornar o desenvolvimento mais incremental.

Poderia dar exemplos dessas classes abstratas?

Os frameworks que usamos no dia-a-dia são o maior exemplo dos benefícios que essa funcionalidade pode trazer, apesar de realmente não ser uma boa solução em userland, ter ferramentas que se utilizam disso, é um aspecto positivo sobre esse princípio.

Não existe só framework OO.

josefilho

Obrigado pelo comentário. Concordo com tudo o que disse. Esse post foi mais um desabafo sobre a atual cultura de tecnologia que simplesmente repete o que viu e ouviu sem ao menos fazer uma análise crítica sobre o assunto. Por exemplo: alguns dias atrás vi um post no Linkedin sobre Design Patterns em TypeScript. No post, um dos design patterns era o Strategy. O problema é que não faz sentido nenhum mostrar como criar as classes pra aplicar o Strategy, sendo que o TypeScript tem funções de primeira ordem. O post gerou muitos likes e comentários parabenizando o autor, mas ninguém mencionou que há uma maneira mais simples de se fazer a mesma coisa. Não é apenas POO e Design Patterns que vejo os programadores repetindo o que aprenderam nas redes sociais. Por isso, no meu primeiro post do meu blog, eu citei coisas que você deveria ignorar. Coisas que eu acredito que não valem a pena gastar tempo aprendendo porque não agregam valor no que realmente importa para ser um bom programador. Eu tinha alguns rascunhos para posts provocativos como: Clean Code, SOLID e Clean Architecture, mas infelizmente, devido a reação muito negativa, perdi o interesse em trazer essas provocações, não vejo mais valor em gastar meu tempo com isso. Sucesso e um forte abraço.

jlucasortiz

mas seu projeto ficará completamente esquisito e estranho

O que especificamente ficaria esquisito e estranho no meu projeto?

vc precisa de OO para implementa-la.

Porque é necessário OO para implementar MVC? Além disso a idea do MVC é a separação de camadas e não implementação.

mas não vi nada com PHP, Python...

Porque não há necessidade, o que estou discutindo é o paradigma orientado a objetos.

como hoje em dia vc desenvolveria na área de Machine Learning sem utilizar OO com as bibliotecas como TF, PyTorch... Aí sim vc teria uma perda de performance .

Qual é a relação entre ML e OO? Só porque as bibliotecas TF e PyTorch são OO? O que exatamente seria essa perda de performance? Seria menos performático usar código não-OO em ML? Se for esse o caso, sugiro assistir os três vídeos no início do post.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment