Eu considero a programação orientada a objetos (POO) um dos tópicos técnicos mais importantes para desenvolver aplicações Java, seguindo os melhores padrões de qualidade de software e utilizando a linguagem com seu paradigma intencional. Neste post irei descrever as minhas respostas e contar as motivações em relação as perguntas que eu faço sobre o tema “Orientação a Objetos”, mencionado no post #0 da série.
Motivação
Apesar de diversos frameworks facilitarem a nossa vida como desenvolvedores, alguns também trazem limitações que costumam interferir no uso das melhores práticas de orientação a objetos. Uma das soluções para isso é pensar a longo prazo e utilizar os conceitos práticos de Domain Driven Design (DDD), como a aplicação de arquitetura hexagonal.
Esse é o tema que eu mais costumo cobrar na parte técnica, porque acredito que é o que pode contribuir mais diretamente na qualidade de software a longo prazo, em conjunto com testes automatizados. As barreiras e facilidades para se desvirtuar da POO são muitas no dia a dia de um Dev Java e por isso é importante ter uma boa noção conceitual e prática para pensar no sistema não só durante o desenvolvimento, mas antes e depois da implementação também.
Perguntas
- O que é uma classe coesa?
Resposta: Uma classe coesa tem uma responsabilidade bem definida, faz exatamente e somente o que ela se propõe fazer.
- O que é encapsulamento?
Resposta: Encapsulamento é o conceito de internalizar atributos e métodos de uma classe, evitando alterações a partir de entidades externas de forma indevida.
- O que é acoplamento?
Resposta: Acoplamento é a relação de união entre duas classes no design de código, conceitualmente existem 3 tipos de relacionamento: composição, agregação e herança.
- Qual a diferença entre composição e agregação?
Resposta: Apesar de na implementação prática serem idênticas, conceitualmente a composição é uma conexão forte entre duas classes, onde uma não faz sentido existir sem a outra e vice-versa. No caso da agregação, uma ou as duas classes relacionadas continuam coerentes ao existir no sistema de forma independente, ou seja, sem a existência de vínculo entre elas.
- Quando você utiliza herança?
Resposta: A relação de herança é uma das mais complexas, pois acredito que só deva ser usada quando se quer reaproveitar código com composição ou agregação, utilizar polimorfismo e, seguindo o princípio de Liskov, conhecer muito bem as pré e pós condições da classe. Ainda assim, pode gerar problemas futuros por furar o encapsulamento e a linguagem permitir que uma classe filha seja capaz de “quebrar” a implementação da super classe. Uma forma de evitar o uso de herança é fazer composição/agregação em conjunto com interfaces e polimorfismo na implementação.
- O que é polimorfismo?
Resposta: Polimorfismo é o conceito de ser ou fazer a mesma coisa de várias formas diferentes e a aplicação prática em Java se dá através do uso de interfaces ou herança. Um dos seus grandes benefícios é a sobrescrita de métodos.
- Cite os princípios SOLID. Você aplica no dia a dia?
Resposta: Os princípios são: Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation e Dependence Invertion. Acredito que todos eles são conceitos de orientação a objetos e eu levo em consideração ao desenhar uma solução técnica, geralmente antes de iniciar um desenvolvimento.
- Você conhece Design Patterns? Costuma aplicar algum no dia a dia?
Resposta: Sim. Cada pattern tem uma aplicação diferente e os mais comuns no meu dia a dia como desenvolvedor são Strategy, Chain of Responsibility, Command, Builder, Factory e o Singleton. Também já utilizei outros como memento, flyweight, bridge, adapter, template method, observer e estes são menos comuns.
Os temas que envolvem a POO são bastante discutidos e pouco alterados com o passar do tempo, eu continuo aprendendo e praticando os conceitos nos projetos em que atuo. A diferença que faz usar orientação a objetos e padrões de projeto é gigante e perceptível, principalmente quando uma alteração no sistema é solicitada.
É verdade que o design do código se torna mais complexo ao utilizar design patterns e seguir princípios de OO, você provavelmente vai escrever muito mais classes, abstrações e precisa pensar bastante antes de começar uma implementação. No entanto, o ganho de tudo isso vem com a flexibilidade, manutenibilidade e legibilidade de soluções complexas.
Apenas para efeito de exemplo, eu considero muito melhor ver e dar manutenção em 50 strategies e commands com responsabilidade única do que em 50 if else if else em uma única classe cheia de responsabilidades.
Para saber mais
Gostou? Foi útil? Concorda ou discorda de algum ponto? Comenta ai e vamos aprender mais juntos.
Espero que te ajude 😉