Modelos de domínio anêmicos e injeção de serviços de domínio

19

O modelo de domínio anêmico é descrito por Martin Fowler como um antipadrão no design controlado por domínio. Para ter lógica de negócios nos modelos de domínio, geralmente são usados ​​serviços de domínio. Mas a injeção de serviços de domínio em modelos de domínio é considerada prejudicial por Vaughn Vernon (consulte "Implementando o design orientado a domínio", na página 387).

Na minha opinião, essas opiniões são contraditórias, isso é verdade? Como os dois pontos podem ser considerados?

É realmente um modelo de domínio rico com serviços de domínio injetado versus modelo de domínio anêmico e serviços de domínio normal ?

Sjoerd222888
fonte
4
Não sou especialista nisso, mas pensei que o tipo de lógica que entrava nos serviços de domínio e nas entidades de domínio era fundamentalmente diferente. A lógica que entra nas entidades é a lógica necessária para manter o objeto em um estado correto. Isso envolve validação e lógica de transformação. Serviços de domínio, por outro lado, são para lógica de nível superior. Assim, por exemplo, um serviço de domínio modelaria um processo de negócios que envolva vários tipos diferentes de entidades de maneiras complexas.
MetaFight
2
@MetaFight: Mesmo que um processo de negócios afete várias entidades de maneiras complexas, você pode conseguir isso sem serviços, com um bom modelo de domínio Raiz Agregada, ou seja, um modelo de domínio que tenha acesso a todas as entidades afetadas como propriedades ou campos em si.
Greg Burghardt
Isso faz sentido :)
MetaFight

Respostas:

16

Um modelo anêmico é simplesmente um contêiner de dados. Não contém comportamento. (Isso pode realmente ser considerado uma coisa boa no paradigma funcional.) O oposto de um modelo anêmico não é um modelo injetado cheio de serviços de domínio. Você está descrevendo dois extremos - ambos são ruins.

Se você tem um modelo anêmico, não está adotando totalmente o que o OOP oferece. Se você começar a injetar serviços nesses modelos, provavelmente estará injetando preocupações que não pertencem a ele. Ou isso ou seu modelo é mais anêmico do que você pensa. Por que mais você precisaria do serviço, além de fornecer algo que é necessário, mas está faltando? (Falta pode significar anêmica).

Evitar os dois "avanços" leva a um design mais forte. Você tem algo em um serviço que um modelo precisa? Talvez deva ser movido para o modelo. Caso contrário, talvez você deva reconsiderar suas preocupações. O comportamento de um modelo deve funcionar dentro do modelo. Deveria se preocupar principalmente (se não apenas) com os membros. Mas lembre-se, ainda haverá coisas que funcionam no modelo ou com ele . Por exemplo, os modelos não devem abrir conexões TCP ou ouvir eventos da interface do usuário, mesmo que estejam envolvidos de alguma forma. Isso é responsabilidade de outra pessoa e que alguém não pertence dentro do modelo.

Roger escasso
fonte
7
Uma boa distinção que eu gostaria de lembrar é que seu Modelo de Domínio implementa a lógica de negócios e seus Serviços de Domínio executam a lógica de negócios nos Modelos de Domínio. A diferença é quem está chamando quem. Os serviços podem chamar métodos de modelo de domínio. Se os Modelos de Domínio estão chamando métodos de Serviço, você inverte o padrão.
Greg Burghardt
7

Não é contraditório. Ambos os proponentes gostariam que você colocasse seu código real no próprio objeto de domínio.

ie

public class Order
{
    private string status = "not bought";
    public void Buy()
    {
        this.status = "bought";
    }
}

vs ADM

public class Order
{
    public string Status = "not bought";
}

public class BuyingService
{
    public Order Buy(Order order)
    {
         Order o = new Order();
         o.status = "bought";
         return o;
    }
}

vs serviços injetados

public class Order
{
    public Order(IBuyingService bs)
    {
        _bs = bs;
    }
    private IbuyingService _bs;
    private string status = "not bought";
    public void Buy()
    {
        this.status = _bs.Buy();
    }
}

public class BuyingService : IBuyingService
{
    public string Buy()
    {
         return = "bought";
    }
}

Francamente, embora cada abordagem tenha vantagens e desvantagens. O que você escolhe é em grande parte uma questão de preferência pessoal

Ewan
fonte