A maneira como você faz a pergunta (e propõe duas alternativas) é como se a única preocupação fosse que o driverId ainda fosse válido no momento em que o carro foi criado.
No entanto, você também deve se preocupar que o driver associado ao driverId não seja excluído antes que o carro seja excluído ou entregue a outro motorista (e possivelmente também que o driver não esteja atribuído a outro carro (isso se o domínio restringir o motorista a apenas ser associado a um carro)).
Sugiro que, em vez de validação, você aloque (o que incluiria validação de presença). Você não permitirá exclusões enquanto ainda estiver alocado, protegendo assim contra a condição de corrida de dados obsoletos durante a construção, bem como outro problema de longo prazo. (Observe que a alocação valida e as marcas alocadas e opera atomicamente.)
Por outro lado, concordo com o @PriceJones que a associação entre o carro e o motorista provavelmente é uma responsabilidade separada do carro ou do motorista. Esse tipo de associação só aumentará em complexidade ao longo do tempo, porque soa como um problema de agendamento (motoristas, carros, horários / janelas, substitutos, etc.). Mesmo que pareça um problema de registro, pode-se querer histórico registros, bem como registros atuais. Assim, pode muito bem merecer seu próprio BC imediatamente.
Você pode fornecer um esquema de alocação (como uma contagem booleana ou de referência) dentro do BC das entidades agregadas que estão sendo alocadas ou dentro de um BC separado, por exemplo, aquele responsável por fazer a associação entre carro e motorista. Se você fizer o primeiro, poderá permitir operações de exclusão (válidas) emitidas para o carro ou motorista BC; se você fizer o último, precisará impedir exclusões dos BCs de carros e drivers e enviá-las pelo agendador de associações de carros e drivers.
Você também pode dividir algumas das responsabilidades de alocação entre os BCs, como segue. O BC de carro e motorista fornece um esquema de "alocação" que valida e define o booleano alocado com esse BC; quando sua alocação booleana é definida, o BC impede a exclusão das entidades correspondentes. (E o sistema está configurado para que o carro e o motorista BC só permitam alocação e desalocação do agendamento da associação de carro / motorista BC.)
O BC do carro e motorista mantém um calendário de condutores associados ao carro por alguns períodos / durações, agora e no futuro, e notifica os outros BCs de desalocação apenas no último uso de um carro ou motorista programado.
Como uma solução mais radical, você pode tratar os BCs de automóveis e condutores como fábricas de registros históricos apenas anexados, deixando a propriedade para o planejador da associação de carros e condutores. O carro BC pode gerar um carro novo, completo com todos os detalhes do carro, junto com seu VIN. A propriedade do carro é gerenciada pelo agendador da associação carro / motorista. Mesmo que uma associação de carro / motorista seja excluída e o próprio carro seja destruído, os registros do carro ainda existem no carro BC, por definição, e podemos usar o carro BC para procurar dados históricos; enquanto associações / proprietários de automóveis / condutores (passado, presente e potencialmente programados para o futuro) estão sendo administrados por outro BC.
Driver.delete
não deveria existir. Eu realmente nunca vi um domínio em que agregados são destruídos. Ao manter os ARs próximos, você nunca pode acabar com órfãos.Pode ser útil perguntar: Você tem certeza de que os carros são fabricados com motoristas? Eu nunca ouvi falar de um carro composto por um motorista no mundo real. A razão pela qual essa pergunta é importante é porque ela pode indicar a direção de criar carros e motoristas de forma independente e criar algum mecanismo externo que atribua um motorista a um carro. Um carro pode existir sem uma referência ao motorista e ainda ser um carro válido.
Se um carro tiver absolutamente um motorista em seu contexto, convém considerar o padrão do construtor. Esse padrão será responsável por garantir que os carros sejam construídos com os motoristas existentes. As fábricas atenderão carros e motoristas validados de forma independente, mas o construtor garantirá que o carro tenha a referência necessária antes de servir o carro.
fonte
Acho que sim. A busca de um determinado DriverId no banco de dados retorna um conjunto vazio, se ele não existir. Portanto, verificar o resultado do retorno torna desnecessário perguntar se ele existe (e depois buscar).
DriverId
e é definido no construtor.Car
necessidades apenas oDriverId
, ter umDriver.Id
getter. Sem setter.Car
se importa se tiver umDriver
(ou seu ID, pelo menos). ADriver
se importa se tiver aDriverId
. Ele seRepository
preocupa com a integridade dos dados e não pode se importar menos com carros sem motorista.DriverId
ser um domínio de negócios é tratado nas classes apropriadas.... acontece quando
Repository.DriverIdExists()
faz a pergunta.Crie um objeto de domínio. Se não for um
Driver
, talvez um objetoDriverInfo
(apenas umDriverId
eName
, digamos). ODriverId
é validado na construção. Ele deve existir e ser do tipo certo e qualquer outra coisa. Em seguida, é um problema de design da classe do cliente como lidar com um driver / driverId inexistente.Talvez um
Car
esteja bem sem motorista até você ligarCar.Drive()
. Nesse caso, oCar
objeto, é claro, garante seu próprio estado. Não é possível dirigir sem umDriver
- bem, ainda não.Claro, tenha um,
Car.DriverId
se desejar. Mas deve ser algo como isto:Isso não:
Agora, é
Car
preciso lidar com todos osDriverId
problemas de validade - uma única violação do princípio de responsabilidade; e código redundante provavelmente.fonte