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
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.
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.
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,
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>:
> 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