Uma classe precisa ter uma única responsabilidade e apenas um motivo para alterá-la. É o que informa o SRP – Single Responsability Principle (Principio da Responsabilidade única), que é um dos componentes do SOLID.
O que é o SOLID
O SOLID é um conjunto de orientações para você possa trabalhar melhor com a Orientação a Objeto.
- Single Responsability Principle
- Open/Closed Principle
- Liskov Substitution Principle
- Interface Segregation Principle
- Dependency Inversion Principle
O S, que seria o Single Responsability Principle, que iremos tratar nesse artigo. Tende a evitar as classes chamadas God Class, que são classes que fazem tudo, e com isso podem ser problemáticas. Se você precisa ficar alterando vários pontos da sua classe, tem uma maior possibilidade de dar algum bug.
A aplicação do SRP (Single Responsability Principle)
Precisamos criar um cadastro de contato básico, apenas nome e e-mail, e a classe precisará realizar o cadastro e enviar um e-mail para o contato que foi cadastrado.
Segue a classe:
<?php class Contact { public $name; public $email; public function insert() { $pdo = new \PDO("mysql:host=localhost;dbname=site", "root", ""); $sql = "INSERT INTO contacts SET name = :name, email = :email"; $stmt = $pdo->prepare($sql); $stmt->bindValue(':name', $this->name); $stmt->bindValue(':email', $this->email); $stmt->execute(); $this->sendEmail(); } public function sendEmail() { mail($this->email, "Enviar email", "Contato"); } }
Na classe acima, ela tem mais de uma responsabilidade: ela é responsável pelos dados, por fazer persistência, por conectar ao banco de dados e enviar um e-mail.
Ela tenta se responsabilizar por todas as etapas.
Para utilizar, seria assim:
<?php $contact = new Contact(); $contact->name = 'David'; $contact->email = '[email protected]'; $contact->insert();
Apesar da execução parecer simplificada, a classe possui vários problemas: a falta de encapsulamento dos dados, conexão do banco de dados definida dentro da classe (se precisarmos alterar os dados da conexão ou se precisarmos criar um template para o e-mail, teremos que mexer na mesma classe).
Essa classe é bem problemática, porque falta coesão e ela é muito acoplada, não permitindo variações ou utilizações separada dos itens.
E com isso, é preciso separar essas responsabilidades. Vamos refatorar a classe, e separar cada responsabilidade em classes distintas.
<?php class Contact { private $name; private $email; public function setName($name) { $this->name = $name; } public function setEmail($email) { $this->email = $email; } public function getName() { return $this->name; } public function getEmail() { return $this->email; } }
<?php class ContactSendMail { private $contact; public function __construct(Contact $contact) { $this->contact = $contact; } public function shoot() { mail($this->getEmail(), "Enviar email", "Contato"); } }
<?php class ContactDAO { private $db; public function __construct(\PDO $pdo) { $this->db = $pdo; } public function insert(Contact $contact) { $sql = "INSERT INTO contacts SET name = :name, email = :email"; $stmt = $this->db->prepare($sql); $stmt->bindValue(':name', $contact->getName()); $stmt->bindValue(':email', $contact->getEmail()); return $stmt->execute(); } }
Refatoramos a nossa classe, e criamos 3 classes:
- Uma classe Contact, que é entidade, responsável por representar um Contato.
- Uma classe ContactSendMail que é responsável por disparar o e-mail.
- Uma classe ContactDAO que é responsável pela interação com Banco de dados.
Como deve ser utilizada:
<?php //Conexão com banco de dados com PDO $pdo = new \PDO("mysql:host=localhost;dbname=site", "root", ""); /*Define os dados a serem inserido*/ $contact = new Contact(); $contact->setName('David'); $contact->setEmail('[email protected]'); //Classe que será responsavel pelas operações no banco de dados $contactDAO = new ContactDAO($pdo); if($contactDAO->insert($contact)) { //Classe responsável por disparar um e-mail $send = new ContactSendMail($contact); $send->shoot(); }
Conclusão
Cada classe tem o nome coerente do que é responsável, facilitando assim a forma de trabalhar com elas.
É importante ressaltar, que a questão não é ter um método por classe, e sim que os métodos dessa classe sejam coerentes com que o que classe se propõe a fazer.
Caso queira se aprofundar mais sobre SOLID, utilizando no PHP, temos um excelente curso sobre o tema, que você pode assistir uma prévia acessando: Curso de SOLID com PHP
E você? Já usou o SOLID em alguma aplicação? Deixe seu comentário abaixo e compartilhe sua experiência conosco.