IntelliJ Idea的得墨忒耳检验定律。是误还是不对?

时间:2013-10-23 18:25:40

标签: intellij-idea law-of-demeter

假设下一个课程

interface Thing {
  void doSomething();
}

public class Test {
  public void doWork() {
    //Do smart things here
    ...
    doSomethingToThing(index);
    // calls to doSomethingToThing might happen in various places across the class.
  }

  private Thing getThing(int index) {
    //find the correct thing
    ...
    return new ThingImpl();
  }

  private void doSomethingToThing(int index) {
    getThing(index).doSomething();
  }      
}

Intelli-J告诉我,我违反了demeter定律,因为DoSomethingToThing正在使用函数的结果,并且据说你只能调用字段,参数或对象本身的方法。

我真的必须做这样的事情:

public class Test {
  //Previous methods
  ...

  private void doSomething(Thing thing) {
    thing.doSomething();
  }

  private void doSomethingToThing(int index) {
    doSomething(getThing(index));
  }
}
我发现这很麻烦。我认为demeter的定律是这样的,因为一个类不知道另一个类的内部,但是getThing()属于同一类!

这真的违反了德米特的规律吗?这是真正改善的设计吗?

谢谢。

2 个答案:

答案 0 :(得分:0)

从技术上讲,这违反了得墨忒耳的法律。虽然我认为应该考虑LoD-F的私人功能,因为据说它们无法从外部访问。与此同时,如果“东西”归Test所有,那么它并不会破坏Demeter的定律。但是在Java中,获取东西的唯一方法可能是通过一个getter,它将这恢复到技术性(getter和action方法之间没有明确的分离)。

我会说,做到这一点:

public class Test {
  private Thing getThing(int index) {
    //find the thing
    return thing;
  }

  private void DoSomethingToThing(Thing thing) {
    thing.doSomething();
  }

  private void DoSomethingToThing(int index) {
    DoSomethingToThing(getThing(index));
  }
}

或者,或许更好,让调用者直接使用东西。如果Test的功能是产生或暴露事物,而不是作为操纵事物的媒介,那么这是可能的。

答案 1 :(得分:0)

IntelliJ未正确检测对象实例化。

Wikipedia(与IDEA相关的链接)描述了您可以调用在当前上下文中创建的对象。

这就是我的所作所为,但我仍在flatMap()收到警告:

optionalIntegers.stream()
                .flatMap(o -> o.map(Stream::of)
                               .orElse(Stream.empty()))
                .forEach(integers::add);

IDEA的检查提供了忽略对图书馆'方法。就我而言,getMajor() 库方法,但它位于当前项目内(项目必须是自我支持的)。 IDEA认为它不是图书馆方法。

由于这次检查的机制不充分/不完整/天真(比如很多的IDEA检查btw),唯一的解决方案是禁用它并尝试手动避免这些情况。