Tag Archives: Arquitetura de Software

Controlando a crição dos Controllers no ASP.NET MVC

Uma das características que eu mais gosto do ASP.NET MVC é sua extensibilidade, existem diversos pontos que são possíveis de customizar e configurar para que o framework se comporte da maneira que você quer.

A criação dos controllers é um destes pontos e possivelmente um dos menos usados pelos desenvolvedores por ai. Talvez por desconhecimento ou não saber como tirar proveito disso, não sei. Foi isso que me levou a criar este post onde vou apresentar o que podemos fazer ao tomar controle sobre a construção dos controllers.

Antes de prosseguirmos, sabiam que os Controllers utilizam o princípio de Hollywood? Este princípio se resume na seguinte frase “não nos chame, nós chamaremos você” (don’t call us, we’ll call you). Isso significa que, ao criar um novo Controller, você não precisa dizer ao ASP.NET MVC quando chamar ou então como criá-lo, você apenas o define e deixa que o próprio framework cuide do ciclo de vida  dele.

Voltando ao assunto principal, quando realizamos um HTTP Request o framework utiliza as definições de rotas para descobrir qual o controller que deve ser criado e então repassa a responsabilidade de criação para a classe DefaultControllerFactory.

Os controllers são objetos como qualquer outro e é da natureza da Programação Orientada a Objetos que haja a “troca de mensagens” entre os objetos e consequentemente uma dependência de um objeto para outro. É comum um controller depender de uma classe de serviço ou de acesso à dados, a maneira mais comum de gerenciarmos isso é através dos contrutores. Um controller com dependência ficaria assim:

private IMailService mailService;

public HomeController(IMailService mailService)
{
    this.mailService = mailService;
}

Se executarmos assim como está, recebemos uma exception com a mensagem “No parameterless constructor defined for this object.“. Se olharmos um pouco o código do DefaultControllerFactory é possível perceber que é utilizado o Activator.CreateInstance sem a passagem de parâmetros, isso significa que ele irá procurar um construtor sem parâmetros. No nosso caso onde não podemos aceitar a construção do HomeController sem o serviço de e-mail, a solução é tomar controle sobre a criação dos controllers e customizá-los como bem quisermos. Uma implementação bem simples ficaria assim.

public class CustomControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == typeof(HomeController))
            return new HomeController(new LocalMailService());
        return base.GetControllerInstance(requestContext, controllerType);
    }
}

Apesar de eu ter herdado de DefaultControllerFactory, seria perfeitamente aceitável implementar diretamente a IControllerFactory, a diferença é que assim eu economizo diversas linhas de código já que não preciso escrever todos os métodos exigidos pela interface. Para registrar esta customização, é necessário adicionar a seguinte instrução no Application_Start do Global.asax.

ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());

Done! Agora nosso controller está sendo criado com uma instância de LocalMailService. Isso é chamado de injeção de dependência via construtor. Como eu disse acima, essa é uma implementação simples, se olharmos com mais cuidado a classe CustomControllerFactory é possível verificar que esta solução não escala. Se para cada controller for necessário adicionar uma nova condição, nossa classe vai crescer em tamanho e complexidade.

A solução mais utilizada e até onde eu sei a mais recomendada, é utilizar um framework de injeção de dependência. Neste exemplo vou utilizar o StructureMap, o download está disponível no site oficial.

Ao utilizar o StructureMap, a solução final fica assim.

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterDependencies();

    ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}

private void RegisterDependencies()
{
    ObjectFactory.Configure(x =>
        x.For<IMailService>().Use<LocalMailService>()
    );
}

E nossa ControllerFactory ficou bem mais limpa.

protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
    return ObjectFactory.GetInstance(controllerType) as IController;
}

Quando tivermos novos controllers e novas dependências basta registar no StructureMap e o resto já estará sendo feito sozinho.

UPDATE: Para quem está usando o MVC3 e está buscando injeção de dependência nos controllers, uma outra opção ainda mais elegante é usar o DependencyResolver,  o Vínicius Quaiato fez um post sobre isso.

Espero que seja útil :)

Evitando o excesso de ‘null check’ (continuação)

Conforme comentado no outro post, vou descrever aqui outra forma de evitar a verificação de um objeto nulo. Este tipo de verificação que é tão usada causa um bad smell tremendo.

Imagine a seguinte funcionalidade de um sistema de vendas e-commerce:

Quando nós enviarmos um pedido para um cliente que comprou em nossa loja, nós queremos que este cliente seja avisado que seu produto já foi deixado nos correios. Gostariamos de enviar um SMS para os clientes que consideramos ótimo e um e-mail para aqueles que achamos que são bons clientes. Qualquer outro cliente não deve receber o aviso, se ele tiver interesse ele passa no site e verifica o status.

Então, modelando esta user story, podemos ter uma interface chamada de Notificador e algumas implementações como NotificadorViaSms e NotificadorViaEmail. Isso nos permite que em um dado momento possamos incluir algum outro tipo de notificador, por exemplo, NotificadorViaTwitter.

Pois bem, tendo múltiplas implementações eu vou precisar de um factory que vai ser responsável por criar um notificador baseado no tipo do cliente. Aqui vai um exemplo do código:

public class NotificadorFactory {
	public static Notificador cria(Pedido pedido) {
		if (pedido.getCliente().getTipo() == TipoCliente.Otimo)
			return new NotificadorPorSms(pedido);
		else if (pedido.getCliente().getTipo() == TipoCliente.Bom)
			return new NotificadorPorEmail(pedido);
		else
			return null;
	}
}

Seu uso ficaria assim:

Cliente maria = new Cliente("Maria", TipoCliente.Otimo);
Pedido pedido2 = new Pedido(maria);
pedido2.setTotal(520.10f);

Notificador notificador = NotificadorFactory.cria(pedido2);
notificador.enviar();

Então, o que acharam? Ficou legal, não? Eu gostei :) (só não gostei do nome da factory e do seu método, mas não é esse o objetivo).

Só que este código tem um problema. E se a cliente “maria” fosse do tipo Ruim ao invés de Otimo? Segundo a minha user story, eu não deveria avisar ela. Minha factory está correta, se o cliente for do tipo Ruim ela não vai retornar nenhum Notificador, vai retornar null. Quando meu código cliente for chamar o método enviar() vai surgir um NullPointerException.

Solução: coloca um “if notificador != null” antes de chamar o método. Yeah! Resolvemos o problema, mas criamos outro… Em todo lugar que você for usar o NotificadorFactory você vai ter que se lembrar de que ele pode retornar um valor nulo, e por isso será necessário verificar se o retorno é nulo na maioria das chamadas.

Outra solução seria aplicar o Null Object Pattern. Segundo a definição encontrada no Wikipedia:

Original:

In object-oriented computer programming, a Null Object is an object with defined neutral (“null”) behavior. The Null Object design pattern describes the uses of such objects and their behavior (or lack thereof).

Traduzido:

Em programação orientada a objetos, um Objeto Nulo é um objeto que possui comportamento neutro (nulo). O padrão de projeto Null Object descreve o uso de tais objetos e seu comportamento (ou a falta dela).

De forma simplificada, o Objeto Nulo segundo o padrão de projeto é um objeto que não faz nada, que possui um comportamento neutro. Em nosso caso poderiamos ter um notificador chamado NotificadorVazio que seria criado pelo NotificadorFactory ao invés de retornar null. Sendo assim, o código cliente ficaria livre para utilizar o retorno da factory sem se preocupar com NullPointerException pois o retorno nunca seria nulo. Curioso para saber como fica a implementação do NotificadorVazio? Olha que simples:

A Interface:

public interface Notificador {
	void enviar();
}

A implementação nula:

public class NotificadorVazio implements Notificador {
	@Override
	public void enviar() {
		//Não fazer nada
	}
}

A factory:

public class NotificadorFactory {
	public static Notificador cria(Pedido pedido) {
		if (pedido.getCliente().getTipo() == TipoCliente.Otimo)
			return new NotificadorPorSms(pedido);
		else if (pedido.getCliente().getTipo() == TipoCliente.Bom)
			return new NotificadorPorEmail(pedido);
		else
			return new NotificadorVazio();
	}
}

Pronto, resolvemos o problema de forma organizada, orientada a objetos e utilizando padrões bem definidos.

Até mais :D

A teoria da janela quebrada e o desenvolvimento de software

Teoria da Janela Quebrada

Teoria da Janela Quebrada

EDIT: Este post foi criado dia 22/10/2009 e alterado dia 31/01/2010.

A teoria da janela quebrada foi formulada em Nova Iorque após algumas experiências feitas em bairros nobres da cidade. Em um dos testes realizados, um carro foi deixado  parado em uma rua e durante uma semana inteira ninguém tocou no carro. Os responsáveis pela experiência então quebraram propositalmente uma das janelas do carro e deixaram por mais uma semana exatamente no mesmo lugar. Qual foi o resultado? O carro foi completamente destruído, janelas quebradas, peças roubadas dentre outras degradações.

Esta teoria é aplicada em uma Política de Tolerância Zero nos estados unidos onde cada crime, por mais pequeno que seja, passa por uma punição. Uma simples pixação já é suficiente para que o delinquente seja levado pela polícia e a parede pixada é rapidamente limpada. Com o tempo percebeu-se que havia diminuido a quantidade de pixação já que era sabido que havia punição e que a polícia estava sempre de olho. Esta teoria foi assunto de um livro chamado Fixing Broken Windows: Restoring Order And Reducing Crime In Our Communities sobre a sua utilização no combate à crimanilidade.

Vejo que isto também acontece bastante com os aparelhos eletrônicos. Nos primeiros dias após a compra está tudo em perfeito estado, todo o cuidado é pouco para não danificá-lo. Todo esse cuidado acaba quando ele cai pela primeira vez. Na hora da até um aperto no coração, porém, a partir da segunda ou terceira queda ninguém se importa mais.

O que isso tem a ver com desenvolvimento de software? Tudo. O primeiro dia de um projeto é o paraíso, existem poucas classes no sistema, complexidade do código está baixa e o prazo de entrega está bem longe. O tempo vai passando, a complexidade aumentando e o prazo apertando, a tendência é que a qualidade do código baixe, pois você precisa se preocupar mais com a entrega do que com o design do código. Você adquire o famoso Technical Debt. Nesses momentos surge frases como: “Cara, faz assim mesmo, depois da entrega do produto eu te dou mais uma semana para arrumar isso”. Esse dia nunca chega.

Tendo um produto com design ruim ninguém vai se importar de fazer uma manutenção e continuar errando, o que vai contra a regra dos escoteiros, que diz: “Deixe o acampamento mais limpo do que você encontrou” e também se aplica à software.

O que fazer nestes casos? Refactore, refatore e refatore um pouco mais. Deixe o código o mais limpo possível. Se as donas de casa limpam TODA a casa uma vez (ou duas) por semana, porque também não fazemos o mesmo com nosso software?

E ai, você atua em um projeto com janelas quebradas? Cuidado.

Livro: Clean Code, A Handbook of Agile Software Craftsmanship

Sabe aqueles livros que você lê e não para? Então, aconteceu isso comigo ao ler este, Clean Code é um dos poucos livros que dei nota 5 no shelfari.

Martin_MECH.qxd

O primeiro cápitulo é um dos pontos chaves da leitura, ele fala sobre as vantagens de um código limpo, e porquê você deveria se preocupar com isso. Mesmo que um trecho de código compile e funcione da maneira esperada ( certificando-se através de testes unitários )  pode ser ser considerado ruim, legado e mal escrito. O problema é que é muito difícil manter um código limpo, toda a equipe precisa estar ciente dos ganhos que isso pode trazer, e basta uma pessoa violar as regras e o código já vira um carnaval. O que acontece geralmente é que a primeira versão de um componente é desenvolvido de forma clara e bem escrito, nas manutenções subseqüentes as primeiras sujeiras começam a ser inseridas até o momento que vira um monstro onde ninguémtem coragem de tocar.

Nos Estados Unidos as reservas florestais possuem uma regra que diz: “Leave the campground cleaner than you found it”. Imagine isso em um ambiente de desenvolvimento de software, não seria o máximo ter um projeto que o código está sempre mais limpo do que ontem?

Não sei exatamente o que leva algumas empresas a não se preocupar com as boas práticas, é fato que a maior parte dos problemas ocorrem na fase de análise de sistemas, uma análise errada pode resultar em um software inútil, assim como uma ótima análise é um péssimo código resulta em um sistema com os dias contados, daqui 2 ou 3 anos vai sair mais barato fazer outro do que dar manutenção no sistema “legado”. No final quem ganha com isso são as Fábricas de Software, no final do mês são mais horas contratadas, enquanto isso o pobre cliente está lá investindo em algo que logo morre.

wtf-per-minute

Talvez você não tenha como mudar as coisas na sua empresa, mas faça sua parte, limpe o acampamento antes de fazer check-in, tudo bem que um urso pode vir e destruir seu código, mas pelo menos você fica com a consciência limpa de que fez o que era certo.

Como escrever um código clean?

Sugiro a leitura do livro, ele trata sobre nomenclatura de métodos, classes e variáveis, comentários, funções, tamanho da função e responsabilidades (SRP). Dentre outros assuntos, também fala sobre testes automatizados, vejam que esse assunto está presente em todo lugar.

Não adianta ler e achar que vai virar um ninja, é claro que depois de terminar você já vai ter aprendido diversos truques, mas os mais as práticas mais elaboradas precisam de tempo e prática. Na teoria é tudo muito bonito e aparentemente fácil, quando você coloca a mão na massa você percebe que não é tão fácil e que requer muito estudo.

Segue mais alguns links interessantes sobre o assunto:

TechEd Brasil 2009

TechEd Brasil 2009

Tive a oportunidade de participar do Microsoft TechEd Brasil 2009, que ocorreu em São Paulo durante os dias 25, 26 e 27 de agosto. O que posso falar do evento? De maneira geral, foi excelente, super organizado e com conteúdo de primeira. Como nem tudo são rosas, o Lunch Box me deixou na mão, não havia ficado muito claro, pelo menos para mim, que eram lanches estilo McDonald’s, eu estava esperando um almoço normal em um restaurante normal, da próxima vez vou ler o FAQ antes.

General Session

O evento começou com uma apresentação geral com o histórico da Microsoft até hoje, o auditório da UNIP lotou, e foram necessárias mais quatro outras salas que estavam assistindo por streaming. Após essa volta no tempo, Waldemir Cambucci falou sobre o futuro na visão da Microsoft, resumindo os vários slides, o futuro está no S+S (Software + Serviços). Aqui tem uma enorme explicação sobre o assunto escrito pelo próprio Waldemir.

Nesta sessão houve também a presença do BOPE (Batalhão de Otimização de Plataformas Empresarial). Esse negócio de BOPE já ficou meio manjado, todo mundo faz isso agora, é a nova moda, mas eu confesso que deu para rir bastante.

Vou colocar aqui um resumo das palestras que eu assisti e achei mais interessante.

C# – Dicas, Truques e o futuro da linguagem com a versão 4.0 - Alfred Myers

Alfred começou a palestra mostrando um código curioso, você acha que é possível instanciar uma interface? Pois é, ele provou que é possível, mas é INCORRETO, nunca faça isso. Para os curiosos aqui está o how-to para este hack tosco.

As grandes mudanças serão:

ASP.NET MVC com jQuery: retome o controle da sua aplicação web - Giovanni Bassi

Nem foi tanto sobre ASP.NET MVC e jQuery, o que mais foi comentado foi sobre como montar uma arquitetura seguindo os princípios do SOLID. Ficou bem claro que projetar um software não é simplesmente sair programando, existe uma série de padrões e princípios que vão ajudar a construir um produto de qualidade e que seja durável.

Além do mais, foi dada a ênfase de que o framework MVC da Microsoft não é um substituto do WebForms, ele foi criado para atender aos desenvolvedores que procuravam construir softwares seguindo todos estes padrãos, e o WebForms não é o melhor framework para isso (principalmente quando no quesito testes automatizados). Esse ebook sobre SOLID é bem interessante, tendo exemplos em Ruby e C#.

Desenvolvendo aplicações com as novidades do Windows 7 - Bruno Sonnino

O Windows 7 trouxe algumas novidades para os desenvolvedores Desktop, o principal deles é a taskbar. O foco que a Microsoft deu para essa taskbar é incrível, você faz tudo nela. Segundo o palestrante, a tendência é que a tray (onde fica o relógio, geralmente no canto inferior esquerdo) seja removida do SO. Para desenvolver sobre essa nova plataforma você vai precisar de um API, chamada de Windows API Code Pack For .NET.

Na taskbar é possível criar barras de progresso, jump lists, atalhos, thumbnails e outra coisas mais. O maior problema é que se você tentar rodar isso em Windows XP ou Vista, você terá problemas. A saída é a compilação condicional, o que em minha opinião é bem tosco, vou precisar de unit tests adicionais para cada versão de SO.

Unit Testing – boas práticas e patterns - Cezar Guimarães e Fabio Vazquez

Uma das palestras mais interessantes, eu que já tenho certa prática com Unit Testing consegui aprender muita coisa nova, como por exemplo o FIRST (Fast, Isolated, Repeatable, Self-Validating, Timely), cada letra representa uma característica importante dos testes. No quesito de boas práticas conheci também o AAA, que é uma forma de organizar os testes. Não fazia idéia da importância da nomenclatura dos testes, eu sempre escrevi sem padrão nenhum, vou começar a seguir a recomendação deles (tirada do livro The Art of Unit Testing) onde o método deve ter o padrão:

<nome_do_método_a_ser_testado>_<o_que_você_vai_fazer>_<qual_o_resultado>
Play_WhenIClickPlayButton_ASoundShouldBePlayed
Stop_WhenIClickStopButtonWhileIsPlaying_SoundShouldStopPlaying

Testes de Software com Visual Studio Team System 2010 - Brian Keller

Outro palestrante que veio da Corporação, desta vez falando do VSTS2010. Basicamente o que foi dito é que o foco atualmente está sendo em automatizar os testes de API ou então de caixa branca. Os testes manuais também possuem importância, mas até então não havia foco do VSTS2010 nestes testes. Usando o novo Test Lab, os encarregados por executar os testes terão uma ferramente para fazer anotações, automatizar os testes manuais quando possível e outras coisas mais. O interessante é que pode ser rodado dentro de uma máquina virtual, então não teremos mais a famosa desculpa “Na minha máquina funciona”, o tester pode tirar um snapshot e enviar o time de desenvolvimento.

Conclusão

Fantástico, será que em 2010 tem outro?

Convite para grupo de discussão sobre arquitetura .net

Há um ano atrás a minha maior fonte para tirar dúvidas sobre arquitetura era o fórum de Arquitetura do GUJ. Apesar de ser em Java você consegue aproveitar 99% das discussões abertas, esse assunto é do tipo que você aprende uma vez e usa em qualquer lugar. Domain Model, IoC, DI, TDD, Design Patterns em geral é algo que pode ser feito qualquer linguagem, sendo ela dinâmica ou estática (não posso falar de funcional pois não sei :)). Inclusive dentro meus livros de arquitetura, a maioria deles é em Java, o Clean Code (fantástico, merece um review mais tarde) e o Code Complete (na fila…).

Para a felicidade de mais de 400 pessoas (número atual de participantes), ano passado foi criado uma lista de discussão de arquitetura focado em .Net, a idéia veio de um dos MVPs da Microsoft, o Giovanni Bassi. Aqui está a lista e aqui está o site.

Apesar do foco em .Net, temos a participação do Rafael Rosa da comunidade Ruby on Rails, o Phillip Calçado aparece de vez em quando nas threads mais quentes, e já houve a presença do Fábio Akita falando de Ruby on Rails (Vídeo).

Aproveitando o assunto, vou deixar mais alguns blogs que eu recomendo.

  1. O do Scott Hanselman, segundo esta lista com o top 200, este é o melhor blog sobre desenvolvimento desoftware;
  2. O CodeBetter, que é uma compilação de assuntos variados escritos por várias pessoas;
  3. O Bliki do Martin Fowler, preciso dizer algo? next!;
  4. Fábio Akita sobre Ruby on Rails e
  5. Phillip Calçado sobre Softwares e Batatas
http://www.hanselman.com/blog/
Sharing Buttons by Linksku