O que é uma maneira prática de modelar lookup tabelas em Domain Driven Design (DDD)?

StackOverflow https://stackoverflow.com/questions/808481

  •  03-07-2019
  •  | 
  •  

Pergunta

Estou aprendendo DDD (livro de Eric Evans está aberto na frente de mim) e eu me deparei com um problema que não consigo encontrar uma resposta para. O que você faz no DDD quando você está apenas tentando obter uma lista simples de registros de pesquisa?

Ex.

EmployeeID: 123
EmployeeName: John Doe
Estado: Alaska (drop-down)
Concelho:. Wasilla (drop-down - serão filtradas com base no estado)

Por exemplo, digamos que você tem um objeto de domínio Employee, uma interface IEmployeeRepository e uma classe EmployeeRepository. Este será utilizado por uma interface de usuário para mostrar uma lista de empregados e detalhes individuais. Na interface do usuário, você quiser usar um drop-down para o Estado e do Concelho, onde as vidas dos funcionários. Os condados disponíveis serão filtrados com base em qual estado foi escolhido.

Infelizmente, as tabelas de banco de dados e interface do usuário muito diferente. Em tblEmployees, ele contém código Estado = AK e County Code = 02130, não os nomes estado e município.

A maneira de idade (antes de começar esta missão DDD) seria bastante simples, basta criar 2 consultas e usar um DataReader para preencher os menus suspensos. Debaixo da exibição nas listas suspensas é o valor, que é usado automaticamente em mensagens de formulário.

Com DDD, porém, eu não sei como você deveria fazer isso. Eu comecei através da criação de Estado e County objetos como repositórios bem e interfaces para os repositórios. No entanto, escrevendo 4 classes + 2 interfaces e do encanamento nos arquivos hbm.xml objetos + Employee negócio parece um exagero para apenas 2 consultas para 2 menus suspensos. Tem que haver uma maneira melhor, não há? Eu não estou mudando os registros nas tabelas estado ou município em breve e até mesmo se eu fizesse, não seria através desta aplicação. Então, eu realmente não quero criar objetos de negócios para Estado e County se eu não preciso.

A solução mais simples que eu vejo é apenas para criar uma classe auxiliar com métodos que dicionários de retorno, como GetStatesAll (), GetState () e GetCounties () e GetCounty (), mas isso só se sente mal de uma perspectiva DDD.

Por favor, ajuda. Como posso usar o DDD sem overengineering apenas um par de pesquisas simples?

Solução Final Eu acho que eu finalmente encontrei a minha resposta através da experiência, que era colocar os GetStates () método em sua própria classe de acesso a dados, embora não uma classe repositório. Desde que eu só estava fazendo o acesso só de leitura, eu joguei em um DTO struct. Desde que o banco de dados era pequeno, eu joguei-los completamente em uma única classe, como Todd abaixo descrito.

As minhas conclusões:

    tabelas
  1. Lookup nunca são objetos de valor, porque tabelas de pesquisa sempre tem uma identidade. Se eles não têm uma identidade, você tem duplicatas, o que não faria muito sentido.
  2. Read-only tabela de pesquisa pode ter um repositório, mas provavelmente não precisa de um. O objetivo de um repositório é reduzir a complexidade, forçando o acesso apenas através do agregado. Atravessar o agregado fornece uma maneira de garantir que as regras de negócio podem ser aplicadas, como a não adição de pneus se você não tiver um carro.
  3. Se você permitir a manutenção CRUD na tabela de pesquisa, então faz sentido para a tabela de referência para ter seu próprio repositório.
  4. O fato de que eu acabei armazenar os códigos como estruturas não torná-los "tipos de valor". Fowler diz em PoEAA que uma struct é um tipo de valor. Isso é verdade, estruturas são imutáveis, razão pela qual Fowler diz que eles são "tipos de valor", no entanto eu estava usando-los de forma diferente. Eu estava usando estruturas como uma maneira leve para passar em torno de DTOs que eu não sempre pensando em mudar após a sua criação inicial. Na verdade, as estruturas que eu usei fez, de fato, têm identidades, mas desde que eles foram somente leitura que trabalhou como estruturas.
  5. Um padrão que eu tenho usado que eu não vejo muito em outros lugares é fazer com que campos de chave primária ser imutável. Eles são definido pelo construtor, mas eles são (acessores não privada) somente leitura e CannOT ser alterado uma vez que o objeto é criado.
Foi útil?

Solução

Você pode querer olhar para o conceito de comando de consulta Separação . Eu não me preocuparia com repositórios digitadas para valores de pesquisa, mas eu ainda provavelmente usar classes tipo DTO sobre conjuntos de dados etc ...

Você pode querer gastar algum tempo lendo blogs de Greg Young a partir de esta ao presente. Ele não fala sobre o preenchimento de pesquisa de dados especificamente, mas muitas vezes ele fala sobre não lidar com a leitura / funcionalidade de relatórios da sua aplicação através de métodos digitadas em um repositório.

Outras dicas

Usando DDD eu tenho algo parecido com o seguinte:

interface IAddressService
{
  IList<Country> GetCountries ();
  IList<State> GetStatesByCountry (string country);
  IList<City> GetCitiesByState (string state);
  // snip
}

País, Estado e Cidade são objetos de valor que vêm de uma tabela de pesquisa no banco de dados.

Bem, eu li um artigo por Mathias Verraes há algum tempo falando sobre isso aqui . Ele fala sobre objetos de valor de separação no modelo a partir de conceitos que servem a interface do usuário.

Citando o artigo quando perguntado se deseja Países modelo como entidades ou valor do objeto:

Não há nada de intrinsecamente errado com os países de modelagem como entidades e armazená-los no banco de dados. Mas na maioria dos casos, que coisas complicar. Países não mudam frequentemente. Quando um mudanças de nome do país, é na verdade, para todos os efeitos práticos, uma novo país. Se um dia um país não existe mais, você não pode basta alterar todos os endereços, porque, possivelmente, o país foi dividido em dois países.

Ele sugeriu uma abordagem diferente para introduzir um novo conceito chamado AvailableCountry:

Estes países disponíveis pode ser entidades em um banco de dados, registros em um JSON, ou mesmo simplesmente uma lista codificada em seu código. (Isso depende se a empresa quer fácil acesso a eles por meio de uma interface do usuário.)

<?php

final class Country
{
    private $countryCode;

    public function __construct($countryCode)
    {
        $this->countryCode = $countryCode;
    }

    public function __toString()
    {
        return $this->countryCode;
    }
}

final class AvailableCountry
{
    private $country;
    private $name;

    public function __construct(Country $country, $name)
    {
        $this->country = $country;
        $this->name = $name;
    }

    /** @return Country */
    public function getCountry()
    {
        return $this->country;
    }

    public function getName()
    {
        return $this->name;
    }

}

final class AvailableCountryRepository
{
    /** @return AvailableCountry[] */
    public function findAll()
    {
        return [
            'BE' => new AvailableCountry(new Country('BE'), 'Belgium'),
            'FR' => new AvailableCountry(new Country('FR'), 'France'),
            //...
        ];
    }

    /** @return AvailableCountry */
    public function findByCountry(Country $country)
    {
        return $this->findAll()[(string) $country];
    }
}

Assim, parece que há uma terceira solução que é modelo de olhar para cima tabelas como objetos e entidades de valor.

BTW certifique-se u verificar a seção de comentários para algumas discussões sérias sobre o artigo.

O estado e município não são entidades, mas o valor objetos. Eles não são o assunto do seu sistema. A maneira como você disse que tratou estes anteriormente é OK. Quando você vai mudar o estado ou registros do condado em seu banco de dados, com base nas mudanças no estado de seu modelo de domínio? Não, de modo que estes não vai precisar de um repositório.

Você está lendo o livro errado, se você quiser aprender como fazer DDD, sem excesso de complicá-la. : -)

A solução mais simples que você está propondo é bom se ele atende às suas necessidades. Encapsulando dados de endereço em objetos de negócios pode ser tão simples ou tão complicada como suas demandas de aplicação. Por exemplo, o objeto de estado tem um relacionamento um-para-muitos com County tão Employee realmente só precisa de fazer referência a uma County se você escolheu para modelá-lo dessa forma. Eu só iria introduzir esse tipo de complexidade, se necessário.

Além disso, eu não acho que há muito a ser ganho por definir as interfaces para seus repositórios a menos que há uma possibilidade real de que você pode ter vários repositórios para seus objetos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top