C# 我的代码充满了服务接口!

C# 我的代码充满了服务接口!,c#,asp.net-mvc,service,repository-pattern,C#,Asp.net Mvc,Service,Repository Pattern,大家好。我遇到了一个使用存储库和服务模型的奇怪设计模式。应用程序包括ASP.NET MVC、WCF和一些Windows服务。我的存储库正在使用LINQDataContext。随着应用程序的发展,我发现自己到处都在传递对IWhateverService的引用。例如,我有IAccountService,它定义了ChangePlan(帐户、计划)等方法 现在,似乎IAccountService是使用此方法的最佳场所,因为我们在这里为帐户提供服务。然而,ChangePlan方法在实际更改计划之前需要知道

大家好。我遇到了一个使用存储库和服务模型的奇怪设计模式。应用程序包括ASP.NET MVC、WCF和一些Windows服务。我的存储库正在使用LINQDataContext。随着应用程序的发展,我发现自己到处都在传递对IWhateverService的引用。例如,我有IAccountService,它定义了ChangePlan(帐户、计划)等方法

现在,似乎IAccountService是使用此方法的最佳场所,因为我们在这里为帐户提供服务。然而,ChangePlan方法在实际更改计划之前需要知道一些事情。它必须知道用户的当前使用情况、可用计划列表、用于计费的电子商务服务接口实例等

我认为让ChangePlan方法接受IAccountService接口中所有必需的服务。但是这些其他服务的需求是实现的问题,不应该是接口定义的一部分

因此,现在我发现自己正在为AccountService创建一个巨大的构造函数,以IAccountRepository、IPlanService、IUsageService、IECCommerceService和IValidationDictionary为例。这感觉一点也不对劲

现在,以这个场景为例。显然,IAccountService包含一个简单的方法来通过ID检索用户的帐户:account Get(intid)有时我只需要调用这个方法。所以,我去创建我的AccountService,它需要所有其他服务的实例(特别是IValidationDictionary,我不需要验证)。同样,这感觉是错误的。我可以传递null,但这只是因为我知道实现并没有将它们仅用于此方法

另外,为了避免在我需要的任何地方实例化服务,我创建了一个名为ServiceFactory的静态类,它有静态方法、CreateAccountService、CreatePlanService等。。。我围绕应用程序调用这些方法。这看起来还可以,但我无法摆脱这种不合适的感觉

我的电话在哪里?有人有什么建议吗

谢谢


Andrew

事件至少可以帮助您将其中的一些解耦。您可以让需要将计划更改注册验证为ChangePlanRequestEvent的其他服务,让每个服务执行必要的验证,如果不允许更改,则引发异常。现在你有问题了。计划的细节应编码在计划对象中,除非您想显示,否则任何人都不需要可用计划的列表


但为什么会有会计服务呢?对我来说,为什么ChangePlan不是一种计算方法呢?

您所描述的设计似乎非常符合原则。许多较小的部件通常也被认为是良好的设计

SOLID原则通常会接受您在实现中描述的非规范化,并且更倾向于让这样一个组件的每个外部用例都有自己的接口


我认为你的主要问题是你花了太多的时间思考如何构建这些对象。您可能应该考虑一个依赖项注入框架来处理这个问题,比如。然后,您只需在完全状态下构造对象,而不必担心每次调用都没有使用所有依赖项。

在以前的项目中,我与您走了一条相同的道路,我还没有找到一种干净的方法来解决这个问题。我认为真正的答案是SOA解决了多少问题,就造成了多少问题。逻辑是,通过解耦一切,您可以轻松地切换服务及其实现。然而,如果我们为这样一个特性付出的代价是代码变成了一堆接口、服务和注入的依赖项,那么这样做的好处是值得的——我说不是

我目前的SOA方法是谨慎行事。一旦意图和实现确定下来,我们就从常规编写的代码中获取服务

所以现在我发现自己创造了一个巨大的 AccountService获取的构造函数 IAccountRepository的一个实例, IPlanService、IUsageService、, IECCommerceService,以及 我是虚构的。这并不重要 感觉很好

像这样的依赖性不应该是一个大问题。您需要注意的是AccountService中的大量方法。如果您有100行长的方法,那么可能是时候考虑重构并将AccountService分解为几个较小的服务了

另外,为了避免实例化 无论我在哪里需要服务,我都会 创建了一个名为 ServiceFactory,它具有静态 方法、CreateAccountService、, 创建计划服务等。。。我称之为 方法围绕应用程序。这个 看起来不错,但我无法摆脱这种感觉 这是不恰当的

您可以使用一个解决方案来消除对这些工厂的需求


除非您的对象非常大或在构建过程中加载数据(通常不应该这样做)然后,构造一个类的新实例所需的时间微乎其微,不必担心。

您能创建重载构造函数来接受执行底层操作所需的接口吗?例如:

AccountService(IAccountRepository)
AccountService(IAccountRepository, IPlanService)
AccountService(IAccountRepository, IPlanService, IUsageService, IEcommerceService,IValidationDictionary)

然后,帐户服务中的方法可以断言特定接口引用在对其进行操作之前不为null。

我同意这正是创建依赖注入框架要解决的问题(我建议使用Ninject,但它们中的任何一个都可以帮助您解决此问题)。+1,对这个问题的描述听起来正是DI和IoC发明的目的。