当前位置: 首页 > 知识库问答 >
问题:

干净的代码:依赖注入强制程序代码,如何重构

卢永寿
2023-03-14

我有以下课程:

  class Validator {
    private final SchemaFetcher schemaFetcher;

    @Inject
    Validator(SchemaFetcher schemaFetcher) {...}
  }

  class DatabaseSchemaFetcher implements SchemaFetcher {
     @Override
     Schema loadSchema(final SchemaDefinition schemaDef);

     @Override
     boolean compareSchemaWithSource(final SchemaDefinition schemaDef, final Schema updatedSchema);
  }

这只是其中一个例子,我有一些类似的其他类,我将它们作为依赖注入到其他类中。但是它使我的SchemaFetcher类像一个单例,我不断地向它的每一个方法传递模式定义。这似乎是非常程序化的,我想实际上使模式定义成为数据库模式获取类的实例变量,但在这种情况下,我将无法将模式获取对象注入到我的验证器类中,相反,我应该这样做

   validate(String schemaName) {
     SchemaDefinition schemaDef = buildSchemaDefinitionFrom(schemaName);
     SchemaFetcher fetcher = new DatabaseSchemaFetcher(schemaDef);
   }

但这使我与fetcher紧密耦合,这就是为什么我想首先使用依赖注入。

我可以看到,我可能有一个DatabaseSchemaFetcher的默认构造函数,然后有一个SetSchemaDefinition()setter来实现这一点,但这违反了完全使用构造函数构建对象的原则。

如何改进这一点,使其既不具有过程样式的获取程序,又将依赖项注入构造函数?我更喜欢构造函数注入,因为它清楚地定义了我的依赖项,而不需要任何人查看类的实现,以找出类在使用工厂或服务定位器时使用的依赖项。

共有3个答案

邵阳辉
2023-03-14

我不太确定在这种情况下,依赖注入和过程注入的使用有什么关系。

我认为真正的问题是,你选择的建模对象的方式并没有反映出既定的目标。

在您提供的代码Validator中,我看不到任何用途。如果它的目的是验证SchemaFetcher对象,那么它可能没有超出验证规则的状态,然后接受任意的SchemaFetcher对象进行验证。

至于DataBaseSchemaFetcher。如果它声明的目的只是获取模式,那么它不需要关于DatabaseSchema对象的状态,因此它应该接受DatabaseSchema作为它负责处理DatabaseSchema的方法。任何内部状态都应该只与类的获取行为相关。

>

  • 你试图解决的确切问题的领域非常困难。

    不要解决任何你没有的问题。把你的可扩展性梦想扔掉。他们几乎总是错的,只是一个巨大的时间水槽。

    接受你的设计必然是有缺陷的,你以后必须改变它。

  • 越朗
    2023-03-14

    为什么在第二个解决方案中说您与SchemaFetcher紧密耦合
    你提供了一个接口,所以你没有连接到任何特定的实现,而只有SchemaFetcher的定义(即SchemaFetcher的契约)
    你可以考虑有一个ValueActer类进入它的CTORE模式定义,并且你的DavaStudioCeaTeCter可以保存一个字段给它。通过这种方式,您还可以扩展验证器类,并在需要时更改验证逻辑
    但是,如何传递模式定义对象的问题再次出现。不确定注射应该在这里-考虑改变你的设计。br>

    萧亦
    2023-03-14

    依赖注入是一个非常好的想法,它看起来非常好,以至于被严重滥用。我不会使用DI框架将抓取器注入到验证器中。相反,我希望DI框架将工厂注入到“main”中。工厂使用适当的SchemaDefinition创建获取程序,并将其传递给验证器。

    请记住,我们需要一个将“main”与应用程序其余部分分开的边界,所有依赖项都应该从“main”指向应用程序。应用程序不应该知道“main”。i、 e.“main”是应用程序的插件。

    一般来说,DI应该被用来注入“main”,然后main使用更传统的技术将工厂、策略或只是常规的旧抽象接口传递到应用程序中。

     类似资料:
    • 问题内容: 我已经开始使用gwt进行一些基本的Java编码,而我有点担心主类的繁重。 例如- 如何分隔密钥处理程序,因为它们触发了UI的许多更改,我如何才能将其移到单独的.class文件中,并且仍然能够访问主类中的所有各种小部件,而不必将所有内容传递给处理程序(即,我在click事件之后处理的所有小部件)。 我已经在Google上搜索过,但是没有遇到任何特别好的例子- 知道我可以阅读的任何易读的代

    • 比如 其实相当于 代码不需要手动处理就可以执行。

    • 我有一个Spring MVC项目,我正在尝试使用IntelliJ进行调试。 如果我在控制器代码中设置断点,调试会在适当的地方停止。该特定行在另一个bean中有更多我自己的代码。我希望能够进入代码。如果我在断点装配工后立即“介入”,它会进入Spring的AOP框架代码。 如果我立即触发相同的断点和“智能步进”,它会将我置于源文件的第1行(如上图所示)。这一行-1代表什么?如果我再次执行“smart

    • 问题内容: 我如何强制Spark执行对map的调用,即使它认为由于其惰性求值而无需执行该调用? 我已经尝试过使用map调用了,但是仍然不能解决问题。我的地图方法实际上将结果上传到HDFS。因此,它不是无用的,但Spark认为是。 问题答案: 简短答案: 要强制Spark执行转换,您需要要求一个结果。有时,一个简单的动作就足够了。 TL; DR: 好的,让我们回顾一下 操作。 支持两种类型的操作:

    • 问题内容: Fendy和Glen Best的答案 同样 被我 接受 和尊重,但由于可以接受并给予赏金,因此我选择Fendy的答案。 如果我有 一些代码 有 被多次重复使用 在 许多类 (很少有轻微参数改变是显而易见的)和并发线程,哪种方法去? 必须重用的代码可以是任何理智的东西(在考虑了静态和非静态上下文以及方法制作技术的前提下)。它可以是一种算法,一种执行connect,operate,clos

    • 5.4. 代码注入 一个特别危险的情形是当你试图使用被污染数据作为动态包含的前导部分时: <?php include "{$_GET['path']}/header.inc"; ?> 在这种情形下攻击者能操纵不只是文件名,还能控制所包含的资源。由于PHP默认不只可以包含文件,还可以包含下面的资源(由配置文件中的allow_url_fopen所控制): <?php include 'http://w