Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 依赖注入会增加我做傻事的风险吗?_Oop_Dependency Injection_Encapsulation - Fatal编程技术网

Oop 依赖注入会增加我做傻事的风险吗?

Oop 依赖注入会增加我做傻事的风险吗?,oop,dependency-injection,encapsulation,Oop,Dependency Injection,Encapsulation,我正试图接受广泛的依赖注入/IoC。随着我越来越多地了解到这些好处,我当然会感激它们,然而,我担心在某些情况下,采用依赖注入模式可能会导致我创造灵活性,而代价是通过封装系统能够做什么以及我或项目中的其他程序员能够犯什么错误的控制来限制风险。我怀疑我在解决我的问题的模式中遗漏了什么,我希望有人能指出这一点 这里有一个简单的例子来说明我所关心的问题。假设我在通知类上有一个NotifyAdmins方法,并且我使用该方法将非常敏感的信息分发给应用程序中定义为管理员的用户。根据用户定义的设置,可以通过传真

我正试图接受广泛的依赖注入/IoC。随着我越来越多地了解到这些好处,我当然会感激它们,然而,我担心在某些情况下,采用依赖注入模式可能会导致我创造灵活性,而代价是通过封装系统能够做什么以及我或项目中的其他程序员能够犯什么错误的控制来限制风险。我怀疑我在解决我的问题的模式中遗漏了什么,我希望有人能指出这一点

这里有一个简单的例子来说明我所关心的问题。假设我在通知类上有一个NotifyAdmins方法,并且我使用该方法将非常敏感的信息分发给应用程序中定义为管理员的用户。根据用户定义的设置,可以通过传真、电子邮件、IM等方式分发信息。此方法需要检索管理员列表。历史上,我会通过调用AdminSet类,或者调用要求一组属于管理员的用户对象的UserSet类,或者甚至通过直接调用数据库来封装在方法中构建管理员集。然后,我可以调用Notification.NotifyAdmins方法,而不用担心意外地将敏感信息发送给非管理员

我相信依赖注入要求我将管理员列表作为参数(以某种形式)。这确实有助于测试,但是,如何防止我在调用代码和传递一组非管理员时犯愚蠢的错误呢?如果我不注入设置,我只能在一个或两个固定的位置不小心给错误的人发送错误的电子邮件。如果我真的注入了这个集合,那么我在调用方法和注入管理员集合的任何地方都会犯这个错误吗?我做错什么了吗?IoC框架中是否有允许您指定这些类型的约束但仍然使用依赖注入的设施


谢谢。

否,依赖项注入不要求您将管理员列表作为参数传递。我想你有点误解了。但是,在您的示例中,它将涉及注入
通知
类用于构建其管理员列表的
AdminSet
实例。然后,这将使您能够模拟此对象以单独测试
通知


依赖项通常在实例化类时使用以下方法之一进行注入:构造函数注入(在类的构造函数中传递依赖类实例)、属性注入(将依赖类实例设置为属性)或其他方法(例如,使所有可注入对象实现一个特定接口,该接口允许IOC容器调用注入其依赖项的单个方法。它们通常不会像您建议的那样注入到每个方法调用中。

您需要改变想法

如果您有一个服务/类,该服务/类应该只向管理员发送私有信息,而不是向该服务传递管理员列表,而是传递另一个服务,该类可以从中检索管理员列表

是的,您仍然有可能犯错误,但此代码:

AdminProvider provider = new AdminProvider();
Notification notify = new Notification(provider);
notify.Execute();
比这更难出错:

String[] admins = new String[] { "joenormal@hotmail.com" };
Notification notify = new Notification(admins);
notify.Execute();
在第一种情况下,所涉及的方法和类的命名方式将非常清楚,这样很容易发现错误

在Execute方法内部,代码可能如下所示:

List<String> admins = _AdminProvider.GetAdmins();
...
List<String> admins = _AdminProvider.GetAllUserEmails();
List admins=\u AdminProvider.GetAdmins();
...
如果出于某种原因,代码如下所示:

List<String> admins = _AdminProvider.GetAdmins();
...
List<String> admins = _AdminProvider.GetAllUserEmails();
List admin=\u AdminProvider.GetAllUserEmails();

那么你有一个问题,但这应该很容易发现。

其他好的答案已经给出,但我想补充一点:

您既可以开放扩展性(遵循),也可以保护敏感资产

在这种情况下,您可以传入一个完全任意的用户列表,但随后通过AdminSpecification过滤这些用户,以便只有管理员收到通知

您的通知类可能会有一个类似于以下内容的API:

public class Notification
{
    private readonly string message;

    public Notification(string message)
    {
        this.message = message;

        this.AdminSpecification = new AdminSpecification();
    }

    public ISpecification AdminSpecification { get; set; }

    public void SendTo(IEnumerable users)
    {
        foreach(var u in users.Where(this.AdminSpecification.IsSatisfiedBy))
        {
            this.Notify(u);
        }
    }

    // more members
}
出于测试目的,您仍然可以通过指定不同的规范来覆盖过滤行为,但默认值是安全的,因此您不太可能在使用此API时出错


为了获得更好的保护,您可以将整个实现包装在一个接口后面。

否,但访问stackoverflow.com会:-)所谓参数,我指的是注入,而不是在类中定义。很抱歉不够清晰。让我紧张的是注入管理信息。更一般地说,如果我在方法中检索数据,我知道从何处获取数据。如果是注入的,我如何知道数据与我想要的数据相同,而不仅仅是stru是否完全相同?如果我能够模拟表示管理信息的任何类/类集(从可测试性的角度来看,这当然是一件好事)这不一定意味着方法不能信任它接收的数据吗?不是你注入的数据,而是用来构造/检索数据的类。你甚至可以“反向”它甚至可以将通知提供程序传递给您的AdminSet。我遵循您的示例,但我认为我仍然暴露在外。想必,AdminProvider是一个接口的实现,有人可能会向通知发送一个以错误方式实现GetAdmins的实现。我的示例有点做作,但我担心的是我不能相信一个类不再强制内部控制;一旦我使用DI,我就不得不担心调用方出错。我认为Cellfish的方法给了我想要的控制,但我又有了内部依赖(我需要