Quel est l'avantage d'avoir des modèles POCO purs?

15

Quel est l'avantage majeur d'avoir des modèles POCO purs? J'ai l'impression que les modèles doivent être propres et simples, mais j'ai tendance à aimer maintenir la maintenance des objets enfants dans les classes de modèles. Par exemple, si j'ai un ClassAet ClassBdéfini comme suit:

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; }
} 

Y a-t-il quelque chose de mal à avoir les méthodes d'ajout et de suppression? Dois-je à la place simplement exposer la liste et autoriser le code client à ajouter tout ce qui passe la responsabilité de simples validations de données comme non nul et non dupliqué dans une autre classe?

Toute aide est la bienvenue, merci.

Jesse
la source
Je supprimerais les méthodes Add / Remove sauf si elles ajoutent de la valeur, comme la conversion d'un argument ClassB nul en une version de modèle NullObject de l'objet:AddChild(ClassB newChild) => Children.Add(newChild ?? new NullClassB())
Graham
Si vous avez déjà traité le casse-tête des classes ActiveRecord avec des centaines de méthodes qui peuvent ou non être ce que vous voulez à un moment donné, je pense qu'il serait plus facile de comprendre l'appel.
Casey
La principale raison pour éviter cette conception particulière est qu'elle va à l'encontre des directives de conception .net. C'est complètement arbitraire, mais les gens s'attendent à ce que la collection contienne les méthodes de mutation.
Frank Hileman
@Casey Je n'utilise pas le modèle d'enregistrement actif, la méthode add effectue simplement une validation mineure des données. La méthode remove est là car la collection n'est pas exposée, ils ajoutent et suppriment simplement d'une liste interne. Je l'ai cependant changé pour utiliser un type de collection différent qui me permet de faire la validation tout en utilisant les méthodes intégrées Add / Remove.
Jesse

Réponses:

42

Vos deux questions ne sont pas liées.

Quel est l'avantage d'avoir des modèles POCO purs?

Un POCO pur ne dépend pas d'un cadre d'entreprise, d'une convention, [] thingy, ou est intimement lié à un objet qui est également dépendant. En d'autres termes, le monde peut complètement changer autour d'un POCO et il continue de faire ce qu'il fait sans se soucier. Vous ne pouvez pas le casser en mettant à jour un framework, en le déplaçant dans un nouveau système ou en le regardant de manière amusante. Il continue de fonctionner. Les seules dépendances sont les choses qu'il demande explicitement.

POCO n'est rien de plus que l'idée POJO. Le J a été changé en C parce que les gens vous regardent drôle quand vous expliquez un concept qui a Java dans son nom si ces gens utilisent C #. L'idée ne dépend pas de la langue. Ils auraient pu simplement l'appeler Plain Old Objects. Mais qui veut se vanter d'utiliser POO?

Je laisse Fowler expliquer les origines:

Le terme a été inventé alors que Rebecca Parsons, Josh MacKenzie et moi nous préparions pour une conférence lors d'une conférence en septembre 2000. Dans la conférence, nous soulignions les nombreux avantages de l'encodage de la logique métier dans des objets Java normaux plutôt que d'utiliser Entity Beans. Nous nous sommes demandé pourquoi les gens étaient si contre l'utilisation d'objets ordinaires dans leurs systèmes et avons conclu que c'était parce que les objets simples n'avaient pas de nom fantaisiste. Nous leur en avons donc donné un, et c'est très bien compris.

martinfowler.com: POJO

Quant à votre autre question:

Y a-t-il quelque chose de mal à avoir les méthodes d'ajout et de suppression?

Je n'aime pas Asavoir directement B. Mais c'est une chose DIP pas une chose POJO .

candied_orange
la source
J'avais la dépendance directe à des Bfins de simplicité, idéalement, ces deux implémenteraient des interfaces. Mais a Atoujours une liste de IInterfaceB. Y a-t-il un problème avec la AddChildméthode si les enfants sont couplés de manière lâche via des références d'interface?
Jesse
6
Je peux faire toute une série de bêtises pour des raisons de simplicité. Ce que je n'aime pas, c'est que A sache que B. A n'utilise pas B, il n'est donc pas nécessaire de définir une interface appropriée appartenant à A pour parler à B. Autant que je sache, A est une collection. Donc, A devrait traiter B à travers un <T> pour qu'il n'ait rien à savoir à ce sujet.
candied_orange
2
J'ai également vu «PODO» pour «simple vieil objet de données» pour éviter toute sorte de spécificateur de langue dans l'acronyme. PODO sonne un peu idiot (un peu comme une épithète que vous entendriez sur Tatooine, pour moi), plus que POJO ou POCO je suppose, mais beaucoup moins idiot que POO.
KRyan
2
Je me demande dans quelle mesure la présentation de Fowler se serait bien passée s'il les avait appelés POO?
Oliver
3

Avec Ajouter et supprimer, vous implémentez des Collection<T>fonctionnalités. Demandez-vous pourquoi utilisez-vous IEnumerable<T>au lieu de List<T>ou une autre classe mutable? Apparemment, ce n'est pas parce que votre collection doit être en lecture seule.

La seule raison pour laquelle je peux penser est que vous voulez contrôler les méthodes d'accès que vous souhaitez publier. Dans ce cas, il serait plus agréable de créer votre propre classe de collection, d'encapsuler une liste, d'implémenter vos méthodes de sélection Ajouter et Supprimer et d'implémenter IEnumerable<T>. Utilisez ensuite cela au lieu de IEnumerable<T>pour le type de votre collection d'enfants.

Mais il me semble que List<ClassB>cela vous servirait probablement bien.

Martin Maat
la source
0

Qu'est-ce que cela AddChildajoute et RemoveChildsupprime? Si cela provient de la base de données (ou du magasin de persistance de tout type), vous avez en quelque sorte un enregistrement actif. Pas nécessairement toujours une mauvaise chose, mais cela vous rapproche définitivement d'avoir à vous soucier des cadres, des conventions, des dépendances, etc., comme le mentionne @CandiedOrange.

Dans le même temps, quel serait l'intérêt d'éviter une dépendance de ClassA à ClassB (ou au moins InterfaceB) s'ils sont tous dans la même application? Dans le domaine réel que votre application modélise, les choses dépendent les unes des autres. Objets du monde réel n'ont des collections d'autres objets qui « appartiennent » à eux. Il est tout à fait approprié de représenter ces relations dans votre code.

La seule raison pour laquelle cela devient même un peu compliqué, c'est parce qu'il semble que vous ayez besoin de gérer exactement comment un ClassB devient associé et dissocié de ClassA. Vous avez donc un petit comportement à mettre en œuvre. Vous pouvez l'implémenter dans la classe (ce qui est totalement "légal"; voir /programming//a/725365/44586 ), ou vous pouvez avoir une sorte de classe distincte qui contient ce comportement. Faites ce qui convient le mieux à votre situation personnelle.

En tout cas, POJO / POCO est vraiment juste OOP comme il était censé être, sans fioritures et sans encombrement. Suivez les principes de la POO et vous serez en sécurité.

John M Gant
la source
Vraiment, AddChild vérifie simplement la duplication, et null, et n'autorise pas non plus. RemoveChild est là parce que pour empêcher l'ajout de porte dérobée, la collection est exposée comme un IEnumerable. Il n'effectuerait que la suppression standard de la collection.
Jesse
1
Merci d'avoir expliqué. Oui, cela ressemble exactement au type de comportement qui devrait être dans un POCO, et certainement mieux que d'exposer simplement votre IEnumerable sous-jacent pour que les appelants puissent le modifier ou le remplacer à volonté.
John M Gant
Je pense qu'Active Record n'est qu'un mauvais schéma.
Casey
1
@Casey, vous n'obtiendrez aucun argument de ma part à ce sujet. Mais je ne dirais pas non plus si quelqu'un voulait l'utiliser. Le point principal était que si Jesse avait l'intention d'utiliser un modèle comme Active Record qui intègre la persistance à la définition du modèle, il aurait tous les problèmes mis en évidence par CandiedOrange, et ne serait pas vraiment qualifié de POCO, pour ce que cela vaut. Mais ce n'est pas ce qu'il fait de toute façon.
John M Gant