[英]Ideal code following the law of demeter and is testable (Dependency injection)?
[英]Dependency Injection with Guice and “Law of Demeter”
“ 与Guice的依赖注入 ”中的一个简单例子打破了“Demeter法则”。 至少PMD意味着它。
public class BillingModule extends AbstractModule {
@Override
protected void configure() {
bind(TransactionLog.class).to(DatabaseTransactionLog.class);
bind(CreditCardProcessor.class).to(PaypalCreditCardProcessor.class);
bind(BillingService.class).to(RealBillingService.class);
}
}
PMD标记下一行警告Potential violation of Law of Demeter (method chain calls)
bind(TransactionLog.class).to(DatabaseTransactionLog.class)
使用@SuppressWarnings("PMD.LawOfDemeter")
抑制此警告是否可以,或者我是否需要采用其他方法?
澄清
通过几个简单的方法,流畅的界面可以转换为经典的一个:
fasten(TransactionLog.class, DatabaseTransactionLog.class);
fasten
可能实现:
private <M, N extends M> void fasten(final Class<M> dependency, final Class<N> realization){
fastenTo(bind(dependency), realization);
}
private <M, N extends M> void fastenTo(final AnnotatedBindingBuilder<M> binder, final Class<N> realization){
binder.to(realization);
}
这不只是一个幻想,一些图书馆,扩展Guice部分使用它。 例如play.libs.akka.AkkaGuiceSupport
:
https://playframework.com/documentation/2.5.5/api/java/play/libs/akka/AkkaGuiceSupport.html
它有方法
default <T extends akka.actor.Actor> void bindActor(java.lang.Class<T> actorClass,java.lang.String name)
default <T extends akka.actor.Actor> void bindActor(java.lang.Class<T> actorClass,java.lang.String name, java.util.function.Function<akka.actor.Props,akka.actor.Props> props)
它不是bindActor(actorClass).qualified(name).with(props)
但它是bindActor(actorClass, name, props)
我知道Guice要复杂得多,并且可以有更多的参数和组合,但是,有人创建了包装库来取代Guice中的流畅界面吗? 有人写点什么吗? 或者,是否有人对Guice的流利感到满意?
此外,我阅读了文章,并发布了流利的界面和德米特法则。 只有少数文章,显然不是来自主流人。 他们中的一些人写道,流利是好的,这里必须违反得墨忒耳法,其中一些人写道,流利的界面很糟糕,有些人写道,流利不违反得墨忒耳法则。 社区没有严格的愿景。
不过,这个问题是关于Guice的,而不是关于“流畅”的界面。
这种“编码规则”检查工具......是关于执行规则的。
它们带来了默认规则集,但使用这些工具的本质是:它们应该按照您希望的方式执行。
换句话说:我们无法告诉你什么是适合你的。 如果你; 使用这个工具的你周围的团队同意:“我们理解这个警告;我们认为它可以很好地压制它”; 那你就定了。 您不需要SO社区的支持; 你希望负责你的项目的人同意“正确的事情”。
我在这里看到的唯一“真实”问题是:决定是否要将大量此类抑制注释推送到代码中; 或者你应该改为调整PMD规则集。
还有一些个人2分:我确实认为“德米特定律”确实是一个重要的规则。 我正在使用python的小cmdline工具; 我最初违反了LoD--故意。 3天后,我开始后悔这个决定。 但是看看你的代码示例; 我不会声明这是一个值得考虑的LoD违规(所以:压制对我来说没问题)。
或者,是否有人对Guice的流利感到满意?
Javadoc for Binding
(强调我的)中提到了流畅的接口的意图:
Guice使用嵌入式特定于域的语言(EDSL)来帮助您简单且可读地创建绑定。
还有一个很大的好处在于你拥有纯真的粘结剂代码读起来几乎像自然语言的流畅的语法:
bind(TransactionLog.class).to(DatabaseTransactionLog.class);
一般而言,在软件工程中,您必须在做出决策时平衡优点和缺点。 再次从同一个javadoc中读取:
这种方法(EDSL)非常适合整体可用性,但它的成本很低:通过读取方法级别的javadoc很难学习如何使用Binding EDSL
它继续承认流利语法的一个缺点,即Binder
javadoc变得稍微不透明。 可能违反“得墨忒耳法”的另一个缺点。
此外,我阅读了文章,并发布了流利的界面和德米特法则。 只有少数文章,显然不是来自主流人。 他们中的一些人写道,流利是好的,这里必须违反得墨忒耳法,其中一些人写道,流利的界面很糟糕,有些人写道,流利不违反得墨忒耳法则。 社区没有严格的愿景。
让它就这样! 有可能存在适合不同倾向的多种方法。
您应该注意关于C#中的扩展方法是否违反封装的类似争论。 请参阅Jon Skeet的回答,并引用Eric Lippert的精彩报道。
说一口流利的API 并不一定违反迪米特法则,因为不是所有的链呼叫违反迪米特法则。
Demeter法则规定您可以访问您所在对象内的任何内容,您获得的方法参数或在调用期间创建的任何对象 。
因此:
bind(TransactionLog.class).to(DatabaseTransactionLog.class)
很好。 你没有得到以前的任何东西,你创建了一个新的绑定。 解除引用适用于(可能)新对象(新的绑定构建器或其他)。
Demeter法则基本上规定您不应访问其他对象的内部字段。 只要您不这样做,只要您愿意,您就可以拥有一个呼叫链。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.