简体   繁体   中英

Dependency Injection with Guice and “Law of Demeter”

A trivial example from the " Dependency Injection with Guice " break the "Law of Demeter." At least as PMD mean it.

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 mark the next line the warning Potential violation of Law of Demeter (method chain calls)

bind(TransactionLog.class).to(DatabaseTransactionLog.class)

Is it fine to suppress this warning with @SuppressWarnings("PMD.LawOfDemeter") or do I need to go with another approach ?

Clarification

With a few simple methods fluent interface can be converted to the classic one:

fasten(TransactionLog.class, DatabaseTransactionLog.class);

Possible realization of 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);
}

This is not just a fantasy, some libraries, that extend Guice partly use it. For example play.libs.akka.AkkaGuiceSupport :

https://playframework.com/documentation/2.5.5/api/java/play/libs/akka/AkkaGuiceSupport.html

It have methods

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)

It's not bindActor(actorClass).qualified(name).with(props) but it is bindActor(actorClass, name, props)

I understand that Guice is much more complicated and could have more parameters and combinations, nevertheless, does someone create wrap libraries that replace fluent interface in Guice? Does someone write something about it? Alternatively, is anyone happy with a fluent in Guice?

Moreover, I read the articles and post about the fluent interface and the Law of Demeter. There are only a few articles and clearly not from the mainstream guys. Some of them wrote that fluent is good, and Law of Demeter must be violated here, some of them wrote that fluent interface is bad and some of them wrote that fluent does not violate the Law of Demeter. There is no strict vision by the community.

Still, this question is about Guice, not about "fluent" interface in general.

Such "coding rule" checking tools ... are about enforcing rules.

They bring a default rule set, but the essence of using such tools is: they should do what you want them to do.

In other words: we can't tell you what is right for you. If you; and the team around you using this tool agrees: "we understand this warning; and we think it is fine suppressing it"; then you are all set. You don't need the buy-in from the SO community; you want that the people responsible for your project agree on "the right thing".

The only "real" question I see here: to decide whether you want to push a lot of such suppress annotations into your code; or if you should instead tune the PMD ruleset.

And some personal 2 cent: I do think that "law of demeter" is really an import rule. I am working on a small cmdline tool with python; and I initially violated LoD - on purpose. 3 days later, I start regretting that decision already. But looking at your code example; I would not declare this to be a LoD violation worth thinking about (so: suppressing would be fine with me).

Alternatively, is anyone happy with a fluent in Guice?

The intention of the fluent interface is mentioned in the Javadoc for Binding (emphasis mine):

Guice uses an embedded domain-specific language, or EDSL, to help you create bindings simply and readably .

There is a great benefit to the fluent syntax in that you get simple binder code that reads almost like natural language:

bind(TransactionLog.class).to(DatabaseTransactionLog.class);

In Software Engineering in general you will have to balance advantages and disadvantages when making a decision. Reading again from the same javadoc:

This approach (EDSL) is great for overall usability, but it does come with a small cost: it is difficult to learn how to use the Binding EDSL by reading method-level javadocs

it goes on to acknowledge one disadvantage of a fluent syntax ie, the Binder javadoc becomes slightly more opaque. A potential violation of the Law of Demeter is, perhaps, another disadvantage.

Moreover, I read the articles and post about the fluent interface and the Law of Demeter. There are only a few articles and clearly not from the mainstream guys. Some of them wrote that fluent is good, and Law of Demeter must be violated here, some of them wrote that fluent interface is bad and some of them wrote that fluent does not violate the Law of Demeter. There is no strict vision by the community.

Let it be so! It's possible for there to exist a multiplicity of approaches that suit different dispositions.

You should probably note the similar debate around whether extension methods in C# violate encapsulation or not. See this answer from Jon Skeet with a great quote from Eric Lippert.

A fluent API does not necessarily violate the Law of Demeter, since not all chain calls violate the Law of Demeter.

The Law of Demeter states that you can access anything inside the object you are in, the method parameters you got, or any object created during the call .

Therefore:

bind(TransactionLog.class).to(DatabaseTransactionLog.class)

Is fine. You don't get anything that was previously there, you create a new binding. The dereferencing applies to (probably) a new object (a new binding builder or whatever).

The Law of Demeter basically states that you should not access internal fields of other objects. As long as you are not doing that, you can have a call chain as long as you like.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM