Pular para o conteúdo principal

Table Module

Descrição​

O Table Module é uma única instância que trata a lógica de negócio de todas as linhas de uma tabela ou view do banco de dados. Há uma classe por tabela, e seus métodos recebem ou operam sobre um conjunto de dados tabular.

Diferente do Domain Model, que cria um objeto por registro (um objeto para cada pedido), o Table Module tem um único objeto Orders que processa todos os pedidos. Para identificar uma linha, o cliente passa uma chave ou o método recebe o registro como argumento.

O padrão funciona muito bem com Record Set, estruturas tabulares em memória fornecidas por plataformas como .NET (DataSet), que o integram a ferramentas de interface e de acesso a dados.

Problemas que resolve​

  • Evitar o custo e a complexidade do mapeamento objeto-relacional de um Domain Model.
  • Organizar a lógica em um lugar previsível, em vez de espalhá-la em scripts.
  • Aproveitar plataformas e ferramentas orientadas a dados tabulares.

Quando usar​

  • Quando a plataforma oferece suporte forte a Record Set e a controles de interface ligados a dados.
  • Lógica de complexidade moderada, organizada em torno de tabelas.
  • Quando se quer mais estrutura que o Transaction Script, sem o custo de um Domain Model.

Quando evitar​

  • Quando as regras exigem polimorfismo, herança e relacionamentos ricos entre entidades.
  • Quando a lógica cresce e se espalha entre muitos módulos de tabelas que precisam se chamar.
  • Quando o suporte a Record Set da plataforma é fraco.

Trade-offs​

GanhoCusto / Risco
Estrutura mais clara que scripts soltosSem polimorfismo nem identidade por objeto
Dispensa mapeamento objeto-relacionalAcoplado ao formato tabular dos dados
Integra bem com ferramentas orientadas a dadosLógica complexa fica difícil de expressar
Poucas consultas e operações em lote eficientesDifícil migrar para Domain Model depois
  • Desempenho: processar muitas linhas de uma vez costuma ser eficiente.
  • Testabilidade: exige montar Record Sets em memória, mas dispensa banco.
  • Evolução: relações entre tabelas se tornam chamadas entre módulos.

Diagrama​

Cada tabela tem um módulo (OrdersModule, OrderItemsModule) que opera sobre um RecordSet carregado por um gateway de tabela.

Exemplo​

Um módulo Orders calcula o total de um pedido a partir do conjunto de itens carregado.

public class OrderItems
{
private readonly DataTable table;
public OrderItems(DataTable table) { this.table = table; }

public decimal Subtotal(int orderId) =>
table.AsEnumerable()
.Where(r => r.Field<int>("OrderId") == orderId)
.Sum(r => r.Field<decimal>("Price") * r.Field<int>("Qty"));
}

public class Orders
{
private readonly DataTable table;
private readonly OrderItems items;
public Orders(DataTable table, OrderItems items) { this.table = table; this.items = items; }

public decimal Total(int orderId)
{
var row = table.AsEnumerable().Single(r => r.Field<int>("Id") == orderId);
var subtotal = items.Subtotal(orderId);
return row.Field<bool>("Vip") ? subtotal * 0.9m : subtotal;
}
}

Padrões relacionados​

Referência​