Qual é o benefício de ter modelos POCO puros?


15

Qual é o principal benefício de ter modelos POCO puros? Entendo que os Modelos devem ser limpos e simples, mas eu gosto de manter a manutenção de objetos filho dentro das classes de modelo. Por exemplo, se eu tiver um ClassAe ClassBdefinido da seguinte forma:

public class ClassA
{
    public string MyProp { get; set; }
    public IEnumerable<ClassB> Children { get; }

    public void AddChild(ClassB newChild) { /*... */ }
    public void RemoveChild(ClassB child) { /* ... */ }
}

public class ClassB
{
    public string SomeProp { get; set; }
} 

Existe algo inerentemente errado em ter os métodos de adição e remoção? Em vez disso, devo apenas expor a lista e permitir que o código do cliente adicione o que quer que seja que passe a responsabilidade de validações simples de dados, como não nulo, e não duplicar para outra classe?

Qualquer ajuda é apreciada, obrigado.


Eu removeria os métodos Adicionar / Remover, a menos que eles adicionassem algum valor, como a conversão de um argumento ClassB nulo em uma versão padrão NullObject do objeto:AddChild(ClassB newChild) => Children.Add(newChild ?? new NullClassB())
Graham

Se você já lidou com a dor de cabeça das classes ActiveRecord com centenas de métodos que podem ou não ser o que você deseja em um determinado momento, acho que seria mais fácil entender o apelo.
Casey

O principal motivo para evitar esse design específico é porque ele vai contra as diretrizes de design do .net. É completamente arbitrário, mas as pessoas esperam que a coleção tenha os métodos de mutação nela.
Frank Hileman

@ Casey Eu não estou usando o padrão Active Record, o método add está simplesmente fazendo uma pequena validação de dados. O método remove existe porque a coleção não é exposta; eles simplesmente adicionam e removem de uma lista interna. Eu o mudei para usar um tipo de coleção diferente que me permita fazer a validação enquanto ainda estiver usando os métodos Adicionar / Remover integrados.
Jesse

Respostas:


42

Suas duas perguntas não têm relação.

Qual é o benefício de ter modelos POCO puros?

Um POCO puro não depende de alguma estrutura empresarial, convenção, [] coisa ou está intimamente conectado a algum objeto que seja igualmente dependente. Em outras palavras, o mundo pode mudar completamente em torno de um POCO e continua fazendo o que faz sem se importar. Você não pode quebrá-lo atualizando uma estrutura, movendo-a para um novo sistema ou olhando para ela de forma engraçada. Apenas continua trabalhando. As únicas dependências são as coisas solicitadas explicitamente.

POCO nada mais é do que a idéia do POJO. OJ foi alterado para um C porque as pessoas olham para você de maneira engraçada quando você explica um conceito que tem Java em seu nome se essas pessoas estiverem usando C #. A ideia não depende da linguagem. Eles poderiam simplesmente chamar isso de Objetos Antigos Simples. Mas quem quer se gabar de usar o POO?

Vou deixar Fowler explicar as origens:

O termo foi cunhado enquanto Rebecca Parsons, Josh MacKenzie e eu estávamos nos preparando para uma palestra em uma conferência em setembro de 2000. Na palestra, destacamos os muitos benefícios de codificar a lógica de negócios em objetos java regulares em vez de usar o Entity Beans. Nós nos perguntamos por que as pessoas eram tão contra o uso de objetos regulares em seus sistemas e concluímos que era porque objetos simples não tinham um nome sofisticado. Por isso, demos a eles um, e ele pegou muito bem.

martinfowler.com: POJO

Quanto à sua outra pergunta:

Existe algo inerentemente errado em ter os métodos de adição e remoção?

Não gosto de Aconhecer diretamente B. Mas isso é uma coisa DIP , não uma coisa POJO .


Eu tinha a dependência direta de, Bpor uma questão de simplicidade, o ideal seria que ambos implementassem interfaces. Mas Aainda tem uma lista de IInterfaceB. Há algo de errado com o AddChildmétodo se os filhos forem vagamente acoplados por meio de referências de interface?
Jesse

6
Eu posso fazer uma série de coisas bobas por uma questão de simplicidade. O que eu não gosto é de A saber B. A não usa B, então não há necessidade de definir uma interface A apropriada para conversar com B. Tanto quanto eu posso dizer, A é uma coleção. Portanto, A deve lidar com B através de um <T> para que ele não precise saber nada sobre isso.
Candied_orange 5/06

2
Eu também vi "PODO" para "objeto de dados antigo simples" para evitar qualquer tipo de especificador de idioma na sigla. PODO parece um pouco bobo (meio que parece um epíteto que você ouviria em Tatooine, para mim), mais do que POJO ou POCO, suponho, mas significativamente menos bobo que POO.
precisa saber é o seguinte

2
Eu me pergunto o quão bem a apresentação de Fowler teria sido se ele os tivesse chamado de POO.
Oliver

3

Com Adicionar e Remover, você está implementando Collection<T>recursos. Pergunte a si mesmo por que você está usando em IEnumerable<T>vez de List<T>ou alguma outra classe mutável? Aparentemente, não é porque sua coleção deve ser somente leitura.

A única razão pela qual consigo pensar é que você deseja controlar quais métodos de acesso deseja publicar. Nesse caso, seria melhor criar sua própria classe de coleção, encapsular uma lista, implementar seus métodos de seleção Adicionar e Remover e implementar IEnumerable<T>. Em seguida, use isso em vez do IEnumerable<T>tipo de coleção de seus filhos.

Mas parece-me List<ClassB>que provavelmente serviria bem a você.


0

O que AddChild adiciona e RemoveChildremove de? Se for do banco de dados (ou de qualquer tipo de armazenamento de persistência), você terá um Registro Ativo. Nem sempre é uma coisa ruim, mas definitivamente deixa você mais próximo de se preocupar com estruturas, convenções, dependências etc., como o @CandiedOrange menciona.

Ao mesmo tempo, qual seria o sentido de evitar uma dependência da ClassA para a ClassB (ou pelo menos InterfaceB) se todos estiverem no mesmo aplicativo? No domínio do mundo real que seu aplicativo está modelando, as coisas dependem umas das outras. Objetos do mundo real têm coleções de outros objetos que "pertencem" a eles. É inteiramente apropriado representar esses relacionamentos no seu código.

A única razão pela qual fica um pouco complicado é porque parece que você precisa gerenciar exatamente como uma Classe B se associa e desassocia da ClassA. Então você tem um pouco de comportamento para implementar. Você pode implementá-lo dentro da classe (que é totalmente "legal"; consulte /programming//a/725365/44586 ) ou pode ter algum tipo de classe separada que contenha esse comportamento. Faça o que faz mais sentido para as suas circunstâncias individuais.

De qualquer forma, POJO / POCO é realmente apenas OOP como deveria ser, sem adornos e sem ônus. Siga os princípios do POO e você estará seguro.


Realmente o AddChild está apenas verificando se há duplicação e nulo, e não permitindo nenhum. RemoveChild está lá porque, para impedir que o backdoor adicione, a coleção é exposta como um IEnumerable. Porém, ele executaria apenas a remoção padrão da coleção.
Jesse

1
Obrigado por explicar. Sim, isso parece exatamente o tipo de comportamento que deveria estar em um POCO e definitivamente melhor do que apenas expor seu IEnumerable subjacente para que os chamadores modifiquem ou substituam à vontade.
John M Gant

Eu acho que o Active Record é apenas um padrão ruim.
Casey

1
@ Casey, você não terá nenhum argumento meu sobre isso. Mas eu não argumentaria se alguém também queria usá-lo. O ponto principal foi que, se Jesse pretendia usar um padrão como o Active Record que integra persistência à definição de modelo, ele teria todos os problemas que CandiedOrange destaca e não se qualificaria realmente como POCO, pelo que vale a pena. Mas não é isso que ele está fazendo de qualquer maneira.
John M Gant
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.