Como lidar com campos calculados complexos em um ORM

8

Em nossa API, temos alguns tipos de dados centrais que precisam ser "decorados" (por assim dizer) após a recuperação do banco de dados com valores calculados. O banco de dados é acessado através de um ORM que segue uma dinâmica de Tabela / Entidade fortemente inspirada na camada de banco de dados do CakePHP 3, onde um objeto de Tabela é usado como intermediário entre o banco de dados e o aplicativo que recebe e distribui linhas como instâncias de objeto de modelo. Portanto, em vez de apenas recuperar dados do banco de dados e retornar essas linhas, precisamos pré-processar os dados retornados antes que sejam realmente utilizáveis. Aqui estão alguns casos de uso que surgiram para explicar melhor o que quero dizer:

  • Os objetos têm valores numéricos que são traduzidos para rótulos amigáveis ​​ao usuário (normalmente essa é a lógica que eu manteria apenas no cliente, mas por razões de segurança comercial, alguns desses dados precisam ser mantidos apenas no servidor, reconhecidamente caso borda)
  • Os objetos precisam ter um valor de classificação associado, extraído da classificação adicionada mais recentemente
  • Com base em uma combinação de valores calculados como este e valores armazenados, um objeto de planejamento complexo é construído

Por si só, qualquer um desses individualmente é realmente muito fácil de executar com uma map()operação simples sobre o conjunto de resultados retornado. O mesmo se aplica a quando você deseja vários valores calculados, basta realizar mais operações de mapa para calcular e adicionar esses campos conforme necessário.

Dito isto, essa abordagem tem duas grandes desvantagens:

  1. Isso significa que você precisa executar uma etapa adicional de pós-processamento em todos os lugares em que deseja trabalhar com esses valores calculados, o que não é particularmente SECO
  2. Algumas dessas transformações dependem de outras transformações sendo executadas primeiro, caso contrário, elas simplesmente não têm os dados disponíveis para trabalhar com

Para lidar com ambos, estive pensando que a melhor abordagem seria mover esse código para o ORM e modificá-lo para que a interface permita (externamente) o acesso aos campos virtuais calculados da mesma maneira que lida com as colunas do banco de dados . Internamente, ele poderia mapear esses campos virtuais para funções de transformação e determinar internamente quaisquer possíveis transformações de dependência necessárias para resolver o segundo problema.

(À parte, estou pensando se isso também elimina a necessidade de as linhas retornadas serem objetos reais, em oposição a hashes simples. No momento, cada linha instancia um novo objeto com os dados do campo definidos, mas se todo o cálculo ou Como a modificação dos dados é removida do modelo, o objeto se torna um conjunto de propriedades - um mapa de hash, essencialmente, sem lógica interna própria. O que, na verdade, pode não ser uma coisa ruim)

moberemk
fonte
Como foi isso @moberemk?
Slamice 22/03
Se for muito difícil com o ORM, você poderá usar a consulta SQL nativa. Normalmente, o ORM fornece a maneira de realizar consultas SQL seguras, porque eles sabem muito bem que não podem lidar com todas as situações que podem ser feitas no SQL bruto.
Walfrat 23/03

Respostas:

3

Você pode usar a camada semelhante a repositório para os casos mencionados acima.

[Repositório] Medeia entre o domínio e as camadas de mapeamento de dados usando uma interface semelhante a uma coleção para acessar objetos do domínio.

Um repositório por caso, que usa o ORM para ler dados, os enriquece e retorna.

Portanto, você teria uma maneira unificada de acessar essas instâncias e ocultar como essas instâncias são criadas de fora. Isso também permite que você alterne do ORM para as consultas SQL brutas sem alterar a interface exposta.

potfur
fonte
Isso foi o que acabei fazendo neste projeto essencialmente, mas quero observar que houve enormes problemas de desempenho com isso em grandes conjuntos de dados. Essencialmente: funciona, mas não em escala. Aceitando a precisão embora.
Moberemk 26/03/16
0

Eu concordo com @potfur. A divisão entre os "objetos de dados", representando dados no banco de dados e sua representação "comercial", encapsulando lógica adicional, cálculo, etc., é IMHO na direção certa. Como os dados são representados para determinado domínio / empresa e o que é tecnicamente armazenado, podem ser coisas completamente diferentes. A implementação da lógica de negócios com objetos que representam o domínio ajuda a agregar valor ao cliente e facilita a comunicação. Quanto ao ORM, você menciona problemas de escalabilidade. Eu acho que um ORM é um anti-padrão. Embora muito útil em escala menor / média, quando se trata de escalabilidade, começa a falhar. O que você pode fazer é adicionar uma camada de cache para as "entidades comerciais", para que você não precise calculá-las sempre.

David Lukac
fonte