Este documento apresenta os cinco princípios SOLID da programação orientada a objetos: Princípio da Responsabilidade Única (SRP), Princípio Aberto-Fechado (OCP), Princípio da Substituição de Liskov (LSP), Princípio da Segregação de Interface (ISP) e Princípio da Inversão de Dependência (DIP). Estes princípios promovem código mais extensível, manutenível e testável, com classes de responsabilidades bem definidas e baixo acoplamento entre elas.
2. “Enquanto a programação estruturada tem
como principal foco as ações
(procedimentos e funções), a programação
OO se preocupa com os objetos e seus
relacionamentos”.
O que é SOLID?
3. O que é SOLID?
Os princípios SOLID são
cinco princípios básicos
de programação e design
orientados a objetos,
introduzidos por Uncle
Bob no início de 2000. Robert C. Martin (Uncle
Bob)
4. Princípios
SRP – Princípio da Responsabilidade Única
OCP – Princípio Aberto e Fechado
LSP – Princípio da Substituição de Liskov
ISP – Princípio da Segregação de Interface
DIP – Princípio da Inversão de Dependência
5. Benefícios
Código fácil de se manter, adaptar e se ajustar
às alterações de escopo;
Código testável e de fácil entendimento;
Código extensível para alterações com o
menor esforço necessário;
Que forneça o máximo de reaproveitamento;
7. Princípio da Responsabilidade Única
class DebitoContaCorrente
{
public function ValidarSaldo($valor) { }
public function DebitarConta($valor) { }
public function EmitirComprovante() { }
}
8. Princípio da Responsabilidade Única
Essa classe valida o saldo e debita conta e
emite comprovante. Ela tende a crescer muito,
pois cada vez que houver alguma mudança
na forma de validar o saldo, ou na forma de
debitar, ou na forma de emitir comprovante
essa classe será alterada.
Agora, aplicando o SRP...
9. Princípio da Responsabilidade Única
public class DebitoContaCorrente{
public function DebitarConta($valor) { }
}
public class SaldoContaCorrente{
public function ValidarSaldo($valor) { }
}
public class ComprovanteContaCorrente{
public function EmitirComprovante() { }
}
11. Princípio do Aberto e Fechado
Entidades de software (classes, módulos,
funções, etc) devem estar abertas para
extensão, mas fechadas para modificação.
13. Princípio do Aberto e Fechado
abstract class CalculadoraSalarioBase{
public function CalcularSalario() ;
}
class CalculadoraSalarioAnalista extends CalculadoraSalarioBase{
public function CalcularSalario() { return 5000; }
}
class CalculadoraSalarioArquiteto extends CalculadoraSalarioBase{
public function CalcularSalario() { return 7000; }
}
14. Princípio do Aberto e Fechado
Segundo o OCP, a classe base
(CalculadoraSalarioBase) nunca pode mudar
(fechada para modificação), porém a posso
tranquilamente estender outras classes a
partir dela(CalculadoraSalarioDiretor,
CalculadoraSalarioEstagiario, etc.)
15. Princípio da substituição de Liskov
Se q(x) é uma propriedade demonstrável
dos objetos x de tipo T. Então q(y) deve
ser verdadeiro para objetos y de tipo S
onde S é um subtipo de T.
16. Princípio da substituição de Liskov
Sempre que uma classe cliente esperar
uma instância de uma classe base X, uma
instância de uma subclasse Y de X deve
poder ser usada no seu lugar.
20. Princípio da segregação de interfaces
Essa classe “SuperInterface” fere o ISP, pois os
clientes são obrigados a utilizar uma interface a
qual não necessitam. As implementações desta
interface precisarão também suprir as
necessidades dos clientes, implementando
métodos que não serão utilizados e/ou não são
de sua responsabilidade.
21. Princípio da inversão de dependência
Dependa de uma abstração(interfaces) e
não de uma implementação(classes
concretas).
22. Princípio da inversão de dependência
public class Botao{
private Lampada _lampada;
public void Acionar()
{
if (condicao)
_lampada.Ligar();
}
}
23. Princípio da inversão de dependência
Esse exemplo viola o DIP, uma vez que o
atributo _lampada receberá uma classe
concreta em vez de uma interface. Sendo
que dessa forma o funcionamento do
método acionar fica restrito apenas a
“Lampada”.
24. Princípio da inversão de dependência
O correto é que em vez de usarmos uma
classe especifica criarmos uma interface
Dispositivo, na qual a classe Lampada a
implementará. Assim, o funcionamento da
classe Botao será estendido para todas as
classes que implementarem Dispositivo,
nos dando flexibilidade.
25. Princípio da inversão de dependência
public class Botao{
private Dispositivo
_dispositivo;
public void Acionar(){
if (condicao)
_dispositivo.Ligar();
}
}
public interface Dispositivo{
void Ligar();
void Desligar();
}
public class Lampada : Dispositivo{
public void Ligar() {
// ligar lampada
}
public void Desligar(){
//desligar lampada
}
}