Ayende e Repository

29 views
Skip to first unread message

Gustavo Rocha

unread,
Apr 23, 2009, 9:49:49 PM4/23/09
to dotnetar...@googlegroups.com
http://ayende.com/Blog/archive/2009/04/17/repository-is-the-new-singleton.aspx

A todos, especialmente ao Bassi. Voce realmente concorda com a abordagem dele?

Se sim, existe realmente um equivoco na implementacao do pattern na maioria dos casos?

Giovanni Bassi

unread,
Apr 23, 2009, 10:04:44 PM4/23/09
to dotnetar...@googlegroups.com
Já tinha lido o post quando ele publicou. Achei bem legal.

Acho que o que ele coloca é uma opção.

Gosto de trabalhar query objects de outra forma. Ele coloca que em muitos casos você só está encapsulando o mapper, e que nunca vai conseguir ser tão rico quando o mapper de verdade, e é verdade. Só que muita vezes, usando o padrão de specification, você consegue dar sentido aos query objects para o domínio. Isso faz toda a diferença. Assim, em vez de falar em termos de propriedades de um objeto, você fala em termos de conceitos de negócio. É bem mais interessante.
Gosto muito mesmo deste padrão specification. Sempre que uso descubro uma outra forma de trabalhá-lo. Ultimamente brinquei um pouco com interfaces fluentes com ele, mas sinto que preciso aprimorar o desenho.

[]'s

Giovanni Bassi
Microsoft MVP, MCSD, MCPD, CSM
Arquiteto de software
http://www.giovannibassi.com


2009/4/23 Gustavo Rocha <gustav...@gmail.com>

Gustavo Rocha

unread,
Apr 23, 2009, 10:13:49 PM4/23/09
to dotnetar...@googlegroups.com
Eu peguei esse post do seu comentario no Twitter.

Eu acho que uma ma implementacao estraga qualquer coisa boa. Mas a busca por tras do Repository é insubstituivel. A busca. O que pretendemos com a ideia do Repository nao é DAO, sao outras coisas. E isso, hoje, eu vejo o quanto é produtivo na pratica. 

To estudando bastante sobre Fluent Interfaces tambem. Esse outro post que eu vi de alguem(acho que seu) é bem legal tambem. Ele e os anteriores:

Sobre Specification vou estudar mais pra ter opiniao.



2009/4/23 Giovanni Bassi <gig...@giggio.net>

Giovanni Bassi

unread,
Apr 23, 2009, 10:16:41 PM4/23/09
to dotnetar...@googlegroups.com
Eu estou com uns posts agendados para publicar sobre fluent interfaces. Eu lancei esse post que você comentou no meu twitter. Dissequei esses posts do elegant code e já tenho vários agendados. É beeeeeeeem legal.
Dá uma olhada em specifications, é bem legal também. No livro de DDD do Evans ele dá exemplos concretos (alguns dos raros), inclusive de um início de FI.

Rodrigo Vieira

unread,
Apr 24, 2009, 5:06:00 AM4/24/09
to dotnetar...@googlegroups.com
Interessante essa discussão. Um dia desses eu tava batendo um papo com
um colega, sobre repositórios, e a gente caiu num ponto relacionado, e
ficamos meio na dúvida qto a resposta. A discussão era: repositórios
fazem parte da camada de negócio, devem ser magros ou gordos? Porque
na prática, o que temos visto em aplicações muito dependentes do BD
são muitas das regras de negócio embutidas no repositório,em forma de
queries, o que fica meio esquisito, o modelo de domínio fica quase
vazio, e os repositórios super gordos. Aí se alguém um dia resolver
substituir o AdoCustomerRepository com um NHibernateCustomerRepository
vai ter que reescrever muita coisa, todas essas regras de negócio o
que torna o processo caro e arriscado.

Acho que a peça que tava faltando na nossa discussão então é essa
questão de ter uma linguagem que nos permita expressar uma regra de
negócio de forma rica no modelo ou serviço, sabendo que isso vai ser
mapeado numa query ótima no repositório. Adoraria achar exemplos de
como isso tem sido feito na prática, acho que é uma boa coisa a se
estudar. Senão o repositório vira basicamente um DAL rebatizado, ou
pelo menos essa é a impressão que eu tenho.

2009/4/24 Gustavo Rocha <gustav...@gmail.com>:

Diego Dias Ribeiro da Silva

unread,
Apr 24, 2009, 7:00:50 AM4/24/09
to dotnetar...@googlegroups.com
Sobre a sua duvida Rodrigo, gostaria de explanar uma "solução" que eu e um amigo tivemos aqui na empresa e gostaria de saber a opnião dos demais participantes.
 
Sobre o repositorios no criamos Interfaces, por exemplo ICustomerRepository, e no projeto atual estamo usando o EF com a classe EFCustomerRepository implementando essa interface. Já temos planos para mudar para NH futuramente, e fariamos a classe NHCustomerRepository.
 
Essa foi uma solução mas queria saber sobre os outros partiipantes, se isso é valido ou estamos indo para o lado errado.

 
2009/4/24 Rodrigo Vieira <rodr...@gmail.com>

Rodrigo Vieira

unread,
Apr 24, 2009, 7:34:03 AM4/24/09
to dotnetar...@googlegroups.com
Diego,

A gente também tá fazendo algo assim no nosso primeiro projeto com
repositórios. Tb tenho curiosidade em saber se é por aí mesmo.

O que tem me incomodado com essa solução é que se por exemplo temos
uma regra de negócio que diz "um cliente é considerado inadimplente se
as condições X, Y e Z ocorrem", isso vira uma query no nosso
Linq2SqlCustomerRepository, algo do tipo
Clientes.Where(...).Where(..).Join(...).GroupBy(...)..., e quando
alguém for implementar um novo repositório, vai ter que reescrever
isso tudo na nova sintaxe. Me parece que o repositorio tá tendo
responsabilidades que não é dele, nesse caso saber quais os critérios
de inadimplência, seria legal se ele pudesse receber tais critérios
como parâmetros de alguma forma. A gente poderia criar uma função
especial no repositório que retorna IQueryable (no caso de Linq2SQL)
ou Criteria (no caso de NH), mas aí estaríamos assumindo um
compromisso de amor eterno com uma tecnologia específica.

Bem, quem tá mexendo com isso há mais tempo com certeza tá tendo um
deja-vu agora :)

- Rodrigo

2009/4/24 Diego Dias Ribeiro da Silva <ddrs...@gmail.com>:

Cássio Rogério Eskelsen

unread,
Apr 24, 2009, 7:44:11 AM4/24/09
to dotnetar...@googlegroups.com
Esquecendo a informática, o que é um repositório? É simplesmente um lugar onde se guardam coisas, e para isso você vai ter formas de colocar, tirar e movimentar "cargas". Um repositório não tem inteligência.

Ayende é um cara muito inteligente, ja acompanho ele desde a época em que que estava encarnado na linguagem Boo  (para quem não conhece, é uma linguagem para .Net cuja sintaxe é muito parecida com Python), no entanto, as vezes me parece que ele quer apenas criar polêmica.

Nhibernate e outros O/R M, por mais bem implementados e bonitos que sejam, no frigir dos ovos continuam sendo apenas.... "gambiarras" para resolver a impedância exisitente entre o mundo OO e o mundo relacional. O próprio nome ja diz, são "mappers", mapper vem de mapa. Desde quando um "mapa" tem inteligência? Você deve aplicar inteligência para construir um mapa, mas o mapa não tem inteligência, tem apenas informação.

Regras de negócio ficam no domínio PONTO, seja nas entidades ou em classes services. Essas entidades vão no repositório e buscam o que precisam. São elas que especificam como serão feitas as queries para o banco. A Query Language é apenas uma forma de comunicação.

Quem, como o Ayende, defende não encapsular o NH ou qualquer outro O/R M, demonstra apenas que não conhece o mundo real, onde não existe essa de File->New->Start New Blog Project. Existe um mundo onde temos sempre um legado para ser preservado, comunicações entre sistemas sendo feitas via banco de dados e a necessidade de pular de um O/R M para outro é uma constante.

abraços,

Cássio Rogério Eskelsen
 
 


2009/4/24 Rodrigo Vieira <rodr...@gmail.com>

Rodrigo Vieira

unread,
Apr 24, 2009, 8:12:27 AM4/24/09
to dotnetar...@googlegroups.com
> Essas entidades vão no repositório e buscam o que precisam. São
> elas que especificam como serão feitas as queries para o banco. A Query
> Language é apenas uma forma de comunicação.

Cassio, qual a solução que vc adotou pra transportar tal especificação
do domínio pro repositório?

Sobre o Ayende, bem, ele ganhou o direito de ser polêmico. É pq ele tá
sempre à frente de todo mundo uns 2 ou 3 anos. Então qdo ele diz que
alguma coisa tá quebrada, em geral todo mundo discorda agora mas acaba
concordando dois anos depois...rs

- Rodrigo

Juliano Oliveira

unread,
Apr 24, 2009, 8:13:28 AM4/24/09
to .Net Architects
Cássio,

Pow, pegou pesado com o "gambiarra"... hehe

O que vocês acham de Repositories com Fluent Interfaces? Algo tipo:

_clienteRepo.Buscar().Todos();
_clienteRepo.Buscar().PorNome("Nome do pelego");

Acham que as técnicas se completam?

[]´s

Juliano Oliveira
Analista Desenvolvedor
.Net, C#, Actionscript, Flex, Nhibernate
http://programandoem.net

On 24 abr, 08:44, Cássio Rogério Eskelsen <eskel...@gmail.com> wrote:
> Esquecendo a informática, o que é um repositório? É simplesmente um lugar
> onde se guardam coisas, e para isso você vai ter formas de colocar, tirar e
> movimentar "cargas". Um repositório não tem inteligência.
> Ayende é um cara muito inteligente, ja acompanho ele desde a época em que
> que estava encarnado na linguagem Boo   <http://boo.codehaus.org/>(para quem
> não conhece, é uma linguagem para .Net cuja sintaxe é muito parecida com
> Python), no entanto, as vezes me parece que ele quer apenas criar polêmica.
>
> Nhibernate e outros O/R M, por mais bem implementados e bonitos que sejam,
> no frigir dos ovos continuam sendo apenas.... "gambiarras" para resolver a
> impedância exisitente entre o mundo OO e o mundo relacional. O próprio nome
> ja diz, são "mappers", mapper vem de mapa. Desde quando um "mapa" tem
> inteligência? Você deve aplicar inteligência para construir um mapa, mas o
> mapa não tem inteligência, tem apenas informação.
>
> Regras de negócio ficam no domínio PONTO, seja nas entidades ou em classes
> services. Essas entidades vão no repositório e buscam o que precisam. São
> elas que especificam como serão feitas as queries para o banco. A Query
> Language é apenas uma forma de comunicação.
>
> Quem, como o Ayende, defende não encapsular o NH ou qualquer outro O/R M,
> demonstra apenas que não conhece o mundo real, onde não existe essa de
> File->New->Start New Blog Project. Existe um mundo onde temos sempre um
> legado para ser preservado, comunicações entre sistemas sendo feitas via
> banco de dados e a necessidade de pular de um O/R M para outro é uma
> constante.
>
> abraços,
>
> Cássio Rogério Eskelsen
>
> 2009/4/24 Rodrigo Vieira <rodrig...@gmail.com>
>
>
>
> > Interessante essa discussão. Um dia desses eu tava batendo um papo com
> > um colega, sobre repositórios, e a gente caiu num ponto relacionado, e
> > ficamos meio na dúvida qto a resposta. A discussão era: repositórios
> > fazem parte da camada de negócio, devem ser magros ou gordos? Porque
> > na prática, o que temos visto em aplicações muito dependentes do BD
> > são muitas das regras de negócio embutidas no repositório,em forma de
> > queries, o que fica meio esquisito, o modelo de domínio fica quase
> > vazio, e os repositórios super gordos. Aí se alguém um dia resolver
> > substituir o AdoCustomerRepository com um NHibernateCustomerRepository
> > vai ter que reescrever muita coisa, todas essas regras de negócio o
> > que torna o processo caro e arriscado.
>
> > Acho que a peça que tava faltando na nossa discussão então é essa
> > questão de ter uma linguagem que nos permita expressar uma regra de
> > negócio de forma rica no modelo ou serviço, sabendo que isso vai ser
> > mapeado numa query ótima no repositório. Adoraria achar exemplos de
> > como isso tem sido feito na prática, acho que é uma boa coisa a se
> > estudar. Senão o repositório vira basicamente um DAL rebatizado, ou
> > pelo menos essa é a impressão que eu tenho.
>
> > 2009/4/24 Gustavo Rocha <gustavohro...@gmail.com>:
>
> >http://ayende.com/Blog/archive/2009/04/17/repository-is-the-new-singl...

Giovanni Bassi

unread,
Apr 24, 2009, 8:21:26 AM4/24/09
to dotnetar...@googlegroups.com
Rodrigo,

A questão é isso mesmo. Repositórios não são DALs. Se seguirmos o que o DDD propõe, eles representam coleções de entidades. Consultas DEVEM ser expressas na linguagem do domínio.


[]'s

Giovanni Bassi
Microsoft MVP, MCSD, MCPD, CSM
Arquiteto de software
http://www.giovannibassi.com


2009/4/24 Rodrigo Vieira <rodr...@gmail.com>

Giovanni Bassi

unread,
Apr 24, 2009, 8:28:29 AM4/24/09
to dotnetar...@googlegroups.com
Isso é o que eu mais faço: Interface pro repositório, na camada de domínio, implementação na camada de Infra, usando NH.


[]'s

Giovanni Bassi
Microsoft MVP, MCSD, MCPD, CSM
Arquiteto de software
http://www.giovannibassi.com


2009/4/24 Diego Dias Ribeiro da Silva <ddrs...@gmail.com>
Sobre a sua duvida Rodrigo, gostaria de explanar uma "solução" que eu e um amigo tivemos aqui na empresa e gostaria de saber a opnião dos demais participantes.

Tiago Soczek

unread,
Apr 24, 2009, 8:31:43 AM4/24/09
to dotnetar...@googlegroups.com
Tenho uma implementação de Specifications + Linq2NH + Overload de operadores, ficou bem bacana, tenho queries do tipo:

var products = productRepository.FindAllSatisfying( ProductSpecs.Available && ProductSpecs.PriceBetween(0, 500) );

Ou

var available = ProductSpecs.Available.SatisfiedBy(product);

E na classe ProductSpecs tenho propriedades e métodos que me retornam um Specification.

public Specification<Product> Available {
    get {
        return new Specification<Product>(p => p.Enabled && p.Quantity > 0);
    }
}


2009/4/24 Juliano Oliveira <jul.ol...@gmail.com>

Giovanni Bassi

unread,
Apr 24, 2009, 8:33:05 AM4/24/09
to dotnetar...@googlegroups.com
Rodrigo,

Encapsula suas consultas em objetos de consulta baseados em specification.
Aí vc faz:
var spec = new EspecificacaoInadimplente();
var clientes = repositorio.ObterPorEspecificacao(spec);

Dentro da spec tem o que vc vai precisar no NH ou L2S.


[]'s

Giovanni Bassi
Microsoft MVP, MCSD, MCPD, CSM
Arquiteto de software
http://www.giovannibassi.com


2009/4/24 Rodrigo Vieira <rodr...@gmail.com>

Giovanni Bassi

unread,
Apr 24, 2009, 8:35:35 AM4/24/09
to dotnetar...@googlegroups.com
Cassio,

Discordo que o repositório tem que ser burro. Só precisamos separar as responsabilidades. Veja o exemplo de especificação que acabei de mandar.
Outra coisa: o repositório não é um mapper. O mapper é o NH ou o EF.
Considero a solução do Ayende interessante, talvez ainda venha a aplicacá-la...


[]'s

Giovanni Bassi
Microsoft MVP, MCSD, MCPD, CSM
Arquiteto de software
http://www.giovannibassi.com


2009/4/24 Cássio Rogério Eskelsen <eske...@gmail.com>

Giovanni Bassi

unread,
Apr 24, 2009, 8:37:24 AM4/24/09
to dotnetar...@googlegroups.com
Bem legal. A única questão é que nesse cenário, o Buscar() não retorna as entidades, mas um IQueryable. Aí é que mora o perigo. Tem que saber tratar.


[]'s

Giovanni Bassi
Microsoft MVP, MCSD, MCPD, CSM
Arquiteto de software
http://www.giovannibassi.com


2009/4/24 Juliano Oliveira <jul.ol...@gmail.com>

Juliano Oliveira

unread,
Apr 24, 2009, 8:41:17 AM4/24/09
to dotnetar...@googlegroups.com
No caso "Buscar()" é exatamente isso, um "return this"
O que você sugere para esse tratamento?
Eu concordo que é frágil, mas é bem legal se usar.


[]´s

Juliano Oliveira
Analista Desenvolvedor
.Net, C#, Actionscript, Flex, Nhibernate
http://programandoem.net


2009/4/24 Giovanni Bassi <gig...@giggio.net>

Giovanni Bassi

unread,
Apr 24, 2009, 8:49:56 AM4/24/09
to dotnetar...@googlegroups.com
Putz, tem n formas de tratar. Você pode retornar uma spec, um Iqueryable...

Cássio Rogério Eskelsen

unread,
Apr 24, 2009, 8:51:03 AM4/24/09
to dotnetar...@googlegroups.com
Giovanni,

Mas foi isso que falei: o mapper é o NH ou qq outro mapper. Não disse que o repositório é o mapper : "(..)Nhibernate e outros O/R M, por mais bem implementados e bonitos que sejam, no frigir dos ovos continuam sendo apenas.... "gambiarras" para resolver a impedância exisitente entre o mundo OO e o mundo relacional. O próprio nome ja diz, são "mappers"".    Ou seja, estou falando do "M" de O/R M.

Quando estou falando de burro estou falando de regras de negócio, ou seja, "domínio". Eu faço justamente como você:  no dominio tenho interfaces e quem implementa essas interfaces (no meu caso L2Sql ou Ado puro) faz o serviço sujo. Jamais colocaria dentro da implementação concreta uma regra de negócio que não estivesse explícita no mínimo na assinatura do método da Interface.


Cássio Rogério Eskelsen
 

2009/4/24 Giovanni Bassi <gig...@giggio.net>

Rodrigo Vieira

unread,
Apr 24, 2009, 8:59:01 AM4/24/09
to dotnetar...@googlegroups.com
A gente comecou a ir por esse caminho, mas aih qdo a gente viu que o
Linq2SQL (ou seja, retornar IQueryable) nao ia ser uma solucao a longo
prazo, desistimos. Ou quase. Temos uma funcao la chamada
repository.Query que retorna IQueryable, mas a gente nao faz muita
propaganda dela hehehe. Mas como a chance desse projeto um dia ter o
ORM mudado eh pequena, ta OK.

No mais eh aquele monte de repository.FindCustomersByIssoEAquilo,
FindCustomersNotZ, e por ai vai...o nome da funcao e a assinatura
representa um conceito do dominio, eh um comeco, mas ainda estamos com
um repositorio esperto demais pro nosso conforto.

Giovanni Bassi

unread,
Apr 24, 2009, 8:59:30 AM4/24/09
to dotnetar...@googlegroups.com
Concordamos então.
Ninguém discorda???

Juliano Oliveira

unread,
Apr 24, 2009, 9:23:37 AM4/24/09
to dotnetar...@googlegroups.com
Eu só discordo do "gambiarra". Não acho que ORM´s são "gambiarras".
Se for assim, tudo é gambiarra. Afinal, na tomada temos corrente elétrica e nossos computadores trabalham com corrente contínua, "se não tivermos um circuito que resolva essa impedancia" não teriamos transmissão de energia elétrica.

(O exemplo foi por quê eu estava ouvindo AC/DC.. rs)


[]´s

Juliano Oliveira
Analista Desenvolvedor
.Net, C#, Actionscript, Flex, Nhibernate
http://programandoem.net


2009/4/24 Giovanni Bassi <gig...@giggio.net>
Concordamos então.

Rodrigo Vieira

unread,
Apr 24, 2009, 9:30:32 AM4/24/09
to dotnetar...@googlegroups.com
Bem, concordo desde que o conceito de "servico sujo" esteja claro para
todas as partes envolvidas :)

Se por servico sujo estamos nos referindo a ter uma assinatura de
metodo que reflete um conceito do dominio, tipo
BuscaClientesInadimplentes() mas o criterio de inadimplencia tah
embutido dentro da query, voltamos aa estaca zero da discussao.


2009/4/24 Giovanni Bassi <gig...@giggio.net>:


> Concordamos então.
> Ninguém discorda???
>
> []'s
>
> Giovanni Bassi
> Microsoft MVP, MCSD, MCPD, CSM
> Arquiteto de software
> http://www.giovannibassi.com
>
>
> 2009/4/24 Cássio Rogério Eskelsen <eske...@gmail.com>

>> Quando estou falando de burro estou falando de regras de negócio, ou seja,

Rodrigo Vieira

unread,
Apr 24, 2009, 9:31:21 AM4/24/09
to dotnetar...@googlegroups.com
Isso parece bem interessante Tiago. Hora de estudar esse design
pattern, e dar uma passeada no Google...

2009/4/24 Tiago Soczek <tiago...@gmail.com>:

Cássio Rogério Eskelsen

unread,
Apr 24, 2009, 9:31:40 AM4/24/09
to dotnetar...@googlegroups.com
Ok, qndo puxei o termo "impedância" realmente cavei minha cova pois aí até um resistor usado para ligar um Alto-falante de 8 ohms em um circuito de 4 ohms poderia ser considerado "gambiarra" hehe

Mas continuo afirmando que é gambi: o mundo relacional e o mundo OO são muito distintos e por melhores que sejam as ferramentas, você nunca vai conseguir casar os dois: ou você usa todo o potencial do banco e perde alguma coisa na OO, ou faz teu sistema bonitinho, dentro de todos os padrões OO e perde o potencial do banco (o que eu particularmente prefiro).

Cássio Rogério Eskelsen
  
2009/4/24 Juliano Oliveira <jul.ol...@gmail.com>

Cássio Rogério Eskelsen

unread,
Apr 24, 2009, 9:34:20 AM4/24/09
to dotnetar...@googlegroups.com
No meu caso, considero "serviço sujo" o "select x,y,z from xpto" e o consequente " objeto.PropriedadeX = dr["x"]."

Mas realmente, é dificil você expressar regras de negócio na assinatura de um método sem incorrer em dois problemas: a assinatura virar um "tratado" e você ter trocentos métodos para uma Interface

Cássio Rogério Eskelsen
 


2009/4/24 Rodrigo Vieira <rodr...@gmail.com>

Juliano Oliveira

unread,
Apr 24, 2009, 9:36:44 AM4/24/09
to dotnetar...@googlegroups.com
Cássio,

Acho que tudo depende muito da "forma de implementação".
A implementação de ActiveRecord do Rails por exemplo é espetacular. Não é a melhor e nem é bala de prata, mas é sem dúvida a que melhor atende essa "transformação de energia".

O que você chama de "gambiarra" eu chamo de "transformação de energia".
:)


[]´s

Juliano Oliveira
Analista Desenvolvedor
.Net, C#, Actionscript, Flex, Nhibernate
http://programandoem.net


2009/4/24 Cássio Rogério Eskelsen <eske...@gmail.com>

Anderson Correia

unread,
May 5, 2009, 11:34:13 AM5/5/09
to .Net Architects
Olá!

Desculpem resgatar essa thread que já está ficando antiga (aqui no
grupo os assuntos rolam muito rápido e isso eu considero muito bom).
Gostaria de aproveitar o tema de repositórios para saber qual a
opinião de vocês sobre a implementação sugerida neste link
(IRepository : IQueryable<T>):

http://www.codeinsanity.com/2008/08/implementing-repository-and.html

Ele a utiliza para implementar em conjunto com o pattern UnitOfWork,
descrito nos links:

http://www.codeinsanity.com/2008/09/unit-of-work-pattern.html
http://www.codeinsanity.com/2008/10/implementing-persistence-ignorant-unit.html

Considero a abordagem de realizar queries LINQ no repositório muito
interessante, além da implementação de Specification utilizada nos
links serem também interessantes.

[]'s

Anderson Correia.

On Apr 24, 10:31 am, Cássio Rogério Eskelsen <eskel...@gmail.com>
wrote:
> Ok, qndo puxei o termo "impedância" realmente cavei minha cova pois aí até
> um resistor usado para ligar um Alto-falante de 8 ohms em um circuito de 4
> ohms poderia ser considerado "gambiarra" hehe
> Mas continuo afirmando que é gambi: o mundo relacional e o mundo OO são
> muito distintos e por melhores que sejam as ferramentas, você nunca vai
> conseguir casar os dois: ou você usa todo o potencial do banco e perde
> alguma coisa na OO, ou faz teu sistema bonitinho, dentro de todos os padrões
> OO e perde o potencial do banco (o que eu particularmente prefiro).
>
> Cássio Rogério Eskelsen
>
> 2009/4/24 Juliano Oliveira <jul.olive...@gmail.com>
>
> > Eu só discordo do "gambiarra". Não acho que ORM´s são "gambiarras".
> > Se for assim, tudo é gambiarra. Afinal, na tomada temos corrente elétrica e
> > nossos computadores trabalham com corrente contínua, "se não tivermos um
> > circuito que resolva essa impedancia" não teriamos transmissão de energia
> > elétrica.
>
> > (O exemplo foi por quê eu estava ouvindo AC/DC.. rs)
>
> > []´s
>
> > Juliano Oliveira
> > Analista Desenvolvedor
> > .Net, C#, Actionscript, Flex, Nhibernate
> >http://programandoem.net
>
> > 2009/4/24 Giovanni Bassi <gig...@giggio.net>
>
> >> Concordamos então.
> >> Ninguém discorda???
>
> >> []'s
>
> >> Giovanni Bassi
> >> Microsoft MVP, MCSD, MCPD, CSM
> >> Arquiteto de software
> >>http://www.giovannibassi.com
>
> >> 2009/4/24 Cássio Rogério Eskelsen <eskel...@gmail.com>
>
> >>> Giovanni,
> >>> Mas foi isso que falei: o mapper é o NH ou qq outro mapper. Não disse que
> >>> o repositório é o mapper : *"(..)Nhibernate e outros O/R M, por mais bem
> >>> implementados e bonitos que sejam, no frigir dos ovos continuam sendo
> >>> apenas.... "gambiarras" para resolver a impedância exisitente entre o mundo
> >>> OO e o mundo relacional. O próprio nome ja diz, são "mappers"".*    Ou
> >>> seja, estou falando do "M" de O/R M.
>
> >>> Quando estou falando de burro estou falando de regras de negócio, ou
> >>> seja, "domínio". Eu faço justamente como você:  no dominio tenho interfaces
> >>> e quem implementa essas interfaces (no meu caso L2Sql ou Ado puro) faz o
> >>> serviço sujo. Jamais colocaria dentro da implementação concreta uma regra de
> >>> negócio que não estivesse explícita no mínimo na assinatura do método da
> >>> Interface.
>
> >>> Cássio Rogério Eskelsen
>
> >>> 2009/4/24 Giovanni Bassi <gig...@giggio.net>
>
> >>>> Cassio,
>
> >>>> Discordo que o repositório tem que ser burro. Só precisamos separar as
> >>>> responsabilidades. Veja o exemplo de especificação que acabei de mandar.
> >>>> Outra coisa: o repositório não é um mapper. O mapper é o NH ou o EF.
> >>>> Considero a solução do Ayende interessante, talvez ainda venha a
> >>>> aplicacá-la...
>
> >>>> []'s
>
> >>>> Giovanni Bassi
> >>>> Microsoft MVP, MCSD, MCPD, CSM
> >>>> Arquiteto de software
> >>>>http://www.giovannibassi.com
>
> >>>> 2009/4/24 Cássio Rogério Eskelsen <eskel...@gmail.com>
>
> >>>> Esquecendo a informática, o que é um repositório? É simplesmente um
> >>>>> lugar onde se guardam coisas, e para isso você vai ter formas de colocar,
> >>>>> tirar e movimentar "cargas". Um repositório não tem inteligência.
> >>>>> Ayende é um cara muito inteligente, ja acompanho ele desde a época em
> >>>>> que que estava encarnado na linguagem Boo   <http://boo.codehaus.org/>(para
> >>>>> quem não conhece, é uma linguagem para .Net cuja sintaxe é muito parecida
> >>>>> com Python), no entanto, as vezes me parece que ele quer apenas criar
> >>>>> polêmica.
>
> >>>>> Nhibernate e outros O/R M, por mais bem implementados e bonitos que
> >>>>> sejam, no frigir dos ovos continuam sendo apenas.... "gambiarras" para
> >>>>> resolver a impedância exisitente entre o mundo OO e o mundo relacional. O
> >>>>> próprio nome ja diz, são "mappers", mapper vem de mapa. Desde quando um
> >>>>> "mapa" tem inteligência? Você deve aplicar inteligência para construir um
> >>>>> mapa, mas o mapa não tem inteligência, tem apenas informação.
>
> >>>>> Regras de negócio ficam no domínio PONTO, seja nas entidades ou em
> >>>>> classes services. Essas entidades vão no repositório e buscam o que
> >>>>> precisam. São elas que especificam como serão feitas as queries para o
> >>>>> banco. A Query Language é apenas uma forma de comunicação.
>
> >>>>> Quem, como o Ayende, defende não encapsular o NH ou qualquer outro O/R
> >>>>> M, demonstra apenas que não conhece o mundo real, onde não existe essa de
> >>>>> File->New->Start New Blog Project. Existe um mundo onde temos sempre um
> >>>>> legado para ser preservado, comunicações entre sistemas sendo feitas via
> >>>>> banco de dados e a necessidade de pular de um O/R M para outro é uma
> >>>>> constante.
>
> >>>>> abraços,
>
> >>>>> Cássio Rogério Eskelsen
>
> >>>>> 2009/4/24 Rodrigo Vieira <rodrig...@gmail.com>
>
> >>>>>> Interessante essa discussão. Um dia desses eu tava batendo um papo com
> >>>>>> um colega, sobre repositórios, e a gente caiu num ponto relacionado, e
> >>>>>> ficamos meio na dúvida qto a resposta. A discussão era: repositórios
> >>>>>> fazem parte da camada de negócio, devem ser magros ou gordos? Porque
> >>>>>> na prática, o que temos visto em aplicações muito dependentes do BD
> >>>>>> são muitas das regras de negócio embutidas no repositório,em forma de
> >>>>>> queries, o que fica meio esquisito, o modelo de domínio fica quase
> >>>>>> vazio, e os repositórios super gordos. Aí se alguém um dia resolver
> >>>>>> substituir o AdoCustomerRepository com um NHibernateCustomerRepository
> >>>>>> vai ter que reescrever muita coisa, todas essas regras de negócio o
> >>>>>> que torna o processo caro e arriscado.
>
> >>>>>> Acho que a peça que tava faltando na nossa discussão então é essa
> >>>>>> questão de ter uma linguagem que nos permita expressar uma regra de
> >>>>>> negócio de forma rica no modelo ou serviço, sabendo que isso vai ser
> >>>>>> mapeado numa query ótima no repositório. Adoraria achar exemplos de
> >>>>>> como isso tem sido feito na prática, acho que é uma boa coisa a se
> >>>>>> estudar. Senão o repositório vira basicamente um DAL rebatizado, ou
> >>>>>> pelo menos essa é a impressão que eu tenho.
>
> >>>>>> 2009/4/24 Gustavo Rocha <gustavohro...@gmail.com>:
>
> >>>>>>http://ayende.com/Blog/archive/2009/04/17/repository-is-the-new-singl...

Rodrigo Vieira

unread,
May 5, 2009, 12:59:50 PM5/5/09
to dotnetar...@googlegroups.com
Ola Anderson,

Sobre retornar IQueryable, eu acho que depende dos planos que você tem
pro código em questão, pois ao fazer isso você está se amarrando a uma
tecnologia específica, fica mais difícil mudar depois. Mas por outro
lado, nem sempre ocorre da gente realmente resolver trocar a
tecnologia de ORM/BD de uma aplicação, então um contra-argumento em
favor do pragmatismo também é válido.

A gente teve essa discussão lá na empresa e por fim decidimos por
retornar só IEnumerable de nossos repositórios, e criar métodos do
tipo FindCustomerByPostalCode() etc. É mais chato, e perdemos a
expressividade do Linq, mas quando resolvermos criar uma implementação
NHCustomerRepository é só garantir que todos testes passam e a gente
sabe que o sistema tá OK, o que não seria o caso se tivéssemos
IQueryable espalhado por todas camadas. Tb fica mais fácil manter o
olho em cima de desempenho, etc. Mas nossa aplicação era relativamente
simples, nosso repositório deve ter só uns 10 desses métodos Find*. Se
fosse mais complexa, a gente ia acabar precisando usar QueryObjects ou
especificações, mas dá pra fazer os dois sem retornar IQueryable.

- Rodrigo



2009/5/5 Anderson Correia <info.c...@gmail.com>:

Giovanni Bassi

unread,
May 5, 2009, 1:16:55 PM5/5/09
to dotnetar...@googlegroups.com
O Greg Young falou recentemente no seu blog sobre o post do Ayende, e defendeu que interfaces genéricas de repositório devem ser evitadas, pelo menos quando elas se dirigem ao domínio. Ele prefere métodos mais claros, como "ObterClientesPreferenciais", em vez de "ObterPorEspecificacao" e passar uma spec de cliente preferencial. Ele sente que isso deixa a intenção da interface mais clara. Eu concordo, mas dá trabalho. Internalmente, ele sugere o uso de um repositório genérico om especificações. Sugiro dar uma olhada nos posts recentes dele.


[]'s

Giovanni Bassi
Microsoft MVP, MCSD, MCPD, CSM
Arquiteto de software
http://www.giovannibassi.com


2009/5/5 Rodrigo Vieira <rodr...@gmail.com>

Anderson Correia

unread,
May 5, 2009, 1:35:15 PM5/5/09
to .Net Architects
Rodrigo,

IQueryable<T> te prende a tecnologia LINQ, que é feature do C# e
VB.Net e não é associada diretamente a um ORM. Tanto que nos exemplos
que passei, são utilizados vários ORM's como o NH, EF e L2S. O risco
neste caso é ocorrem mudanças na forma de se integrar nossas coleções
com o LINQ e não de migração do mecanismo de persistência. Uma
amarração de risco que pode ser citada é a do LINQ Provider utilizado
para fazer com que as queries LINQ se tornem SQL, HQL ou EQL por
exemplo. Porém, ambas tem impacto apenas na implementação dos
repositórios.
Lembre-se, essa interface é do System.Linq e não tem nada a ver com o
"Linq to Sql", que na minha opinião foi um péssimo nome, pois vive
causando a associação de query LINQ com acesso a BD.

Giovanni,

Prefiro a abordagem de Repository + Specification. Tendo um spec com o
nome bem definido, sinto que conseguimos alcançar o mesmo objetivo,
sem maiores esforços.
Se for o caso da arquitetura da aplicação, utilizar um service
ObterClientesPreferenciais() e internamente usar o ClienteRepository +
ClientePreferencialSpec pode valer a pena, levando em consideração o
nível de encapsulamento que se deseja.

[]'s

Anderson Correia.

On May 5, 2:16 pm, Giovanni Bassi <gig...@giggio.net> wrote:
> O Greg Young falou recentemente no seu blog sobre o post do Ayende, e
> defendeu que interfaces genéricas de repositório devem ser evitadas, pelo
> menos quando elas se dirigem ao domínio. Ele prefere métodos mais claros,
> como "ObterClientesPreferenciais", em vez de "ObterPorEspecificacao" e
> passar uma spec de cliente preferencial. Ele sente que isso deixa a intenção
> da interface mais clara. Eu concordo, mas dá trabalho. Internalmente, ele
> sugere o uso de um repositório genérico om especificações. Sugiro dar uma
> olhada nos posts recentes dele.
>
> []'s
>
> Giovanni Bassi
> Microsoft MVP, MCSD, MCPD, CSM
> Arquiteto de softwarehttp://www.giovannibassi.com
>
> 2009/5/5 Rodrigo Vieira <rodrig...@gmail.com>
>
>
>
> > Ola Anderson,
>
> > Sobre retornar IQueryable, eu acho que depende dos planos que você tem
> > pro código em questão, pois ao fazer isso você está se amarrando a uma
> > tecnologia específica, fica mais difícil mudar depois. Mas por outro
> > lado, nem sempre ocorre da gente realmente resolver trocar a
> > tecnologia de ORM/BD de uma aplicação, então um contra-argumento em
> > favor do pragmatismo também é válido.
>
> > A gente teve essa discussão lá na empresa e por fim decidimos por
> > retornar só IEnumerable de nossos repositórios, e criar métodos do
> > tipo FindCustomerByPostalCode() etc. É mais chato, e perdemos a
> > expressividade do Linq, mas quando resolvermos criar uma implementação
> > NHCustomerRepository é só garantir que todos testes passam e a gente
> > sabe que o sistema tá OK, o que não seria o caso se tivéssemos
> > IQueryable espalhado por todas camadas. Tb fica mais fácil manter o
> > olho em cima de desempenho, etc. Mas nossa aplicação era relativamente
> > simples, nosso repositório deve ter só uns 10 desses métodos Find*. Se
> > fosse mais complexa, a gente ia acabar precisando usar QueryObjects ou
> > especificações, mas dá pra fazer os dois sem retornar IQueryable.
>
> > - Rodrigo
>
> > 2009/5/5 Anderson Correia <info.corr...@gmail.com>:
>
> > > Olá!
>
> > > Desculpem resgatar essa thread que já está ficando antiga (aqui no
> > > grupo os assuntos rolam muito rápido e isso eu considero muito bom).
> > > Gostaria de aproveitar o tema de repositórios para saber qual a
> > > opinião de vocês sobre a implementação sugerida neste link
> > > (IRepository : IQueryable<T>):
>
> > >http://www.codeinsanity.com/2008/08/implementing-repository-and.html
>
> > > Ele a utiliza para implementar em conjunto com o pattern UnitOfWork,
> > > descrito nos links:
>
> > >http://www.codeinsanity.com/2008/09/unit-of-work-pattern.html
>
> >http://www.codeinsanity.com/2008/10/implementing-persistence-ignorant...
> ...
>
> read more »

Rodrigo Vieira

unread,
May 5, 2009, 1:58:17 PM5/5/09
to dotnetar...@googlegroups.com
Anderson,

Nem toda query linq é suportada por todos ORMs, e, se são, nem sempre
com o mesmo plano de execução e desempenho. Então se vc escrever uma
mega-query com Linq usando joins, group by etc, e isso funcionar com
Linq2SQL, vai sempre exister um ponto de interrogação sobre como isso
vai funcionar com outro ORM, se a query SQL gerada não vai deixar sua
aplicação de joelhos, etc.

Então na prática existe uma amarração ao ORM sim. Com sabedoria dá pra
evitar tais problemas, claro, mas num time heterogêneo eu ainda acho
que é poder demais sendo dado a camadas não relacionadas ao
repositório, um modelo vazado demais a meu ver.

- Rodrigo

2009/5/5 Anderson Correia <info.c...@gmail.com>:

Anderson Correia

unread,
May 5, 2009, 3:14:15 PM5/5/09
to .Net Architects
Rodrigo,

Concordo parcialmente com você, pois foi o que eu disse: "Uma
amarração de risco que pode ser citada é a do LINQ Provider..."
É onde o "bicho pega". E discordamos, na questão de o problema não ser
do ORM em si, até mesmo porque, você pode montar um LINQ Provider
utilizando ADO.Net apenas.
O ponto sobre performance é incógnita ocasionada pelo simples fato de
utilizar ORM, independente de você implementar esse mecanismo com o
Repository Pattern, utilizar IQueryable, "Find*", enfim outro conceito
em conjunto.
Agora, não ficou claro para mim o seu ponto sobre o que é "camada
vazada". Não seria o mesmo problema se o repositório utilizasse
"Fluent Interfaces" ou diretamente "Specification", ou seja, o ponto
não é o IQueryable<T> em si? Você vê que deve "proteger" os
desenvolvedores, controlando o que pode ser extraído do repositório
através de métodos "Find*" sempre?
Outro problema que você falou anteriormente é espalhar o IQueryable<T>
por todas as camadas. Não vejo a implementação de repositório
utilizando IQueryable<T> provocando isso, porque em DDD quem vai
extrair as informações será um Service ou alguém da App Layer, que já
dependeria do "Find*", ou no simples "Layered Services" com
repositório, ele deve estar encapsulado na camada de negócios, em um
Facade ou Business Component. Você concorda com esses termos e os
problemas levantados levaram em consideração essas diretrizes?
Para mim, seria vazado se eu tivesse um Data Component que retorna
IQueryable<T> que tem um Business Component que retorna outro
IQueryable<T> e passa por um Facade que também retorna IQueryable<T>
até chegar na UI.

[]'s

Anderson Correia.

On May 5, 2:58 pm, Rodrigo Vieira <rodrig...@gmail.com> wrote:
> Anderson,
>
> Nem toda query linq é suportada por todos ORMs, e, se são, nem sempre
> com o mesmo plano de execução e desempenho. Então se vc escrever uma
> mega-query com Linq usando joins, group by etc, e isso funcionar com
> Linq2SQL, vai sempre exister um ponto de interrogação sobre como isso
> vai funcionar com outro ORM, se a query SQL gerada não vai deixar sua
> aplicação de joelhos, etc.
>
> Então na prática existe uma amarração ao ORM sim. Com sabedoria dá pra
> evitar tais problemas, claro, mas num time heterogêneo eu ainda acho
> que é poder demais sendo dado a camadas não relacionadas ao
> repositório, um modelo vazado demais a meu ver.
>
> - Rodrigo
>
> 2009/5/5 Anderson Correia <info.corr...@gmail.com>:

Rodrigo Vieira

unread,
May 5, 2009, 4:17:55 PM5/5/09
to dotnetar...@googlegroups.com
Anderson,

> Concordo parcialmente com você, pois foi o que eu disse: "Uma
> amarração de risco que pode ser citada é a do LINQ Provider..."
> É onde o "bicho pega". E discordamos, na questão de o problema não ser
> do ORM em si, até mesmo porque, você pode montar um LINQ Provider
> utilizando ADO.Net apenas.
> O ponto sobre performance é incógnita ocasionada pelo simples fato de
> utilizar ORM, independente de você implementar esse mecanismo com o
> Repository Pattern, utilizar IQueryable, "Find*", enfim outro conceito
> em conjunto.

Sim, e eu acho que é uma boa idéia deixar essas incógnitas num mesmo
lugar, pois é mais fácil para mim monitorar e principalmente testar o
desempenho do meu ORM se eu sei que todas as queries usadas no meu
sistema estão ali, e não espalhadas por N classes.

> Agora, não ficou claro para mim o seu ponto sobre o que é "camada
> vazada". Não seria o mesmo problema se o repositório utilizasse
> "Fluent Interfaces" ou diretamente "Specification", ou seja, o ponto
> não é o IQueryable<T> em si? Você vê que deve "proteger" os
> desenvolvedores, controlando o que pode ser extraído do repositório
> através de métodos "Find*" sempre?

Minha preocupação com o IQueryable em particular é em ficar com um
repositório anêmico, com 3 ou 4 métodos (CRUD + IQueryable), de forma
que o modelo de domínio não fica bem representado. Se eu vejo uma
função chamada repository.FindCustomerByStatus eu sei exatamente o que
ela deve fazer, se eu vejo algo do tipo
repository.GelAll().Where(..).OrderBy(...) a coisa já fica mais
nebulosa. E a idéia do DDD, pelo que entendi, é deixar o conhecimento
sobre o modelo mais explícito. Outro problema a meu ver é que ao
export IQueryable, corremos o risco de ter a mesma query repetida
várias vezes no sistema, em lugares diferentes, mas cada uma com a
sintaxe um pouquinho diferente, e com seus pequenos bugs e
particularidades, e, o mais perigoso, com uma regra de negócio
interpretada levemente diferente. De novo, prefiro deixar tudo num
balde só, onde é mais fácil inspecionar, testar, etc.

Mas (e isso cobre a questão da "proteção"), leve em conta que estou
falando de um sistema bem grande, num time com 30 desenvolvedores dos
mais diferentes níveis, distribuídos geograficamente. Nesse caso acho
importante sim manter tudo dentro do repositório pois se um
desenvolvedor quiser uma nova query, vai ter que ir no repositório, e
lá aumenta a chance de ele notar que a consulta que ele quer já
existe. Em se tratando de grandes times, com desenvolvedores junior no
meio, acho importante adotar uma "arquitetura defensiva".


> Outro problema que você falou anteriormente é espalhar o IQueryable<T>
> por todas as camadas. Não vejo a implementação de repositório
> utilizando IQueryable<T> provocando isso, porque em DDD quem vai
> extrair as informações será um Service ou alguém da App Layer, que já
> dependeria do "Find*", ou no simples "Layered Services" com
> repositório, ele deve estar encapsulado na camada de negócios, em um
> Facade ou Business Component. Você concorda com esses termos e os
> problemas levantados levaram em consideração essas diretrizes?
> Para mim, seria vazado se eu tivesse um Data Component que retorna
> IQueryable<T> que tem um Business Component que retorna outro
> IQueryable<T> e passa por um Facade que também retorna IQueryable<T>
> até chegar na UI.
>
> []'s
>
> Anderson Correia.
>

Realmente nesse exemplo que vc deu, seria ainda mais vazado :) Mas
mesmo que IQueryable só seja usado na camada imediatamente superior ao
repositório, ainda acho que caio nos riscos que descrevi acima. Mas
veja bem, não sou "religioso" quanto a isso, como disse na primeira
mensagem, as duas abordagens a meu ver fazem sentido dependendo do
contexto, do sistema em questão, do time, etc. Em outro contexto eu
poderia muito bem estar defendendo o oposto...

- Rodrigo

Giovanni Bassi

unread,
May 5, 2009, 4:34:55 PM5/5/09
to dotnetar...@googlegroups.com
Eu defendo que há uso para os 2. Concordo que há cenários para o que o Greg Young propõe, e também para Repositorios+Specs.

O maior perigo de IQueryable vazar para fora do repositório é que a próprio consulta passa a ser acessível fora do repositório, o que é ruim. O Repositório deve ser um ponto de acesso à entidades, e não um ponto de acesso à consultas simplesmente.


[]'s

Giovanni Bassi
Microsoft MVP, MCSD, MCPD, CSM
Arquiteto de software
http://www.giovannibassi.com


2009/5/5 Anderson Correia <info.c...@gmail.com>

Giovanni Bassi

unread,
May 5, 2009, 4:37:57 PM5/5/09
to dotnetar...@googlegroups.com
Eu acho que não é "proteger" os desenvolvedores. É proteger o projeto. Ainda mais no cenário brasileiro, em boa parte altamente amador.
E IQueryable vaza conceitos de consulta mesmo. É fato.


[]'s

Giovanni Bassi
Microsoft MVP, MCSD, MCPD, CSM
Arquiteto de software
http://www.giovannibassi.com


2009/5/5 Rodrigo Vieira <rodr...@gmail.com>

Anderson Correia

unread,
May 5, 2009, 4:50:09 PM5/5/09
to .Net Architects
Rodrigo,

Você tem razão nisso, é uma das preocupações que tenho também. Mas é
aí que vejo ser interessante o uso de Specifications, na forma que foi
apresentado pelos links que enviei, principalmente o poder de combinar
várias specs já construídas. Desde que as specs tenham nomes bem
definidos, vejo que conseguimos alcançar o mesmo objetivo do
"FindCustomerByStatus", podendo ficar algo como repo.Query
(Specs.CustomerByStatus1 | Specs.CustomerByStatus2) ou repo.Query(new
Specification(c => c.Status == "Status1" || c.Status == "Status2")).
Em termos de processo, vejo o refactoring sendo um dos meios de
conseguir que as queries LINQ repetidas se tornem Specifications.

[]'s

Anderson Correia.

Anderson Correia

unread,
May 5, 2009, 5:17:31 PM5/5/09
to .Net Architects
Giovanni,

Entendo a postura da arquitetura defensiva, mas será que não é mais
vantajoso, se tiver espaço, capacitar os amadores para profissionais?
Trazer iniciantes para o nível intermediário (aqueles que tem
interesse)?
Sobre a questão de vazar conceito de consulta, o "Find*" acaba não
sendo algo semelhante? Como fica por exemplo, uma requisição da UI que
exige paginação? Não é melhor ter algo como var results = repo.Query
(ClientesPreferenciais).Skip(x).Take(y) do que var results =
repo.FindClientesPreferenciais(x, y) sendo isso uma sobrecarga do
repo.FindClientesPreferenciais()?
Onde quero chegar é que consultar faz parte do negócio da aplicação, e
que fazemos isso de diversas formas e por isso o repositório acaba
ficando com uma gama de métodos, e vejo tendo retorno utilizar
IQueryable<T> e as funcionalidades do LINQ sobre uma coleção de
entidades de negócio, propósito de usar um repositório, independente
de abordagem arquitetural.
Gostaria de entender melhor o que você quis dizer com "acesso à
entidades" x "acesso a consultas".
Acho que acabou fugindo um pouco da pergunta inicial, até mesmo
porque, se o seu repositório retornar uma lista, posso realizar uma
query LINQ nele, e era sobre isso que gostaria de discutir mais.
O que é realmente mais vantajoso:

var results = from c in repoClientes.PegarClientes()
where c.Status == "Preferencial"
select c;

ou

var results = from c in repoClientes
where c.Status == "Preferencial"
select c;

Em cima desses acessos, temos que levar em conta o que os
Specifications podem nos proporcionar.

[]'s

Anderson Correia.

On May 5, 5:37 pm, Giovanni Bassi <gig...@giggio.net> wrote:
> Eu acho que não é "proteger" os desenvolvedores. É proteger o projeto. Ainda
> mais no cenário brasileiro, em boa parte altamente amador.
> E IQueryable vaza conceitos de consulta mesmo. É fato.
>
> []'s
>
> Giovanni Bassi
> Microsoft MVP, MCSD, MCPD, CSM
> Arquiteto de softwarehttp://www.giovannibassi.com
>
> 2009/5/5 Rodrigo Vieira <rodrig...@gmail.com>
>
>
>

Giovanni Bassi

unread,
May 5, 2009, 11:09:41 PM5/5/09
to dotnetar...@googlegroups.com
Capacitação leva tempo. Ainda assim, nada impede... desde que você tenha esse tempo. Lembrando que é possível que sempre tenha um jr na equipe a todo momento, que acabou de chegar.

De qualquer forma, entendo que a expressividade da chamada:
var clientes = repositorioClientes.ObterPorNome(nome);
É muito maior que:
var clientes = repositorioClientes.ObterPorEspecificacao(especificao);
Mas não desconsidero o uso da segunda. Acho que depende do cenário.

Paginação não é um conceito de domínio, e portanto não faz parte da linguagem ubíqua, e portanto não deve ser endereçada pelo DDD. A regra para paginação, se você não quiser matar a performance é: paginação deve acontecer o mais perto possível dos dados. É por isso que paginação como a que é feita em webforms, onde todos os dados devem já estar na camada web, não escala. Ou não escala porque você vai ter que manter os dados em memória, ou porque vai ter que consultar o BD a cada paginação. Para resolver isso, você pagina na camada de dados. Para isso, você teria que pular os repositórios (já que eles não entendem o conceito de paginação), e talvez acessar uma camada de acesso a dados diretamente, e trabalhar com dados tabulares. Aí já começamos a falar de Command and Query separation (CQS), que é algo grande demais para explicar em uma resposta... além de fugir do assunto.


[]'s

Giovanni Bassi
Microsoft MVP, MCSD, MCPD, CSM
Arquiteto de software
http://www.giovannibassi.com


2009/5/5 Anderson Correia <info.c...@gmail.com>

Anderson Correia

unread,
May 6, 2009, 11:00:01 AM5/6/09
to .Net Architects
Giovanni,

Obrigado pela resposta. Batendo ainda um pouco na tecla de paginação e
procurando fugir de CQS.
Em termos de DDD, um repositório como o sugerido neste link:
http://devlicio.us/blogs/rob_eisenberg/archive/2008/04/03/my-nhibernate-2-0-supa-layer.aspx
você considera equivocado? Mesmo se você considera em DDD errado, ele
poderia ser usado em uma abordagem não-DDD?
Você considera sendo um problema em termos de DDD, o repositório ou
serviço que usa um repositório, retornar um IEnumerable para a UI
utilizar isso para gerenciar a paginação?
O modelo de binding do WindowsForms não ocasionaria o mesmo problema
que você mencionou no ASP.Net, considerando que a camada física de
dados não é a mesma da apresentação?

[]'s

Anderson Correia.
> 2009/5/5 Anderson Correia <info.corr...@gmail.com>

Giovanni Bassi

unread,
May 6, 2009, 2:46:28 PM5/6/09
to dotnetar...@googlegroups.com
Oi Anderson,

Foge do conceito de DDD. Mas você poderia dizer que está correto diante do padrão repositório, porque ele continua trabalhando como uma coleção de entidades.
Ainda assim, independente da discussão sobre a correção do padrão, o maior problema é a quebra de responsabilidades. O princípio da responsabilidade única não é mais válido, porque agora o repositório pode mudar por necessidades da coleção de entidades, ou por mudanças na interface gráfica. A coesão morreu.
Quanto à retornar IEnumerable, não vejo problema.
Em Windows Forms o problema de escalabilidade é menor porque não há o risco de a memória do servidor explodir, já que cada usuário mantém sua própria cópia dos dados. Mas o transporte e consulta dos dados podem sobrecarregar o servidor, também impedindo a escala. A regra é nunca permitir um "SELECT *", sempre tem que ter um where. Não retornar nunca um milhão de registros. Ninguém precisa de 1 milhão de registros. Exigindo algum filtro, já resolveria isso. Não seria talvez um problema entregar 100 linhas por usuário.


[]'s

Giovanni Bassi
Microsoft MVP, MCSD, MCPD, CSM
Arquiteto de software
http://www.giovannibassi.com


2009/5/6 Anderson Correia <info.c...@gmail.com>

Anderson Correia

unread,
May 6, 2009, 5:13:15 PM5/6/09
to .Net Architects
Oi Giovanni,

Obrigado novamente pelas respostas. Concordo em tudo o que você disse,
principalmente na questão de filtro. Somente acrescentaria que se não
tem "where", deve ter um "group by" + função de agregação, pois
existem cenários de consolidação de informações que devem ser levados
em conta.
Porém, a questão do "group by" entra no mundo do "depende", pois não
acredito que o processamento de cálculos sempre deva ficar no BD.
Com IEnumerable, a UI pode se utilizar de Linq para realizar a
paginação, mas isso não afeta a implementação do repositório e é
utilizado o Linq to Objects, por isso perguntei o que você achava de
retornar essa interface. Com IQueryable (como sabemos, herda de
IEnumerable), a paginação é feita com o Linq Provider da tecnologia
que implementa a interface, como por exemplo o NHibernate.Linq, e não
vejo também afetar a implementação do repositório em si, ou estou
errado?
Considero um erro implementar um mecanismo do tipo ISorteable,
IPageable, entre outras que já vi, para habilitar essas
responsabilidades de UI diretamente no repositório, exatamente pela
coesão e também por isso que estou avaliando se é válido o repositório
implementar IQueryable e a responsabilidade ficar com o Linq Provider.
Sem IQueryable, vejo algumas alternativas como ele herdar de
Collection<T> ou até mesmo de KeyedCollection<T>, para utilizar algo
como var cliente = repoClientes["A01"] onde "A01" é o id do mesmo.
Você vê algum problema com essa abordagem, considerando que as queries
Linq vão ser realizadas via Linq to Objects?

Sobre CQS, acredito ser um tema "quente" e que pode ser discutido em
um outro post. Mesmo assim, gostaria de deixar registrado aqui dois
links que falam sobre essa questão:

- Implementando um mecanismo IPage:
http://thinkbeforecoding.com/post/2009/01/19/Repositories-and-IQueryable-the-paging-case
- Aqui ele reconsidera para utilizar CQS:
http://thinkbeforecoding.com/post/2009/04/08/Back-on-Repositories-and-Paging-Introducing-reporting

E também, deixar registrado um link com "resumão" da discussão entre
Ayende e Greg sobre repositórios:

http://jonathan-oliver.blogspot.com/2009/04/all-your-repository-are-belong-to-us.html

[]'s

Anderson Correia.

On May 6, 3:46 pm, Giovanni Bassi <gig...@giggio.net> wrote:
> Oi Anderson,
>
> Foge do conceito de DDD. Mas você poderia dizer que está correto diante do
> padrão repositório, porque ele continua trabalhando como uma coleção de
> entidades.
> Ainda assim, independente da discussão sobre a correção do padrão, o maior
> problema é a quebra de responsabilidades. O princípio da responsabilidade
> única não é mais válido, porque agora o repositório pode mudar por
> necessidades da coleção de entidades, ou por mudanças na interface gráfica.
> A coesão morreu.
> Quanto à retornar IEnumerable, não vejo problema.
> Em Windows Forms o problema de escalabilidade é menor porque não há o risco
> de a memória do servidor explodir, já que cada usuário mantém sua própria
> cópia dos dados. Mas o transporte e consulta dos dados podem sobrecarregar o
> servidor, também impedindo a escala. A regra é nunca permitir um "SELECT *",
> sempre tem que ter um where. Não retornar nunca um milhão de registros.
> Ninguém precisa de 1 milhão de registros. Exigindo algum filtro, já
> resolveria isso. Não seria talvez um problema entregar 100 linhas por
> usuário.
>
> []'s
>
> Giovanni Bassi
> Microsoft MVP, MCSD, MCPD, CSM
> Arquiteto de softwarehttp://www.giovannibassi.com
>
> 2009/5/6 Anderson Correia <info.corr...@gmail.com>
>
>
>
> > Giovanni,
>
> > Obrigado pela resposta. Batendo ainda um pouco na tecla de paginação e
> > procurando fugir de CQS.
> > Em termos de DDD, um repositório como o sugerido neste link:
>
> >http://devlicio.us/blogs/rob_eisenberg/archive/2008/04/03/my-nhiberna...
> ...
>
> read more »

Giovanni Bassi

unread,
May 7, 2009, 12:14:53 AM5/7/09
to dotnetar...@googlegroups.com
É uma questão de cenário. A princípio me parece ruim trabalhar com IQueryable em cenários derivados deste, mas não descarto.
Separar as operações de leitura das de escrita, a exemplo do proposto com CQS, me parece fazer mais sentido.


[]'s

Giovanni Bassi
Microsoft MVP, MCSD, MCPD, CSM
Arquiteto de software
http://www.giovannibassi.com


2009/5/6 Anderson Correia <info.c...@gmail.com>

Reply all
Reply to author
Forward
0 new messages