quarta-feira, 10 de novembro de 2010

Conceitos de Arquitetura – Desacoplamento por Interfaces

Esse é o segundo artigo de uma série de artigos onde apresentarei alguns conceitos de arquitetura de software utilizados no desenvolvimento de aplicações corporativas. 

O desacoplamento é extremamente importante para aumentar a flexibilidade ao configurar/desenvolver uma aplicação. E isso trás muitos benefícios no futuro, uma vez que o mercado está em constante evolução e a todo o momento os usuários dos sistemas precisam de novas adequações neles.

Uma prática para aumentar o desacoplamento, é a programação com interfaces. Em programação orientada a objetos, interface é um contrato que define o que a classe deve fazer, mas não como fazer. Para aumentar o desacoplamento, quando há dependência entre classes, referenciamos as interfaces da nossa dependência, ao invés de referenciar a classe diretamente. 

Outra prática muito importante para aumentar desacoplamento é separar responsabilidades diferentes em classes diferentes. Ou seja, cada classe deve ter apenas uma responsabilidade. 

Veja abaixo um exemplo que possui uma classe que realiza o envio de e-mail utilizando um servidor SMTP, e uma classe de negócio que precisa enviar e-mail.

public class EnviadorDeEmailPorSMTP {
  …
  public void EnviarEmail(string[] destinatarios, string assunto, string corpo){
    …
    //Realiza o envio de e-mail
    …
  }
}
public class Usuario {
  …
  public void RecuperarSenha(EnviadorDeEmailPorSMTP enviadorDeEmail){
    …
    enviadorDeEmail.EnviarEmail(this.Email, assunto, corpo);
  }
}
Realizando o desacoplamento através da utilização de interfaces temos. 

public interface IEnviadorDeEmail {
  void EnviarEmail(string[] destinatarios, string assunto, string corpo);
}
public class EnviadorDeEmailPorSMTP : IEnviadorDeEmail {
  …
  public void EnviarEmail(string[] destinatarios, string assunto, string corpo){
    …
    //Realiza o envio de e-mail
    …
  }
}
public class Usuario {
  …
  public void RecuperarSenha(IEnviadorDeEmail enviadorDeEmail){
    …
    enviadorDeEmail.EnviarEmail(this.Email, assunto, corpo);
  }
}

Desenvolvendo dessa forma, a classe “Usuario” não está acoplada a uma determinada forma de envio de e-mail. 

Se quisermos criar uma classe chamada “EnviadorDeEmailPorSQLServer”, que realiza o envio de e-mail utilizando um servidor de banco de dados SQL Server. Basta que a nova classe implemente a interface “IEnviadorDeEmail”, e ela poderá ser utilizada para envio de e-mail pela classe “Usuario”. Nesse caso, é perceptível que as duas classes de envio de e-mail fazem a mesma coisa, porém de forma diferente. 

Em certas circunstâncias não é interessante realizar o envio de e-mail, como ao testarmos o comportamento da classe “Usuario”. Neste caso, poderíamos também ter uma classe chamada “FalsoEnviadorDeEmail”, que implementa a interface “IEnviadorDeEmail” mas não realiza o envio do e-mail. 

Utilizei tal exemplo por que fica clara a possibilidade das duas formas de envio de e-mail, e ainda é perceptível a necessidade de não enviar e-mail durante os testes, sem precisar entrar no mérito de testes de unidade. Mas mesmo assim não gosto do envio de e-mail utilizando SQL Server, então, se você souber de um exemplo legal, favor me informar.

0 comentários:

Postar um comentário