Primeiro, quero dizer que essa parece ser uma pergunta / área negligenciada; portanto, se essa pergunta precisar ser aprimorada, ajude-me a fazer desta uma ótima pergunta que possa beneficiar outras pessoas! Estou procurando conselhos e ajuda de pessoas que implementaram soluções que resolvem esse problema, não apenas idéias para tentar.
Na minha experiência, existem dois lados de um aplicativo - o lado "tarefa", que é amplamente orientado por domínio e é onde os usuários interagem amplamente com o modelo de domínio (o "mecanismo" do aplicativo) e o lado de relatório, onde os usuários obtenha dados com base no que acontece no lado da tarefa.
No lado da tarefa, fica claro que um aplicativo com um modelo de domínio avançado deve ter lógica de negócios no modelo de domínio e o banco de dados deve ser usado principalmente para persistência. Separação de preocupações, todo livro é escrito sobre isso, sabemos o que fazer, incrível.
E o lado dos relatórios? Os data warehouses são aceitáveis ou são de design ruim porque incorporam a lógica de negócios no banco de dados e nos próprios dados? Para agregar os dados do banco de dados nos dados do data warehouse, você deve ter aplicado a lógica e as regras de negócios aos dados, e essa lógica e as regras não vieram do seu modelo de domínio, vieram dos seus processos de agregação de dados. Isso está errado?
Trabalho em grandes aplicações financeiras e de gerenciamento de projetos, onde a lógica de negócios é extensa. Ao relatar esses dados, muitas vezes terei MUITAS agregações para extrair as informações necessárias para o relatório / painel, e as agregações possuem muita lógica de negócios. Por uma questão de desempenho, tenho feito isso com tabelas e procedimentos armazenados altamente agregados.
Como exemplo, digamos que um relatório / painel seja necessário para mostrar uma lista de projetos ativos (imagine 10.000 projetos). Cada projeto precisará de um conjunto de métricas mostradas, por exemplo:
- orçamento total
- esforço até hoje
- taxa de queimadura
- data de esgotamento do orçamento na taxa de queima atual
- etc.
Cada um deles envolve muita lógica de negócios. E não estou falando apenas de multiplicar números ou de alguma lógica simples. Estou falando de, para obter o orçamento, você deve aplicar uma tabela de preços com 500 taxas diferentes, uma para o tempo de cada funcionário (em alguns projetos, outros têm um multiplicador), aplicar despesas e qualquer marcação apropriada etc. lógica é extensa. Foram necessários muitos ajustes de agregação e consulta para obter esses dados em um período de tempo razoável para o cliente.
Isso deve ser executado primeiro no domínio? E o desempenho? Mesmo com consultas SQL diretas, mal estou obtendo esses dados com rapidez suficiente para que o cliente seja exibido em um período de tempo razoável. Não consigo imaginar tentar obter esses dados para o cliente com rapidez suficiente se estiver reidratando todos esses objetos de domínio, misturando, combinando e agregando seus dados na camada do aplicativo ou tentando agregar os dados no aplicativo.
Nesses casos, parece que o SQL é bom em processar dados e por que não usá-los? Mas então você tem lógica de negócios fora do seu modelo de domínio. Qualquer alteração na lógica de negócios precisará ser alterada no modelo de domínio e nos esquemas de agregação de relatórios.
Estou realmente sem saber como projetar a parte de relatórios / painel de qualquer aplicativo com relação ao design orientado a domínio e boas práticas.
Eu adicionei a tag MVC porque MVC é o sabor do dia e estou usando-a no meu design atual, mas não consigo descobrir como os dados do relatório se encaixam nesse tipo de aplicativo.
Estou procurando qualquer ajuda nesta área - livros, padrões de design, palavras-chave para o google, artigos, qualquer coisa. Não consigo encontrar nenhuma informação sobre este tópico.
EDITAR E OUTRO EXEMPLO
Outro exemplo perfeito que encontrei hoje. O cliente deseja um relatório para a equipe de vendas do cliente. Eles querem o que parece ser uma métrica simples:
Para cada vendedor, quais são as vendas anuais até o momento?
Mas isso é complicado. Cada vendedor participou de várias oportunidades de vendas. Alguns ganharam, outros não. Em cada oportunidade de vendas, há vários vendedores aos quais é atribuída uma porcentagem de crédito para a venda, de acordo com sua função e participação. Então, agora, imagine passar pelo domínio para isso ... a quantidade de reidratação do objeto que você precisaria fazer para extrair esses dados do banco de dados para cada vendedor:
Obtenha todo o
SalesPeople
->
Para cada um obtenha o seuSalesOpportunities
->
Para cada um obtenha a sua porcentagem da venda e calcule o valor das Vendas
e adicione o valor total dasSalesOpportunity
Vendas.
E essa é uma métrica. Ou você pode escrever uma consulta SQL que pode fazer isso de maneira rápida e eficiente e ajustá-la para ser rápida.
EDIT 2 - Padrão CQRS
Eu li sobre o Padrão CQRS e, embora intrigante, até Martin Fowler diz que não foi testado. Então, como esse problema foi resolvido no passado. Isso deve ter sido enfrentado por todos em algum momento ou outro. O que é uma abordagem estabelecida ou desgastada, com um histórico de sucesso?
Editar 3 - Sistemas / Ferramentas de Relatório
Outra coisa a considerar neste contexto são as ferramentas de relatório. O Reporting Services / Crystal Reports, o Analysis Services e o Cognoscenti, etc. esperam dados do SQL / banco de dados. Eu duvido que seus dados cheguem aos seus negócios mais tarde. E, no entanto, eles e outras pessoas como eles são parte vital dos relatórios em muitos sistemas grandes. Como os dados para esses dados são manipulados adequadamente, onde existe uma lógica comercial na fonte de dados para esses sistemas e possivelmente nos próprios relatórios?
Respostas:
Essa é uma resposta muito simples, mas vamos direto ao cerne da questão:
Em termos de DDD, talvez pense em relatar como um Contexto Limitado? Portanto, sim, tudo bem se o domínio de relatório contiver lógica de negócios, assim como o domínio transacional terá lógica de negócios transacional.
Quanto à questão de, digamos, procedimentos armazenados SQL versus modelo de domínio no código do aplicativo, os mesmos prós e contras se aplicam ao sistema de relatórios e ao sistema transacional.
Como vejo que você adicionou uma recompensa à pergunta, li a pergunta novamente e notei que você estava solicitando recursos específicos sobre isso, então pensei em começar sugerindo que você analise outras perguntas sobre o estouro de pilha, e encontrei este https://stackoverflow.com/questions/11554231/how-does-domain-driven-design-handle-reporting
A essência geral disso é usar o CQRS como um padrão para o seu sistema, que é consistente com o DDD, e confiar nas responsabilidades do lado da consulta como uma maneira de realizar a geração de relatórios, mas não tenho certeza de que seja uma resposta útil em seu caso.
Também encontrei este http://www.martinfowler.com/bliki/ReportingDatabase.html , que encontrei vinculado aqui: http://groups.yahoo.com/neo/groups/domaindrivendesign/conversations/topics/2261
Aqui está um artigo interessante da ACM sobre o assunto: http://dl.acm.org/citation.cfm?id=2064685, mas está por trás de um paywall, então não consigo lê-lo (não é um membro da ACM :().
Também há esta resposta aqui em uma pergunta semelhante: https://stackoverflow.com/questions/3380431/cqrs-ddd-synching-reporting-database
e este: http://snape.me/2013/05/03/applying-domain-driven-design-to-data-warehouses/
Espero que isto ajude!
fonte
Meu entendimento da sua pergunta é o seguinte: O aplicativo para tarefas diárias foi
Exibir >> Controlador >> Modelo (BL) >> Banco de Dados (Dados)
Pedido para fins de relatório
Exibir >> Controlador >> Modelo >> Banco de Dados (Dados + BL)
Portanto, a alteração no BL para ' aplicativo de tarefa ' também levará à alteração no ' relatório ' de BL. Esse é o seu verdadeiro problema, certo? Bem, tudo bem fazer alterações duas vezes, essa dor que você precisa tomar de qualquer maneira. O motivo é que os BLs são separados por suas respectivas preocupações. Um é para buscar dados e outro para agregar dados. Além disso, seu BL original e o BL agregado serão gravados em diferentes tecnologias ou idiomas ( C # / java e SQL proc ). Não há como escapar.
Vamos dar outro exemplo não relacionado a relatórios especificamente. Suponha que uma empresa XXX rastreie e-mails de todos os usuários para interpretação e venda essas informações para empresas de marketing. Agora ele terá um BL para interpretação e um BL para agregar dados para empresas de marketing. As preocupações são diferentes para ambos os BLs. Amanhã, se o BL mudar de tal forma que os e-mails provenientes de Cuba devam ser ignorados, a lógica comercial será alterada nos dois lados.
fonte
Os relatórios são um contexto limitado ou um subdomínio, para falar livremente. Ele resolve uma necessidade comercial de coletar / agregar dados e processá-los para obter inteligência de negócios.
Como você implementa esse subdomínio provavelmente será um equilíbrio entre a maneira (mais) arquiteturalmente correta de fazer isso e o que sua infraestrutura permitirá. Eu gosto de começar pelo lado anterior e avançar para o segundo apenas quando necessário.
Provavelmente, você pode dividir isso em dois problemas principais que está solucionando:
Agregando ou armazenando dados. Isso deve processar alguma fonte de dados e combinar as informações de forma que sejam armazenadas em outra fonte de dados.
Consultando a fonte de dados agregada para fornecer inteligência de negócios.
Nenhum desses problemas faz referência a qualquer banco de dados ou mecanismo de armazenamento específico. Sua camada de domínio deve apenas lidar com interfaces, implementadas na camada de infraestrutura por vários adaptadores de armazenamento.
Você pode ter vários trabalhadores ou algum trabalho agendado, dividido em algumas partes móveis:
Espero que você possa ver alguns dos CQRS brilharem por lá.
No lado dos relatórios, ele só precisa fazer consultas, mas nunca diretamente no banco de dados. Acesse suas interfaces e sua camada de domínio aqui. Esse não é o mesmo domínio do problema que suas tarefas principais, mas ainda deve haver alguma lógica aqui que você deseja aderir.
Assim que você mergulha diretamente no banco de dados, você depende mais dele e, eventualmente, pode interferir nas necessidades de dados do aplicativo original.
Além disso, pelo menos para mim, eu definitivamente prefiro escrever testes e desenvolver código em vez de consultas ou procedimentos armazenados. Também gosto de não me prender em ferramentas específicas até que seja absolutamente necessário.
fonte
É comum separar armazenamentos de dados operacionais / transacionais dos relatórios. O último pode ter requisitos para manter os dados por motivos legais (por exemplo, sete anos de dados financeiros para auditoria financeira) e você não deseja tudo isso em seu armazenamento de dados transacionais.
Assim, você particionará seus dados transacionais por algum tempo (semanal, mensal, trimestral, anual) e moverá as partições antigas para o repositório de dados de relatórios / histórico via ETL. Pode ou não ser um data warehouse com um esquema e dimensões em estrela. Você usaria ferramentas de relatório de data warehousing para fazer consultas ad hoc, roll-ups e tarefas em lote para gerar relatórios periódicos.
Eu não recomendaria relatar seu armazenamento de dados transacionais.
Se você preferir continuar, aqui estão mais pensamentos:
Software de gerenciamento de projetos que você usa internamente? Eu compraria antes de construir. Algo como o Rally e o Microsoft Project.
fonte
Primeiro, alguma terminologia, o que você chama de lado da tarefa é conhecido como Transacional e o lado de Relatórios é Analytics.
Você já mencionou o CQRS, que é uma ótima abordagem, mas há pouca aplicação prática documentada da abordagem.
O que foi amplamente testado é complementar o processamento Transacional com um mecanismo de processamento analítico. Isso às vezes é chamado de Data Warehousing ou Data Cubes. O maior problema em relação à análise é que tentar executar consultas nos dados transacionais em tempo real é ineficiente, na melhor das hipóteses, porque é realmente possível otimizar um banco de dados apenas para leitura ou gravação. Para transações, você deseja altas velocidades de gravação para evitar atrasos no processamento / execução. Para relatórios, você deseja altas velocidades de leitura para que decisões possam ser tomadas.
Como explicar esses problemas? A abordagem mais simples de entender é usar um esquema nivelado para seus relatórios e ETL (extrair carga de transformação) para transferir dados do esquema transacional normalizado para o esquema analítico desnormalizado. O ETL é executado regularmente por meio de um agente e pré-carrega a tabela de análise para que esteja pronta para uma leitura rápida do seu mecanismo de relatório.
Um ótimo livro para acelerar o armazenamento de dados é o Data Warehouse Toolkit, de Ralph Kimball. Para uma abordagem mais prática. Faça o download da avaliação do SQL Server e escolha o kit de ferramentas do Microsoft Data Warehouse, que aborda a discussão geral do primeiro livro, mas mostra como aplicar os conceitos usando o SQL Server.
Existem vários livros vinculados dessas páginas que fornecem mais detalhes sobre ETL, Star Schema Design, BI, painéis e outros tópicos para ajudá-lo.
A maneira mais rápida de ir de onde você está para onde você quer estar é contratar um especialista em BI e protegê-lo enquanto ele implementa o que você precisa.
fonte
A recuperação de grandes quantidades de informações em redes de área ampla, incluindo a Internet, é problemática devido a problemas decorrentes da latência da resposta, falta de acesso direto à memória dos dados que servem os recursos e tolerância a falhas.
Esta pergunta descreve um padrão de design para resolver os problemas de manipulação de resultados de consultas que retornam grandes quantidades de dados. Normalmente, essas consultas são feitas por um processo do cliente em uma rede de área ampla (ou Internet), com uma ou mais camadas intermediárias, para um banco de dados relacional que reside em um servidor remoto.
A solução envolve a implementação de uma combinação de estratégias de recuperação de dados, incluindo o uso de iteradores para percorrer conjuntos de dados e fornecer um nível apropriado de abstração para o cliente, buffer duplo de subconjuntos de dados, recuperação de dados multiencadeados e divisão de consultas.
fonte
Eu não acho que você esteja falando sobre lógica de negócios, isso é mais lógica de relatórios. O que os usuários fazem com as informações nesta tela, é simplesmente para atualizações de status? Seu modelo de domínio é usado para modelar operações transacionais, os relatórios são uma preocupação diferente. Puxar os dados do SQL Server ou colocá-los em um data warehouse é bom para cenários de relatórios.
Seu modelo de domínio deve aplicar os invariantes do seu domínio, como um membro do projeto não pode reservar para o mesmo projeto ao mesmo tempo ou pode reservar apenas x número de horas por semana. Ou você não pode reservar para este projeto, pois ele está completo, etc. O estado do seu modelo de domínio (os dados) pode ser copiado para geração de relatórios separadamente.
Para melhorar o desempenho da consulta, você pode usar uma exibição materializada. Quando uma operação é confirmada com relação ao seu modelo (por exemplo, reserve 4 horas desse tempo para o projeto x) e for bem-sucedida, pode ocorrer um evento que você pode armazenar em um banco de dados de relatórios e fazer os cálculos necessários para o seu relatório. Em seguida, será muito rápido consultá-lo.
Mantenha seus contextos de transação e relatório separados, um banco de dados relacional foi construído para relatar que um modelo de domínio não era.
EDITAR
Postagem útil do blog sobre o assunto http://se-thinking.blogspot.se/2012/08/how-to-handle-reporting-with-domain.html
fonte
Passaram quatro anos e acabei de encontrar essa pergunta novamente e tenho o que é, para mim, a resposta.
Dependendo do aplicativo e das necessidades específicas, o banco de dados do domínio / transação e os relatórios podem ser "sistemas" ou "mecanismos" separados ou podem ser atendidos por um sistema. No entanto, eles devem ser logicamente separados - o que significa que eles usam diferentes meios de recuperar e fornecer dados para a interface do usuário.
Eu prefiro que eles sejam fisicamente separados (além de serem logicamente separados), mas muitas vezes você os inicia juntos (fisicamente) e, à medida que o aplicativo amadurece, você os separa.
De qualquer forma, novamente, eles devem ser logicamente diferentes. Não há problema em duplicar a lógica comercial no sistema de relatórios. O importante é que o sistema de relatórios obtenha a mesma resposta que o sistema de domínio - mas é provável que chegue lá por diferentes meios. Por exemplo, seu sistema de domínio terá uma tonelada de regras de negócios muito rígidas implementadas no código processual (provável). O sistema de relatório pode implementar essas mesmas regras quando lê os dados, mas o faria via código baseado em SET (por exemplo, SQL).
Aqui está como uma evolução da arquitetura do seu aplicativo pode parecer realista à medida que evolui:
Nível 1 - Domínio e sistemas de relatório separados logicamente, mas ainda na mesma base de código e banco de dados
Nível 2 - Sistemas de relatórios e domínios separados logicamente, mas agora separam bancos de dados, com sincronização.
Nível 3 - Domínio e sistemas de relatórios separados lógica e fisicamente e separar bancos de dados com sincronização.
A idéia principal é que o relatório e o domínio tenham necessidades radicalmente diferentes. Diferentes perfis de dados (frequência de leituras versus gravações e atualizações), diferentes requisitos de desempenho, etc. Portanto, eles precisam ser implementados de maneira diferente e isso exige alguma duplicação da lógica de negócios.
Cabe a sua empresa criar uma maneira de manter a lógica de negócios do domínio e dos sistemas de relatórios atualizados entre si.
fonte
O estado de cada projeto deve ser armazenado como informações estáticas, calculadas e bem formatadas no banco de dados e quaisquer simulações devem ser tratadas no cliente como WebApp.
esse tipo de projeção não deve ser executado sob demanda. O gerenciamento dessas informações mediante solicitação, como realizar cálculos de recursos, taxa, tarefas, marcos etc., resultará em um uso extensivo da camada de cálculo, sem a reutilização desses resultados para chamadas futuras.
Imaginando um ambiente distribuído ( nuvem pública ou privada ), você terá enormes custos na camada de computação, baixo uso de banco de dados e total falta de cache.
O design do seu software deve incluir a capacidade de executar a normalização dos cálculos necessários para obter o resultado necessário durante a "entrada de dados", não durante a leitura. Essa abordagem reduz bastante o uso de recursos de computação e, acima de tudo, cria tabelas que podem ser consideradas como "somente leitura" pelo cliente. Este é o primeiro passo para criar um mecanismo de cache sólido e simples.
Portanto, uma pesquisa primeiro, antes de concluir a arquitetura do software, poderia ser o Sistema de Cache Distribuído .
(pedido: agregação)! = 1: 1
Minha consideração é, portanto (para o primeiro e o segundo exemplo), tente entender quando é adequado normalizar os dados, tendo como objetivo reduzir as agregações por solicitação do cliente. Que não pode ser 1: 1 (solicitação: agregação) se um objetivo é obter um sistema sustentável.
Distribua o cálculo no cliente
Outra questão, antes de terminar o design do software, pode ser: quanta normalização, queremos delegar o navegador do cliente?
Foi nomeado MV *, é verdade que está na moda hoje, além disso, um de seus objetivos é criar o WebApp (aplicativo de página única), que pode ser considerado o presente de muitos aplicativos complexos (e, felizmente, por faturas que pagamos ao provedor de nuvem, eles são executados no cliente).
Minha conclusão é, portanto:
Compreender quantas operações são realmente necessárias para realizar a apresentação dos dados;
Analise quantas delas podem ser feitas em segundo plano (e depois distribuídas por um sistema de cache, após a normalização);
Compreender quantas operações podem ser executadas no cliente, obtendo a configuração dos projetos, executando-a em Views no WebApp e, assim, reduzir o cálculo realizado no backend;
fonte
Use cache para consulta, use domain para cache.
Há um recurso chamado "usuários principais" no stackoverflow. Você pode encontrar uma linha no topo da página dos principais usuários, que diz "Somente perguntas e respostas de outros wiki da comunidade estão incluídas nesses totais ( atualizados diariamente )". Isso indica que os dados estão armazenados em cache.
Mas por que?
Por questão de desempenho, talvez. Talvez eles tenham a mesma preocupação com a fuga de lógica de domínio ("Somente perguntas e respostas que não são do wiki da comunidade estão incluídas nesses totais" neste caso).
Quão?
Eu realmente não sei como eles fizeram isso, então aqui está apenas um palpite :)
Primeiro, precisamos encontrar perguntas / respostas alvo. Uma tarefa de agendamento pode funcionar, basta buscar todos os destinos em potencial.
Segundo, vejamos apenas uma pergunta / resposta. É um wiki não comunitário? É dentro de 30 dias? É muito fácil responder com modelos de domínio. Conte os votos e armazene-os em cache, se estiver satisfeito.
Agora temos o cache, eles são a saída de derivações de domínio. A consulta é rápida e fácil, porque há apenas critérios simples a serem aplicados.
E se os resultados precisarem ser mais "em tempo real"?
Eventos podem ajudar. Em vez de acionar o cache com uma tarefa de agendamento, podemos dividir o processo em muitos subprocessos. Por exemplo, quando alguém vota na resposta do hippoom, publicamos um evento que aciona a atualização do cache dos principais usuários do hippoom. Nesse caso, podemos ver pequenas tarefas rápidas e frequentes.
O CQRS é necessário?
Nem com a abordagem de tarefas de agendamento nem com a abordagem de eventos. Mas cqrs tem uma vantagem. O cache geralmente é altamente orientado para exibição; se alguns itens não forem necessários a princípio, talvez não possamos calculá-los e armazená-los em cache. O CQRS com fornecimento de eventos ajuda a reconsiderar o cache de dados históricos ao reproduzir eventos.
Algumas perguntas relacionadas:
1. https://stackoverflow.com/questions/21152958/how-to-handle-summary-report-in-cqrs 2. https://stackoverflow.com/questions/19414951/how-to-use -rich-domain-with-maciça-operações / 19416703 # 19416703
Espero que ajude :)
fonte
Isenção de responsabilidade:
sou bastante inexperiente em aplicativos com modelos de domínio.
Entendo todos os conceitos e já penso há muito tempo sobre como aplicar esses conceitos aos aplicativos em que estou trabalhando (que são ricos em domínio, mas sem OO, modelos de domínio reais etc.) .
Esta questão é um dos principais problemas que eu também enfrentei. Eu tenho uma idéia de como resolver isso, mas como eu acabei de dizer ... é apenas uma ideia que eu tive.
Ainda não o implementei em um projeto real, mas não vejo uma razão para que não funcione.
Agora que deixei isso claro, eis o que eu criei - usarei seu primeiro exemplo (as métricas do projeto) para explicar:
Quando alguém edita um projeto, você está carregando e salvando-o por meio do seu modelo de domínio.
Nesse momento, você tem todas as informações carregadas para calcular todas as suas métricas (orçamento total, esforço até o momento etc.) para este projeto.
Você pode calcular isso no modelo de domínio e salvá-lo no banco de dados com o restante do modelo de domínio.
Portanto, a
Project
classe no seu modelo de domínio terá algumas propriedades comoTotalBudget
,EffortToDate
etc., e também haverá colunas com esses nomes nas tabelas de banco de dados em que seu modelo de domínio está armazenado (nas mesmas tabelas ou em uma tabela separada ... doesn não importa) .Obviamente, você precisa executar uma única vez para calcular o valor de todos os projetos existentes, ao começar com isso. Mas depois disso, os dados são atualizados automaticamente com os valores calculados atuais sempre que um projeto é editado por meio do modelo de domínio.
Portanto, sempre que você precisar de qualquer tipo de relatório, todos os dados necessários já estarão lá (pré-calculados) e você poderá fazer algo assim:
Não importa se você obtém os dados diretamente das tabelas em que o modelo de domínio está armazenado ou se de alguma forma extrai os dados em um segundo banco de dados, em um data warehouse ou o que quer que seja:
Em ambos os casos, a lógica de negócios para os cálculos está em exatamente um lugar: o modelo de domínio.
Você não precisa dele em nenhum outro lugar; portanto, não é necessário duplicá-lo.
fonte