【问题标题】:Combining builder methods with service methods - bad practice?将构建器方法与服务方法相结合 - 不好的做法?
【发布时间】:2014-03-25 20:27:24
【问题描述】:

这是一个一般模式/最佳实践问题。我使用的是 C#,但我认为它同样适用于 Java 和其他环境。对于库来说,公开一个构建器类是很常见的,该构建器类与一个更加面向服务的类在某种程度上是齐头并进的。假设一个允许你这样做的 ORM:

var sql = SQLBuilder.Select("*").From("Users");
var users = db.ExecQuery<User>(sql);

作为库开发人员,很想将这些组合成一个更流畅、更易于发现的 API,只需要关注一个对象:

var users = db.Select("*").From("Users").ExecQuery<User>();

请注意,区别严格在于 API 表面;在幕后,我们仍然有多个具有适当关注点分离的类。

第二种方法的一个潜在缺点是可测试性。在第一种方法中,存根服务对象要容易得多。但是,如果库开发人员通过公开某种可以在应用启动或测试设置时配置的静态 TestMode 属性来解决这个问题,并发出信号表明应该记录/伪造服务调用,该怎么办?

从纯粹的角度来看,除了可测试性之外,第二种方法有什么“错误”吗?实际上,我正在讨论是否要在我正在开发的几个库中执行此操作,而我的主要危险信号是第一种方法似乎更常见。

【问题讨论】:

    标签: c# java design-patterns builder fluent


    【解决方案1】:

    我认为第二种方法很好,只要公共 API 类只关心提供流畅的接口并正确委派工作。

    【讨论】:

      【解决方案2】:

      我实际上打算为我的下一个版本的 micro orm 采用第二种方法。我没有想到可测试性会受到影响,现在考虑一下,我认为不会。因为那个流利的构建器只是一个门面,至少最后一部分我可能会将它实现为易于测试的扩展方法

      【讨论】:

      • 您不认为从图书馆消费者的角度来看可测试性会受到一点影响吗?在第一种方法中,您可以简单地将 db 完全存根。但是对于第二种方法,您可能需要做更多的模拟设置工作,以至少确保这些构建器方法返回非空值。我想这有多乏味取决于你的模拟框架。 (如果您使用的是最小起订量,SetReturnsDefault 可能会有用。)
      • 除此之外,感谢您的信任投票 - 对采用方法 2 前进感觉更好。
      • 我不这么认为,因为他们不应该首先测试你的代码。另外我认为他们不应该模拟数据库,而应该模拟存储库。但这在处理持久性时是特定的,但我认为它不适用于整个流利的构建器模式,所以它取决于上下文:D
      猜你喜欢
      • 1970-01-01
      • 2017-04-28
      • 2016-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-16
      • 2015-01-08
      • 1970-01-01
      相关资源
      最近更新 更多