
Eu frequentemente encontro desenvolvedores que nunca ouviram falar dos princípios SOLID (nós . — Nota do autor) ou da programação orientada a objetos (POO), ou ouviram, mas não os utilizam na prática. Este artigo descreve as vantagens dos princípios de POO que ajudam o desenvolvedor no seu trabalho diário. Alguns deles são bem conhecidos, outros nem tanto, por isso o artigo será útil tanto para iniciantes quanto para programadores já experientes.
Lembramos: para todos os leitores do «Хабра» — desconto de 10.000 rublos na inscrição em qualquer curso da Skillbox usando o código promocional «Хабр».
A Skillbox recomenda: Curso online educacional .
DRY (Don’t Repeat Yourself)
Um princípio bastante simples, cuja essência é clara através do nome: «Não se repita». Para o programador, isso significa a necessidade de evitar código duplicado, além de permitir o uso de abstração no trabalho.
Se houver duas partes do código que se repetem, elas devem ser combinadas em um único método. Se um valor fixo é usado mais de uma vez, deve ser transformado em uma constante pública.
Isso é necessário para simplificar o código e facilitar sua manutenção, que é a principal tarefa da POO. Não se deve abusar da combinação, já que o mesmo código não passaria na verificação tanto com OrderId quanto com SSN.
Encapsulação de mudanças
Os produtos de software da maioria das empresas estão em constante evolução. Portanto, é necessário fazer mudanças no código e mantê-lo. Você pode simplificar sua vida através da encapsulação. Isso permitirá testar e manter a base de código existente de forma mais eficaz. .
Se você está escrevendo em Java, então .
Princípio da abertura/fechamento
Este princípio pode ser facilmente lembrado ao ler a seguinte afirmação: «Entidades de software (classes, módulos, funções, etc.) devem estar abertas para extensão, mas fechadas para modificação». Na prática, isso significa que elas podem permitir mudanças em seu comportamento sem alterar o código fonte.
O princípio é importante quando as alterações no código-fonte exigem uma revisão, testes em módulos e outras procedimentos. O código que segue o princípio de abertura/fechamento não é alterado ao ser ampliado, portanto, causa muito menos problemas.
Aqui está um exemplo de código que viola esse princípio.

Se precisar fazer alguma alteração, isso levará muito tempo, pois será necessário modificar todas as partes do código que possuem ligação com o fragmento desejado.
A propósito, abertura/fechamento é um dos princípios SOLID.
Princípio da responsabilidade única (SRP)
Outro princípio do conjunto SOLID. Ele afirma que "existe apenas uma razão para modificar uma classe". A classe resolve apenas uma tarefa. Ela pode ter vários métodos, mas cada um deles é utilizado apenas para resolver um problema específico. Todos os métodos e propriedades devem servir somente a isso.

O valor desse princípio reside em que ele diminui a ligação entre cada componente do software e o código. Se mais de uma funcionalidade for adicionada a uma classe, isso introduz uma ligação entre duas funções. Assim, se uma delas for alterada, há uma grande chance de prejudicar a segunda, relacionada à primeira. Isso significa um aumento nos ciclos de teste para detectar todos os problemas antecipadamente.
Princípio da inversão de dependência (DIP)

O exemplo de código acima mostra que AppManager depende de EventLogWriter, que, por sua vez, está intimamente ligado ao AppManager. Se for necessário um método diferente para exibir uma notificação, seja por push, SMS ou email, será preciso alterar a classe AppManager.
O problema pode ser resolvido utilizando o DIP. Assim, em vez de AppManager, requisitamos o EventLogWriter, que será introduzido por meio de um framework.
O DIP permite substituir módulos individuais por outros sem problemas, alterando o módulo de dependência. Isso possibilita modificar um módulo sem impactar os demais.
Composição em vez de herança
Existem duas principais formas de reutilização de código — herança e composição, cada uma com suas vantagens e desvantagens. Normalmente, a segunda é preferida, pois é mais flexível.
A composição permite modificar o comportamento de uma classe em tempo de execução, ajustando suas propriedades. Ao implementar interfaces, utiliza-se o polimorfismo, que oferece uma implementação mais flexível.
Até mesmo "Effective Java" de Joshua Bloch recomenda dar preferência à composição em vez da herança.
O Princípio da Substituição de Liskov (LSP)
Outro princípio do conjunto SOLID. Ele afirma que os subtipos devem ser substituíveis pelo supertipo. Ou seja, métodos e funções que operam no superclasse devem ser capazes de funcionar sem problemas com suas subclasses.
O LSP está relacionado tanto ao princípio da responsabilidade única quanto ao princípio da separação de responsabilidades. Se uma classe oferece mais funcionalidade do que sua subclasse, esta última pode não suportar algumas funções, violando esse princípio.
Aqui está um trecho de código que contraria o LSP.

O método area(Rectangle r) calcula a área de um Rectangle. O programa falhará ao executar Square, já que Square não é um Rectangle neste contexto. De acordo com o princípio LSP, funções que utilizam referências a classes base devem poder usar objetos de classes derivadas sem instruções adicionais.
Este princípio, que é uma definição específica de subtipo, foi proposto por Barbara Liskov em 1987 durante uma conferência em uma palestra principal intitulada "Abstração de Dados e Hierarquia" — daí o seu nome.
O Princípio da Separação de Interface (ISP)
Mais um princípio do SOLID. Segundo ele, uma interface que não é utilizada não deve ser implementada. Seguir esse princípio ajuda o sistema a permanecer flexível e apropriado para refatoração ao fazer alterações na lógica de operação.
Essa situação ocorre com frequência quando a interface contém várias funcionalidades, mas o cliente precisa apenas de uma delas.
Como a escrita de uma interface é uma tarefa complexa, modificá-la após a conclusão do trabalho, sem quebrar nada, será problemático.
A vantagem do princípio ISP em Java é que primeiro é necessário implementar todos os métodos, e só então eles podem ser utilizados pelas classes. Portanto, o princípio permite reduzir o número de métodos.

Programação para a interface, não para a implementação.
Aqui tudo fica claro pelo nome. A aplicação deste princípio leva à criação de um código flexível que pode funcionar com qualquer nova implementação de interface.
Deve-se usar o tipo de interface para variáveis, tipos de retorno ou o tipo de argumento do método. Exemplo — usar SuperClass, e não SubClass.
Ou seja:
List numbers= getNumbers();
E não:
ArrayList numbers = getNumbers();
Aqui está uma implementação prática do que foi mencionado acima.

Princípio de delegação
Um exemplo comum são os métodos equals() e hashCode() em Java. Quando é necessário comparar dois objetos, essa ação é delegada à classe correspondente em vez do cliente.
A vantagem do princípio é a ausência de duplicação de código e uma mudança relativamente simples de comportamento. Também é aplicável à delegação de eventos.

Todos esses princípios permitem escrever um código mais flexível, bonito e confiável, com alta coesão e baixo acoplamento. Claro, a teoria é boa, mas para que o desenvolvedor realmente comece a usar o conhecimento adquirido, é necessária prática. O próximo passo após dominar os princípios da OOP pode ser o estudo de padrões de design para resolver problemas comuns de desenvolvimento de software.
A Skillbox recomenda:
- Curso Prático .
- Curso Online Aplicado .
- Curso Prático de Dois Anos .
Fonte: habr.com
