O princípio aberto fechado, em inglês Open Closed Principle, ou somente OCP, é um dos princípios mais interessantes da OOP. Ele diz que:

“Entidades de software (classes, módulos, funções, etc) devem ser abertas para extensão mas fechadas para modificações” – Bertrand Meyer (1988)

Parece meio contraditório… Mas na prática isso significa que você deve ser capaz de estender uma classe sem modificá-la. Isso acontece com herança, quando você utiliza uma class abstrata, ou até uma não abstrata mas com métodos virtuais. Você estendende a classe base, sem modificá-la, mas completando seu comportamento.

O OCP é sugerido porque, uma vez concluída uma classe, ela é uma unidade funcional que, se alterada, fica sob risco de efeitos colaterais não esperados na aplicação (bugs). Você pode resolver boa parte do problema com testes, mas ainda assim está introduzindo um risco. Nada é mais sólido do que código testado em ambiente de desenvolvimento e produção.

Para aplicar o padrão, tudo começa com a identificação do que não deve mudar e do que pode mudar. As partes que podem mudar você deixa abstratas ou virtuais, ou separa com, por exemplo, uma associação, via padrão Strategy.

Por exemplo, suponha que, em um blog, eu tenha uma ação de postar um comentário. E quero que alguém seja notificado quando um comentário acontecer. No meu controller teria um método assim:

public ActionResult PostarComentario(int id, FormCollection collection)
{
    //algum código
    new NotificadorSMTP().AvisarDoComentario(comentario);
    //mais algum código
}

Só que, se eu quiser mudar o NotificadorSMTP por um NotificadorExchange, vou ter que alterar a classe de controller. Isso não é bom, porque, primeiro, em nada tem a ver com o controller, que é responsável pelo fluxo da interface gráfica, e segundo, o controller já está funcionando e testado. Se eu identifiquei que isso é uma mudança possível, não posso trabalhar com o notificador desta forma. Uma opção seria trabalhar com um Strategy com injeção de dependência e inversão de controle. Ficaria assim:

public class PostsController
{
    private Notificador _notificador;
    public PostsController(Notificador notificador)
    {
        _notificador = notificador;
    }
    public ActionResult PostarComentario(int id, FormCollection collection)
    {
        //algum código
        _notificador.AvisarDoComentario(comentario);
        //mais algum código
    }
}

Agora já posso trabalhar com o controlador sem depender do NotificadorSMTP, ou do NotificadorExchange. A classe apropriada, derivada da classe “Notificador” será passada.

Uma opção mais elegante seria trabalhar com Domain Events. Na hora de adicionar um comentário ao post este levantaria um evento de domínio:

public class Post : Entidade
{
    //outros métodos, campos, propriedades, etc...
    public virtual void AdicionarComentario(string corpo, Comentarista comentarista)
    {
        var comentario = new Comentario(this, corpo, comentarista);
        DomainEvents.Raise(new ComentarioAdicionado(this, comentario));
        //outras ações...
    }
}

E eu teria então uma classe que assinaria o evento de domínio:

public class NotificadorPorEmailEmCasoDeComentarios : IEnderecadorDeEvento<ComentarioAdicionado>
{
    public void EnderecarEvento(ComentarioAdicionado args)
    {
        var textoNotificacao = ...;//formatação
        _notificadorEmail.Notificar(args.Post.Autor.Email, textoNotificacao);
    }
    //outros métodos, etc...
}

É uma opção bastante interessante, onde eu removo a responsabilidade de notificação do controller, já que ela não deveria estar lá desde o começo. Outro dia eu falo mais de eventos de domínios. É um tema que está na minha pauta faz tempo.

Pra completar, sugiro vocês darem uma olhada no artigo do Uncle Bob sobre o assunto, listado na página que deu origem também ao nome SOLID. O livro que deu origem ao termo, Object-Oriented Software Construction, do Bertrand Meyer, também vale a pena dar uma olhada.


Postado na(s) categoria(s) Arquitetura pelo Giovanni Bassi em 30 de setembro de 2009 às 08:41 | Tags: , , ,

Comentários


Brazil Alessandro
setembro 30. 2009 11:45
Alessandro
Giggio,
tem previsão para o post sobre domains events? Isto muito me interessou (tenho certeza que a muita gente), achei bastante interessante. Andei procurando no google, mais não encontrei nenhum artigo específico.

Parabéns mais uma vez, por sempre trazer novidades muito bem vindas.

[]´s



no site


Brazil Alessandro
setembro 30. 2009 13:05
Alessandro
A propósito, nos eventos presenciais TechResult, em São Paulo, seria bom abordar esse tema. Se bem lembro Marcelo D'Ávila falou que o evento iria ocorrer bimestralmente. O próximo estarei lá novamente. Valeu.

no site


Prodis a.k.a. Fernando Hamasaki de Amorim
Acho que você não foi muito feliz ao misturar no post princípios de design com MVC e depois Domain Events. Além disso, os exemplos de código não estão muito claros.

Eu que conheço SOLID e Design Patterns entendi na boa, mas acho que não conhece o princípio aberto-fechado vai viajar um pouco.

Obs.: Não consigo enviar um comentário aqui usando o Safari no Mac.

http://prodis.pro.br/http://prodis.pro.br/


outubro 4. 2009 11:07
Douglas Aguiar
Giovanni,

O tipo ComentarioAdicionado é um delegate ou uma classe normal?

http://sitewaredevelopers.blogspot.com/http://sitewaredevelopers.blogspot.com/


outubro 5. 2009 03:09
Giovanni Bassi
Prodis,
Por isso que primeiro eu dei a opção com DI.

Douglas,
Classe normal. Viu que chamo propriedades dele na linha 6 da última listagem?

http://unplugged.giggio.net/http://unplugged.giggio.net/

Comentar


(Vai mostrar seu Gravatar)

  Country flag

biuquote
  • Comentário
  • Pré-visualização
Loading



Quem é Giovanni Bassi

Giovanni Bassi Sou uma pessoa apaixonada por tecnologia e especificamente por .Net. Sou consultor independente especialista em .Net, focado em arquitetura e melhores práticas. Tenho dezenas de artigos publicados na .Net Magazine, revista da qual sou editor técnico. Ministro palestras e cursos de vez em quando, e quando dá tempo eu respiro um pouco. Mais detalhes nesta página.

Busca

Selos

Eu vou ao TechEd Brasil 2010, e você?

MVP

MCPD

MCSD

.Net Magazine

Abaixo ao if!

Calendário

«  julho 2010  »
seteququsedo
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678
Ver detalhamento de posts no calendário

Blogs interessantes

    OPMLDownload OPML file

    Postagens recentes

    Comentários recentes

    Disclaimer / Aviso
    As opiniões colocadas neste blog são minhas e pessoais e não expressam necessariamente as opiniões de meus empregadores, pareceiros e amigos. Da mesma forma, os comentários feitos por leitores do blog não expressam a minha opinião.

    © Copyright 2010 .Net Unplugged
    Log in