A partir desse artigo, vamos conversar sobre um dos assuntos que mais gosto na orientação a objeto, os padrões SOLID. Não quero perder tempo falando tanto da história e como foi criado, no final de cada artigo, postarei algumas referências que explicam esses pontos com bastante clareza. Pretendo ser mais prático do que teórico oferecendo exemplos focados no dia-a-dia, mas claro, antes uma refrescada pra deixar bem claro do que se trata e pra que serve, beleza?

Legal, mas o que é SOLID?

Como gostava de brincar um professor que tive na faculdade, os padrões SOLID deixam o código mais sólido (que piadinha ruim). SOLID na verdade é o acrônimo de cinco siglas onde cada uma delas representa uma maneira sucinta de resolver problemas diários da programação orientada a objeto através do uso de cinco patterns, seja qual for a linguagem de programação.

Descricao_Solid

 

Para que serve?

Listarei abaixo algumas das missões dos padrões SOLID:
– Melhorar a manutenção do código com menos esforço.
– Tornar o código mais fácil de entender e testar.
– Melhorar capacidade de reuso.
– Diminuir o acoplamento entre objetos.

Apresentando o primeiro padrão responsável pela letra “S”!

Apresentando o SRP – Single Responsibility Principle

Single Responsibility Principle ou Princípio da Responsabilidade Única talvez seja a regra mais básica que existe na programação orientada a objeto. O seu mandamento é que um determinado objeto tenha características e comportamentos referente a suas responsabilidades, nada além disso.

Situação do dia-a-dia:

Quem nunca atuou em um projeto onde encontramos classes semelhantes a essa listada abaixo:

using System;
using System.Collections.Generic;
using System.Net.Mail;
using SOLID.Persistencia;

namespace SOLID.SRP
{
      public class Usuario
      {
           DataContext _db = new DataContext();
           public Usuario(string nome, string email, string senha)
           {
               Nome = nome;
               Email = email;
               Senha = senha;
               Ativo = false;
           }

           public int Id { get; private set; }
           public string Nome { get; private set; }
           public string Email { get; private set; }
           public string Senha { get; private set; }
           public bool Ativo { get; private set; }

           public void Atualizar(string nome)
           {
                Nome = nome;
           }

           public void AtivarUsuario()
           {
               Ativo = true;
           }

           public void Inserir(Usuario usuario)
           {
               _db.InserirAtualizar(usuario);
               _db.SaveChanges();
           }

           public List ObterTodos()
           {
               return _db.Usuarios.ToList();
           }

           public void DeletarUsuario(Usuario usuario)
           {
              _db.Remove(usuario);
              _db.SaveChanges();
           }

           public void RedefinirSenha()
           {
                string novaSenha = "NovaSenha*123";
                MandarEmailRedefinicaoSenha(novaSenha);
           }

           public void MandarEmailRedefinicaoSenha(string novaSenha)
           {
                 try
                 {
                      MailMessage mail = new MailMessage();
                      mail.From = new MailAddress("[email protected]");
                      mail.To.Add(Email);
                      mail.Subject = "Você solicitou a redefinição de senha";
                      mail.Body = "Caro sr." + Nome + ", sua nova senha é: " + novaSenha;
                      SmtpClient smtp = new SmtpClient("smtp.gmail.com");
                      smtp.Send(mail);
                 }
                 catch (System.Exception)
                 {
                     throw;
                 }

            }
       }
}

Quais os problemas que essa classe pode oferecer?

Nesse cenário, a classe Usuario além das suas responsabilidades (métodos) como por exemplo ativar o usuário, iniciar suas características (propriedades) ou até mesmo atualizar um valor dela mesma, vemos que ela foi sobrecarregada com a responsabilidade de fazer a persistência no banco de dados e ainda enviar e-mail. Futuramente isso vai gerar problemas graves e sujeita as famosas “gambiarras”. Qualquer modificação futura vai demandar um tempo razoável na análise e na implementação. Outro grave problema é o forte acoplamento, imagine se um dia esse projeto usar um banco de dados diferente, todas as classes terão que ser modificadas. Por fim, mas não menos importante, como a classe que é uma entidade de domínio, tem a obrigação de enviar e-mail, teremos que poluir nosso domínio com a referência do System.Net.Mail também gerando forte acoplamento.

Como resolvemos esse problema?

Teremos que programar um pouco mais para criar, porém em manutenções futuras, o tempo em análise e implementação será consideravelmente menor, como prega a OOP.

Primeiramente, a classe Usuario deveria ter somente métodos referente a comportamentos dela mesma.

public class Usuario
{
     public Usuario(string nome, string email, string senha)
     {
        Nome = nome;
        Email = email;
        Senha = senha;
        Ativo = false;
     }
     public int Id { get; private set; }
     public string Nome { get; private set; }
     public string Email { get; private set; }
     public string Senha { get; private set; }
     public bool Ativo { get; private set; }

     public void Atualizar(string nome)
     {
        Nome = nome;
     }
     public void AtivarUsuario()
     {
        Ativo = true;
     }
     public void RedefinirSenha()
     {
       string novaSenha = "NovaSenha*123";
     }
}

Outro ponto é desacoplar com o uso de interfaces nas rotinas de persistência. Uma sugestão para tal seria usar o Repository Pattern.

 public interface IUsuarioRepository
 {
      void Inserir(Usuario usuario);
      List<Usuario> ObterTodos();
      void DeletarUsuario(Usuario usuario);
 }

De preferência em um projeto a parte, fazemos as implementações das interfaces. Nesse caso, estamos usando Entity Framework:

public class UsuarioRepository : IUsuarioRepository
 {
      DataContext _db = new DataContext();
      public void Inserir(Usuario usuario)
      {
         _db.InserirAtualizar(usuario);
         _db.SaveChanges();
      }

      public List ObterTodos()
      {
         _db.Usuarios.ToList();
      }

      public void DeletarUsuario(Usuario usuario)
      {
         _db.Remove(usuario);
         _db.SaveChanges();
      }
 }

Lembra da rotina de enviar e-mail? O ideal era criar uma rotina para envio de e-mail genérica em um projeto de infraestrutura.

 public class Utils
 {
     public static void EnviarEmail(string de, string para, string assunto, string corpo)
     {
         try
         {
            MailMessage mail = new MailMessage();
            mail.From = new MailAddress(de);
            mail.To.Add(para);
            mail.Subject = assunto;
            mail.Body = corpo;
            SmtpClient smtp = new SmtpClient("smtp.gmail.com");
            smtp.Send(mail);
         }
         catch (System.Exception)
         {
            throw;
         }
    }
 }

Em outro projeto, poderíamos ter uma classe de serviço ou negócio, como preferir, para manipular esse Usuário.

 public class UsuarioBusiness
 {
        IUsuarioRepository _repo = new UsuarioRepository();

        public void InserirNovoUsuario()
        {
             Usuario novoUsuario = new Usuario("Diego", "[email protected]", "mudar*123");
             novoUsuario.AtivarUsuario();

            _repo.Inserir(novoUsuario);

             /*fora da entidade Usuario, alteramos a senha e enviamos o e-mail*/
             Utils.EnviarEmail("[email protected]", novoUsuario.Email, "Usuário criado com sucesso", "Sr. " + novoUsuario.Nome + ", seu usuário foi criado");
        }
 }

Bom galera, esse foi o padrão mais básico, nos próximos artigos veremos os outros quatro padrões nesse mesmo formato, um problema será apresentado e em seguida a solução através do uso de SOLID.

Até lá!!!

Referências

Princípios SOLID
http://www.macoratti.net/11/05/pa_solid.htm

POO – O princí­pio da responsabilidade única – SRP
http://www.macoratti.net/08/06/net_srp1.htm

ASP .NET MVC – CRUD Usando o padrão Repository (revisitado)
http://www.macoratti.net/14/04/mvc_crud.htm

Diego Neves

Desenvolvedor de software, graduado em Análise e Desenvolvimento de Sistemas pela Universidade Nove de Julho, atualmente trabalha na FCamara e tem foco no mundo .NET, possui algumas certificações como MCSD Web Applications, MCSD App Builder, MCSA Web Applications, Microsoft Specialist, MCP e ITIL V3 Foundation.

Facebook LinkedIn 

Comentários

comentarios