Você aprendeu Orientação a Objetos (OO).
Entendeu classes, objetos, atributos, métodos, herança, polimorfismo, interfaces.
Aprendeu algumas soluções comuns para problemas recorrentes estudando Design Patterns.
Mas como e quando usar OO?
Sem dúvida, a resposta tem a ver com organizar o código, minimizando o impacto de mudanças no médio/longo prazo.
No post The Principles of OOD (MARTIN, 2005), Robert Cecil Martin, o famoso Uncle Bob, descreve duas abordagens complementares no uso de OO:
- criar um modelo de domínio no seu código
- gerenciar as dependências do seu código
OO é uma ótima ferramenta para representar, em código, os conceitos do problema que estamos resolvendo. É importante selecionar entidades de negócio e criar um modelo de domínio que as "traduza" para uma linguagem de programação.
Um bom domain model é o foco de metodologias e técnicas como:
- Feature-Driven Development
- Class-Responsibility-Collaboration (CRC)
- Domain-Driven Design
Mas OO também é uma ótima maneira de evitar código "amarrado" demais, controlando as dependências e minimizando o acoplamento. Um bom código OO, com as dependências administradas com cuidado, leva a mais flexibilidade, robustez e possibilidade de reuso.
Dependências bem gerenciadas são o foco de técnicas como:
- GRASP Patterns/Principles
- Design Patterns
- Dependency Injection
- Princípios SOLID.
Nosso foco nesse curso é aprofundar no estudo dos princípios S. O. L. I. D. de Orientação a Objetos, um acrônimo cunhado por Uncle Bob.
Os 5 princípios S.O.L.I.D. são:
- Single Responsibility Principle (SRP): Uma classe deve ter um, e apenas um, motivo para ser modificada.
- Open/Closed Principle (OCP): Deve ser possível estender o comportamento de uma classe sem modificá-la.
- Liskov Substitution Principle (LSP): Subtipos devem ser substituíveis por seus tipos base.
- Interface Segregation Principle (ISP): Clientes não devem ser obrigados a depender de métodos que eles não usam.
- Dependency Inversion Principle (DIP): Módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender de abstrações. Abstrações não devem depender de detalhes. Detalhes devem depender de abstrações.
Esses princípios expõe os aspectos de gerenciamento de dependências do Design Orientado a Objetos (OOD), em oposição aos aspectos de conceitualização e modelagem. Isso não quer dizer que OO é uma ferramenta ruim para conceitualização do domínio do problema ou que não é um bom veículo para criar modelos. Certamente, muitas pessoas extraem valor desses aspectos de OO. Os princípios, porém, focam bastante no gerenciamento de dependências.
Uncle Bob, no post The Principles of OOD (MARTIN, 2005) - Tradução livre
Uncle Bob indica no artigo Getting a SOLID start (MARTIN, 2009) que os princípios não são check lists, nem leis ou regras.
São bons conselhos vindos do senso comum de gente experiente, coletados em projetos reais ao longo do tempo.
Não significa que sempre funcionam ou que sempre devem ser seguidos.
Uncle Bob também descreve alguns princípios relacionados a módulos.
Os 3 primeiros princípios de módulos descrevem como devemos organizar o conteúdo de um módulo. Ou seja, são sobre coesão:
- Release Reuse Equivalency Principle (REP): A granularidade de reuso é a granularidade de entrega.
- Common Closure Principle (CCP): Classes que são modificadas juntas devem estar no mesmo módulo.
- Common Reuse Principle (CRP): Classes que são usadas juntas devem estar no mesmo módulo.
Há mais 3 princípios de módulos, focados no acoplamento e em métricas para avaliar a estrutura de módulos de um sistema:
- Acyclic Dependencies Principle (ADP): O grafo de dependências dos módulos não deve ter ciclos.
- Stable Dependencies Principle (SDP): Dependa na direção da estabilidade.
- Stable Abstractions Principle (SAP): Abstração traz estabilidade.
Robert Cecil Martin, o famoso Uncle Bob, listou os seus 10 (na verdade, 11) mandamentos de OO, no grupo Usenet comp.object (MARTIN, 1995):
Se eu tivesse que escrever mandamentos, esses seriam os candidatos:
-
Entidades de software (classes, módulos, etc) devem ser abertas para extensão, mas fechadas para modificação. (o Open/Closed Principle - Bertrand Meyer)
-
Classes derivadas devem ser usáveis através da interface da classe base sem a necessidade do usuário saber a diferença. (o Liskov Substitution Principle)
-
Detalhes devem depender de abstrações. Abstrações não devem depender de detalhes. (o Dependency Inversion Principle)
-
A granularidade do reuso é a mesma que a granularidade da entrega (release). Apenas componentes que são entregues através de um tracking system podem ser efetivamente reusados.
-
As classes de um componente entregue devem compartilhar um closure comum. Isto é, se uma classe precisar ser modificada, todos as outras provavelmente precisarão ser modificadas. O que afeta um, afeta todos.
-
As classes de um componente entregue devem ser reusadas juntas. Isto é, é impossível separar os componentes uns dos outros para que sejam menos que o todo.
-
A estrutura de dependências dos componentes entregues deve ser um grafo acíclico direcionado (DAG). Não podem existir ciclos.
-
Dependências entre componentes entregues devem ser na direção da estabilidade. O componente que recebe a dependência deve ser mais estável que o que usa a dependência.
-
Quando mais estável um componente entregue é, mais deve ser consistir de classes abstratas. Um componente completamente estável deve consistir de nada mais que classes abstratas.
-
Onde possível, use patterns comprovados para resolver problemas de design.
-
Ao atravessar entre dois paradigmas diferentes, construa uma camada de interfaces que os separe. Não polua um lado com um paradigma do outro.
(Tradução livre)
Em 1996, fez uma série de artigos na revista C++ Report sobre o que chamou de princípios:
- Open-Closed Principle (MARTIN, 1996a)
- Liskov Substitution Principle (MARTIN, 1996b)
- Dependency Inversion Principle (MARTIN, 1996c)
- Interface Segregation Principle (MARTIN, 1996d)
- Granularity (MARTIN, 1996e)
- Stability (MARTIN, 1997)
Em 2002, no livro Agile Software Development: Principles, Patterns, and Practices (MARTIN, 2002), Uncle Bob adiciona o Single Responsibility Principle.
Em 2004, em colaboração com Michael Feathers, reordena os princípios e cunha o acrônimo S.O.L.I.D..
Em 2006, foi lançada uma versão em C# do livro original, com os mesmos princípios: Agile Principles, Patterns, and Practices in C# (MARTIN, 2006).