Este repositório contém exemplos práticos dos princípios SOLID aplicados à programação orientada a objetos. O SOLID é um acrônimo para os cinco princípios de design que visam melhorar a manutenção, legibilidade e flexibilidade do código:
- S: Single Responsibility Principle (Princípio da Responsabilidade Única)
- O: Open/Closed Principle (Princípio Aberto/Fechado)
- L: Liskov Substitution Principle (Princípio da Substituição de Liskov)
- I: Interface Segregation Principle (Princípio da Segregação de Interfaces)
- D: Dependency Inversion Principle (Princípio da Inversão de Dependência)
Cada regra SOLID é explicada e exemplificada em PHP na pasta examples.
/examples
/SRP
- bom.php
- ruim.php
/OCP
- bom.php
- ruim.php
/LSP
- bom.php
- ruim.php
/ISP
- bom.php
- ruim.php
/DIP
- bom.php
- ruim.php
- Navegue até a pasta
examples. - Abra os arquivos de exemplo para entender como cada princípio é aplicado.
Uma classe deve ter apenas uma razão para mudar, ou seja, ela deve ter apenas uma responsabilidade.
class EnviarEmail {
public function enviar($destinatario, $assunto, $mensagem) {
// lógica para enviar email
}
}class Usuario {
public function salvar() {
// lógica para salvar o usuário
}
public function enviarEmail() {
// lógica para enviar email
}
}Uma classe deve ser aberta para extensão, mas fechada para modificação.
abstract class Forma {
abstract public function area();
}
class Circulo extends Forma {
private $raio;
public function __construct($raio) {
$this->raio = $raio;
}
public function area() {
return pi() * pow($this->raio, 2);
}
}
class Retangulo extends Forma {
private $largura, $altura;
public function __construct($largura, $altura) {
$this->largura = $largura;
$this->altura = $altura;
}
public function area() {
return $this->largura * $this->altura;
}
}class Forma {
public $tipo;
public $largura, $altura, $raio;
public function calcularArea() {
if ($this->tipo == 'circulo') {
return pi() * pow($this->raio, 2);
}
if ($this->tipo == 'retangulo') {
return $this->largura * $this->altura;
}
}
}Objetos de uma classe derivada devem ser substituíveis por objetos da classe base sem alterar o comportamento esperado.
class Animal {
public function fazerSom() {
return "Som do animal";
}
}
class Cachorro extends Animal {
public function fazerSom() {
return "Au Au";
}
}class Animal {
public function fazerSom() {
return "Som do animal";
}
}
class Pato extends Animal {
public function fazerSom() {
return "Quack";
}
public function voar() {
return "Voando";
}
}Uma classe não deve ser forçada a implementar interfaces que ela não usa.
interface Gravavel {
public function gravar();
}
interface Leitura {
public function ler();
}
class Arquivo implements Gravavel, Leitura {
public function gravar() {
// lógica de gravação
}
public function ler() {
// lógica de leitura
}
}interface Documento {
public function gravar();
public function ler();
}
class Arquivo implements Documento {
public function gravar() {
// lógica de gravação
}
public function ler() {
// lógica de leitura
}
}As classes de alto nível não devem depender de classes de baixo nível. Ambas devem depender de abstrações.
interface Repositorio {
public function salvar($objeto);
}
class RepositorioDeUsuario implements Repositorio {
public function salvar($objeto) {
// lógica para salvar o usuário
}
}
class ServicoDeUsuario {
private $repositorio;
public function __construct(Repositorio $repositorio) {
$this->repositorio = $repositorio;
}
public function salvarUsuario($usuario) {
$this->repositorio->salvar($usuario);
}
}class ServicoDeUsuario {
private $repositorio;
public function __construct() {
$this->repositorio = new RepositorioDeUsuario();
}
public function salvarUsuario($usuario) {
$this->repositorio->salvar($usuario);
}
}Contribuições para melhorar o conteúdo e os exemplos são bem-vindas! Feel free to open issues or submit pull requests.