Je suis tombé sur un dilemme dont je pense qu'il vaut la peine de discuter ici.Est-il correct d'utiliser IoC pour l'extensibilité de mes entités ou du modèle de domaine?
J'ai un ensemble d'objets de domaine (vous pouvez aussi les appeler des entités, si vous préférez), qui reçoivent des données d'une couche d'accès distincte distincte qui est résolue avec un IoC.
Je pensais à rendre mon système très extensible, et je me promène si il est juste de résoudre également ces entités par l'IoC. Permettez-moi de présenter un exemple stupide.
Disons que j'ai un site Web pour lequel je l'interface suivante:
public interface IArticleData
{
int ID { get; }
string Text { get; set; }
}
Le concept est que le DAL implémente ces interfaces, et aussi un IDataProvider<TData>
générique inteface, après quoi le DAL devient facilement remplaçable. Et il y a la classe suivante, qui l'utilise:
public class Article
{
private IArticleData Data { get; set; }
public int ID
{
get { return Data.ID; }
}
public int Text
{
get { return Data.Text; }
set { Data.Text = value; }
}
private Article(IArticleData data)
{
Data = data;
}
public static FindByID(int id)
{
IDataProvider<IArticleData> provider = IoC.Resolve<IDataProvider<IArticleData>>();
return new Article(provider.FindByID(id));
}
}
Cela rend l'ensemble du système indépendant de la mise en œuvre de DAL réelle (ce qui serait dans l'exemple, IDataProvider<IArticleData>
).
Ensuite, imaginez une situation dans laquelle cette fonctionnalité n'est pas vraiment suffisante, et j'aimerais l'étendre. Dans l'exemple ci-dessus, je n'ai pas d'options pour le faire, mais si je fais implémentent une interface:
public interface IArticle
{
int ID { get; }
string Text { get; set; }
}
public class Article : IArticle
{
...
}
Et puis, je supprimer toutes les dépendances à la classe de l'article et commencer à le résoudre comme transitoire Composant IArticle avec un IoC.
Par exemple, dans le château: <component id="ArticleEntity" service="IArticle" type="Article" lifestyle="transient" />
Après cela, si je dois prolonger, ce serait cette simple:
public class MyArticle : Article
{
public string MyProperty { ..... }
}
Et tout ce que je dois faire est de changer la configuration à ce : <component id="ArticleEntity" service="IArticle" type="Article" lifestyle="transient" />
Ainsi, quiconque utiliserait le système en question serait capable de remplacer toutes les classes simplement en réécrivant une ligne dans la configuration. Toutes les autres entités fonctionneraient correctement aussi, car la nouvelle implémenterait la même fonctionnalité que l'ancienne. D'ailleurs, cela semble être une bonne solution pour la philosophie de la «séparation des préoccupations».
Ma question est, est-ce la bonne chose à faire? Après une réflexion sérieuse, je ne pouvais pas trouver de meilleure façon de le faire. J'ai également considéré MEF, mais il semble être orienté vers la création de plugins mais pas pour remplacer ou étendre des parties déjà complètes d'un système comme celui-ci.
J'ai lu beaucoup SO questions (et aussi d'autres sources) sur le sujet, les plus notables sont les suivants: How should I handle my Entity/Domain Objects using IoC/Dependency Injection? et IoC, Where do you put the container?
Et je suis aussi peur que je tombe aux problèmes décrits sur les pages suivantes: http://martinfowler.com/bliki/AnemicDomainModel.html et http://hendryluk.wordpress.com/2008/05/10/should-domain-entity-be-managed-by-ioc/
et une chose: cela augmenterait la testabilité de l'ensemble du système, non?
Qu'en pensez-vous?
EDIT: Une autre option serait de créer un modèle d'usine pour ces entités, mais IoC.Resolve<IArticle>
est plus simple que IoC.Resolve<IArticleFactory>().CreateInstance()
C'est fondamentalement vrai, mais s'il y a un cas où il a besoin de plus de logique métier, il serait utile s'il pouvait être remplacé. (Bien sûr, l'exemple dans la question est juste un stupide, pas une vraie classe.) – Venemo
@Venemo: si c'est le cas, peut-être les éléments de l'article qui représentent la logique métier interchangeable devraient être définis en termes abstraits et injectés dans la classe Article par le conteneur IoC. – pmarflee
Après réflexion, je suis vraiment d'accord avec vous, c'était vraiment trop compliqué. J'ai créé un modèle de dépôt simple, et cela semble résoudre le problème. – Venemo