Pergunta

Eu estava tentando encontrar um exemplo claro e simples do que realmente significa um domínio anêmico.Há muita teoria por aí e também muitas perguntas bem respondidas.Ainda assim, não consegui ter uma ideia clara sobre até que ponto o significado de “domínio anêmico” realmente vai.Portanto, acredito que seria mais simples ver um exemplo prático fictício de um design de domínio anêmico e perguntar como isso poderia evoluir para um design orientado por domínio ...

Então, digamos que temos uma entidade de dados do tipo Dados da Tarefa:

public class TaskData
{
    public Guid InternalId { get; set; }

    public string Title { get; set; }

    public string Details { get; set; }

    public TaskState ExplicitState { get; set; }

    public IEnumerable<TaskData> InnerTasks { get; set; }

}

E há a necessidade de uma propriedade adicional chamada "Estado atual", que é um estado computado:se a Tarefa tiver subtarefas internas, o valor depende estritamente dos filhos, caso contrário, o "Estado atual" é igual a "Estado Explícito"

Se eu escrever esta lógica em separado serviço classe (eu os chamo de "motores") Nós temos:

internal class TaskStateCalculator
{
    public TaskState GetState(TaskData taskData)
    {
        if (taskData.InnerTasks.Any())
        {
            if (taskData.InnerTasks.All(x => this.GetState(x) == TaskState.Done))
            {
                return TaskState.Done;
            }
            if (taskData.InnerTasks.Any(x => this.GetState(x) == TaskState.InProgress))
            {
                return TaskState.InProgress;
            }

            return TaskState.Default;
        }

        return taskData.ExplicitState;
    }       
}

O primeira pergunta é:

O código acima reflete um design de domínio anêmico, mesmo que o Calculadora TaskState serviço/mecanismo faz parte da minha camada de domínio?Se sim, para evitá-lo, precisaremos mover a lógica dentro do Dados da Tarefa classe (e renomear Dados da Tarefa para Tarefa).Estou certo?

O segunda questão é (na verdade, uma cadeia deles):

E se tivermos uma situação mais difícil?Digamos que haja a necessidade de uma propriedade chamada ComputeAlgo dentro Tarefa entidade, e a lógica desta propriedade precisa acessar toda a tarefa repositório.Neste caso, o Tarefa classe teria uma dependência de Repositório de Tarefas.Isso estaria bem?Como a EF construiria uma instância dessa classe?Qual é a alternativa?

Foi útil?

Solução

Eu estava tentando encontrar um exemplo claro e simples do que realmente significa um domínio anêmico

Na verdade, é muito fácil passar de um modelo de domínio anêmico para um modelo rico.

  1. Defina todos os configuradores de propriedades como private e, em seguida, adicione métodos se desejar alterar o estado de um modelo.
  2. Avalie tudo Lei de Deméter violações e adicionar métodos quando adequado.

Eventualmente você terá um modelo correto.

No seu caso, eu encapsularia essa lógica dentro TaskData já que sua TaskStateCalculator viola a Lei de Demeter

public class TaskData
{
    public Guid InternalId { get; private set; }

    public string Title { get; private set; }

    public string Details { get; private set; }

    public TaskState ExplicitState { get; private set; }

    public IEnumerable<TaskData> InnerTasks { get; private set; }

    public TaskState GetState()
    {
        if (!InnerTasks.Any())
            return ExplicitState;

        if (InnerTasks.All(x => this.GetState(x) == TaskState.Done))
        {
            return TaskState.Done;
        }

        if (InnerTasks.Any(x => this.GetState(x) == TaskState.InProgress))
        {
            return TaskState.InProgress;
        }

        return TaskState.Default;
    }       
}

outra coisa é que eu provavelmente não exporia a coleção InnerTasks ao mundo exterior (apenas a teria como um campo de membro).Mas é difícil dizer porque não sei como a classe é usada em outros cenários.

Por que setters privados

Cada vez que você precisa alterar mais de uma propriedade, geralmente é melhor descrever o comportamento com um método, pois é impossível esquecer de alterar todas as propriedades necessárias.Um método também descreve melhor o que você está tentando fazer do que alterar um conjunto de propriedades.

Mesmo se você alterar apenas uma única propriedade, essa propriedade poderá definir a classe em um estado inválido, pois a alteração pode não ser compatível com o restante das informações da classe.Não se esqueça que o encapsulamento é um dos princípios fundamentais da OOP

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