2013-10-23 5 views
0

IntelliJ Idea의 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(); 
    }  
} 

인텔리 J가 나는 함수의 결과를 사용 DoSomethingToThing 때문에 데메테르의 법을 위반하고있어 가정에만 필드, 매개 변수 또는의 메소드를 호출 할 수 있음을 말해되는 다음 클래스를 가정 개체 자체.

은 정말 이런 식으로 뭔가를해야합니까 :

public class Test { 
    //Previous methods 
    ... 

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

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

나는 귀찮은 것을 찾을 수 있습니다. 데메테르의 법칙은 한 클래스가 다른 클래스의 내부를 알지 못하도록하기 위해서라고 생각하지만, getThing()은 같은 클래스입니다!

이것은 정말 demeter의 법칙을 어긴 것입니까? 이게 정말 개선되는 디자인인가요?

감사합니다.

답변

0

기술적으로 이것은 Demeter의 법칙을 위반하는 것입니다. 비록 내가 개인적인 기능이 LoD-F를 고려해야한다고 주장 하겠지만, 외부에서는 접근 할 수없는 것으로 추정됩니다. 동시에 '물건'이 테스트의 소유이면 Demeter의 법칙을 어 기지 않는 것은 아닙니다. 하지만 자바에서는 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의 기능이 물건을 조작하기 위해 중개자가 아닌 물건을 생산하거나 노출하는 것이 가능한 경우 가능합니다.

+0

Thing이 그걸 처리하는 방법을 폭로한다는 것은 무엇을 의미합니까? Thing이'doSomething()'을 노출하고 있기 때문입니다. 그 외에는 추가 방법을 추가해야한다고 제안하는 것 같습니다. 권리? – superjugy

+0

죄송합니다. 직접 조작 및/또는 오버로딩을 제안하므로 더 깔끔하게 보입니다. –

+0

여기에있는 것은 실제로 Thing이 실제로 인터페이스이고 getThing이 실제 클래스를 인스턴스화한다는 것입니다. 그러나 사물은 시험 안에서만 사적으로 사용됩니다. 나는 그것을 반영하려고하는 질문을 업데이트 할 것이다. – superjugy

0

IntelliJ가 개체 인스턴스화를 올바르게 감지하지 못합니다.

위키 피 디아 (IDEA가 링크하는 것)는 현재 컨텍스트에서 생성 된 개체를 호출 할 수 있음을 설명합니다.

Version version = Loader.readVersion(inputStream); // Instantiates a new Version 

if (version.getMajor() != 2) 
    throw new IOException("Only major version 2 is supported"); 

IDEA의 검사 '라이브러리'메소드 호출을 무시하는 옵션을 제공합니다 : 내가 뭘,하지만 아직도 내가 getMajor()에 경고를

. 필자의 경우 이지만 현재 프로젝트 안에 있습니다 (프로젝트는 자체 지원해야 함). IDEA는 그것이 도서관 방법이 아니라고 생각합니다.

이 검사의 메커니즘은 순진/완전/불충분하기 때문에, 유일한 해결책은 그것을 해제하고 수동으로 이러한 상황을 피하려고한다 (BTW IDEA의 검사 많은와 같은).

+0

글쎄, 내 예제에서는 인스턴스가 만들어지고 동일한 클래스에서 사용되었습니다. 귀하의 경우에는 클래스 외부에 인스턴스를 작성하고 있습니다. 그러나 나는 동의한다. 또한 의존성 인젝터를 사용하려는 경우 인젝터가 필요한 객체의 생성 된 인스턴스를 제공하므로 항상 발생합니다. 나는이 수표를 사용 중지했다. – superjugy