segunda-feira, 4 de agosto de 2014

Problemas com Repository e ORM

Em um post anterior eu evidenciei uma tendência de se encapsular frameworks em classes da própria aplicação. Dei uma atenção especial ao padrão Repository utilizado com ORM’s, e nesse post resolvi  destacar outros problemas que podem ocorrer com esse padrão.

Nem sempre é fácil identificar a responsabilidade

Quando estamos definindo os métodos do repositório os métodos básicos são fáceis de definir:
  1. GetById;
  2. Save (InsertOrUpdate);
  3. Delete;
  4. GetBy(Filter filters);

Vamos pegar um cenário onde você tenha um classe Customer e a classe Sale tendo cada uma delas a sua devida implementação do Repository.
Agora imagine um item do seu dashboard onde você exibe o total de vendas dos clientes:


Em qual repository você colocaria a implementação dessa consulta? Customer ou Sale?

Funcionalidades que requerem consultas e escritas no banco de dados que cruzam as fronteiras estabelecidas pelo padrão é algo muito comum. Quando surgem cenários desse tipo alguns utilizam estrategias que podem degradar a performance da aplicação como o Select N+1.

Dificuldade para resolver problemas de Performance

O Select N + 1 significa que você foi mais de uma vez no banco de dados para obter dados, no exemplo acima tivemos as seguintes requisições no banco de dados.
  1. Obtém todos os clientes;
  2. Quando acionada a propridade Sales de o sistema foi no banco para obter as respectivas vendas, ou seja, se tivermos 10 clientes o sistema irá 10 vezes no banco buscar as vendas de dos clientes;
Até aqui esses problemas reportados não é culpa do padrão + ORM mas só do padrão. Com os repositories nós não conseguimos customizar o retorno do banco de dados para necessidades especificas, até por que isso foge um pouco das responsabilidades do padrão.

Como uma solução pra esses tipos de problemas muitos preferem expor recursos do ORM pelo Repository, como exemplo:
  • Enable/Disable Lazy Loading;
  • Multi Queries;
  • Operações em Batch;
O problema que isso se torna um “vazamento” da abstração que o Repository se propõe a fazer, se chegamos nesse ponto por que precisamos do padrão?

Organização e reaproveitamento de código

Alguns programadores ainda defendem a utilização do Repository por questões de organização e reaproveitamento de código e realmente processos de escrita e leituras duplicados não é legal. Pra resolver esses problemas já existem outros padrões bem interessantes pra ser utilizado (QueryObjects e CQRS).

Conclusão

Encapsular frameworks não é uma boa idéia, isso não significa que você não possa criar "facilitadores" para melhorar ou até mesmo contextualizar os frameworks para sua necessidade. Acredito que o ideal é sempre permitir que esses frameworks sejam utilizados diretamentes se necessário, assim todo o potencial dessas ferramentas sempre estará disponível.

quinta-feira, 6 de março de 2014

Validando datas para envio ao banco de dados SQL Server

É muito comum achar validação de dados para envio ao banco de dados da seguinte forma:

O problema de validar desta forma é que o DateTime.MinValue retorna 00:00:00.0000000, January 1, 0001  enquanto a data minima aceita pelo SQL Server é 1/1/1753.

Para que a validação seja valida para o envio a um banco de dados SQL Server você pode fazer como abaixo:

terça-feira, 14 de janeiro de 2014

quinta-feira, 12 de dezembro de 2013

Postmon - API para consultar CEP

O Postmon é uma api REST construída em Python e MongoDB para consulta de CEP e encomendas.
Nessa apresentação do InfoQ Alê Borba conta a história da criação da API.

Site da API: http://postmon.com.br/

terça-feira, 10 de dezembro de 2013

Templates free para o Bootstrap

Pra quem ainda não conhece o Bootstrap, ele é um dos mais famosos frameworks de interface web.
Amplamente difundido entre designers e programadores, sua utilização tem sido cada vez mais utilizadas principalmente devido a recursos bem interessantes como recurso de layout reponsive.

Um dos sites mais famosos de vendas de layout, o ThemeForest tem em vários de seus produtos o Bootstrap como base. Mas pra quem não esta afim de gastar em torno U$30,00 (em média) para ter um layout pronto com o Bootstrap, você pode baixar layouts free (bem mais simples) no Start Bootstrap ele tem alguns templates prontos como:




segunda-feira, 9 de dezembro de 2013

domingo, 23 de dezembro de 2012

ASP.Net MVC: Muito código nas Controllers

Eu tenho utilizado muito o ASP.Net MVC e sem dúvida é uma grande tecnologia, mas resolvi colocar nesse post alguns problemas que eu passei e como resolvi.

Com o ASP.Net Web Forms, por padrão, temos um code behind (*.aspx.cs) por página (*.aspx) isso significa que temos tem uma classe, que podemos de certa forma caracterizar como uma controller, responsável por uma View. Já no ASP.Net MVC podemos ter um Controller responsável por varias views. Ex.: ProdutoController  responsável pelas view Pesquisar, Detalhe, Edicao. Nesta mesma controller podemos potencializar a sua aplicação deixando-a responsável por responder chamadas de json.

Bom com isso acabamos tendo muito código nas nossas controllers (consultas, escritas, conversões de tipos etc). E isso não é culpa da tecnologia é apenas uma questão de como organizar as idéias e responsabilidades.


Com essa quantidade de código nas Controller fica dificil de dar manutenção, mesmo refatorando em métodos você acaba vendo um código muito extenso na sua controller o que de cara parece ser um mal sinal (ou um mal cheiro).

Não precisamos "reinventar a roda" para resolver esses problemas, grandes mentes já tem várias sugestões sobre isso e quero apenas apresentar algumas delas que eu estou utilizando e tem me agradado.

CQRS (Command Query Responsibility Segregation) é um padrão que tenho utilizado para organizar esse tipo de coisa, não vou entrar em detalhes sobre o padrão, isso vai ficar para outro post, vou focar apenas em como estou aplicando nos meus projetos.

Consultas

O primeiro problema que eu resolvi foi referente a consultas. Se você utiliza um OR/M como o Entity Framework ou NHibernate com o ASP.Net MVC você pode acabar tendo muito código de consulta dentro da sua controller.

OBS.: Eu não costumo encapsular os frameworks de OR/M com DAOs ou Repositories. Se estiver interessando no motivo leia o artigo abstração da abstração. Só pra reforçar que isso também não é coisa da minha cabeça, Ayende Rahien é um grande defensor da idéia de que abstrair OR/M é um erro.

Eu utilizo para as consultas o Query Object Pattern (link), com isso consigo encapsular as consultas nessas classes. Isso também evita a questão de trazer todas as propriedades das entidades relacionadas na consulta, eu consigo criar consultas espeficidas para fins específicos de uma View, o que traz um grande ganho de performance. (uma coleção de uma determinada entidade para popular um combobox pode te dar muito dor de cabeça. Acredite!).

Escritas

Para as escritas estou utilizando o Command Pattern, com ele eu consigo refatorar o processo de escrita em várias blocos de comando, afinal nem sempre nossas telas só precisamos executar um salvar correto? Como utilizo muito o Entity Framework, também fica fácil seperar esses comandos utilizando uma única instancia de context e controle de transação quando necessário.

Se você pesquisar sobre esse padrão verá outros padrões relacionados como o Tasks e Events, porém os meus projetos até o momento não precisou desse potencial todo.

Basicamente estou organizando os meus projetos da seguinte forma:
  • Entities
  • Commands
  • QueryObjects
  • Controllers
  • Views
  • Models
É claro que isso pode variar de projeto a projeto, mas no geral os projetos que tenho trabalhado esse tipo de organização tem atendido muito bem, sendo bastante produtivo mas sem perder a organização e flexibilidade do código.

Até a próxima!

sábado, 13 de agosto de 2011

Extensions Methods e Namespaces

Eu utilizo Extensions Methods para praticamente duas finalidades:

  • Implementar uma funcionalidade não existente para um objeto;
  • Dar uma maior coesão a um trecho de código;

Como exemplo de coesão, veja o trecho de código abaixo:

img01

Para deixar o código um pouco mais coeso pode implementado da seguinte forma:

image

Para criar uma classe que implemente o código que queremos é muito simples:

image

Agora pra utiliza-lo basta fazer o seguinte:

image

Pois é, o Visual Studio já me avisou que não encontrou o meu método de extensão. Isso se dá por que esqueci de fazer o using para o namespace onde esta a extensão, e isso aconteceu por que o intellisense  não me deu essa opção.
Quando criamos um extension method dentro de uma namespace precisamos lembrar de fazer o using manualmente toda vez que queremos utiliza-lo, o que nem sempre é legal.

O que podemos fazer nesse caso?

Duas opções:

  • Não definir uma namespace para a sua classe que contém os métodos de extensão;
  • Definir o namespace igual ao objeto ao qual o método esta atrelado.

Fica ai a dica, agora é só mandar bala nos extensions methods.

terça-feira, 19 de abril de 2011

O Inferno do Utils, Tools e afins!

Quando estamos pensando nas “camadas” da nossa solução, principalmente no começo do projeto, de uma forma geral temos grandes preocupações com assuntos como por exemplo coesão de responsabilidades, baixos acoplamentos, performance e segurança.
Se você esta em um projeto onde o pessoal diagrama tudo antes de começar a programar, se for criado uma classe diferente do que estava no diagrama os alarmes de incêndio são disparados.

De repente surge uma necessidade de enviar e-mail em mais de um ponto do sistema. Nós como “bons programadores”  que somos não vamos duplicar o código, então o que fazemos? Criamos um projeto chamado Utils (tools e seus primos).
Se precisamos encapsular uma transferência de arquivo via ftp agora não temos mais a “dor de cabeça” de decidir onde colocar esse tipo de funcionalidade, muito simples vai para o Utils.
Encapsulamento de leitura e gravação de um xml também não é mais problema, é só colocar no Utils que fica “tudo certo”.

Se pegarmos esse exemplo em particular fica claro que todos os cuidados que estávamos tomando na criação da solução foram totalmente ignorados quando passamos a ter o projeto Utils. E o pior é que fica tendencioso, se aparecer qualquer funcionalidade que não sabemos onde colocar, ela possivelmente irá parar no Utils.

Existem vários problemas com essa abordagem sendo alguns deles:

  1. O projeto fica dependendo de vários Assemblies, das mais diversas finalidades: E-mail, FTP e acesso a banco são dependências claras no exemplo citado.
  2. Se você tiver vários projetos que utiliza o seu Utils, cada alteração que você faça no seu Utils, recompila todos os projetos dependentes.
  3. O projeto vira um “saco de lixo” de código. Lixo mesmo, por que é incrível como a grande maioria das vezes a qualidade do código cai em classes que são colocadas nesses projetos.

Precisa realmente encapsular o envio de e-mail? Precisa mesmo? Será que você não esta sendo motivado em fazer isso simplesmente para facilitar o envio de e-mail? Será que você não esta criando uma abstração da abstração?


Caso seja realmente necessário encapsular o envio de e-mail minha sugestão é que faça isso de verdade, crie uma projeto com essa funcionalidade com um nome sugestivo para o que ele se propõe a fazer. Assim fica claro o que assembly fará, inclusive podemos prever possíveis dependências que isso pode trazer na hora de utilizá-lo.