두 가지 Java 8 기본 메소드를 서로 구현하는 것이 좋습니다.


14

다음과 비슷한 두 가지 관련 방법으로 인터페이스를 설계하고 있습니다.

public interface ThingComputer {
    default Thing computeFirstThing() {
        return computeAllThings().get(0);
    }

    default List<Thing> computeAllThings() {
        return ImmutableList.of(computeFirstThing());
    }
}

구현의 약 절반은 한 가지만 계산하는 반면 나머지 절반은 더 많은 것을 계산할 수 있습니다.

이것은 널리 사용되는 Java 8 코드에서 전례가 있습니까? Haskell이 일부 유형 클래스에서 유사한 작업을 수행한다는 것을 알고 있습니다 ( Eq예 :) .

단점은 두 개의 추상 클래스 ( SingleThingComputerMultipleThingComputer)를 사용하는 것보다 훨씬 적은 코드를 작성해야한다는 것 입니다.

단점은 빈 구현이 컴파일되지만 런타임에서을 사용하여 폭발한다는 것 StackOverflowError입니다. a로 상호 재귀를 감지하고 ThreadLocal더 좋은 오류를 줄 수는 있지만 버그가없는 코드에 오버 헤드가 추가됩니다.


3
무한 재귀를 보장하는 코드를 의도적으로 작성하는 이유는 무엇입니까? 그로부터 좋은 것은 없습니다.

1
글쎄요. "보장"은 아닙니다. 적절한 구현은 이러한 방법 중 하나를 무시합니다.
Tavian Barnes

6
당신은 그것을 모른다. 클래스 또는 인터페이스는 자체적으로 독립해야하며 서브 클래스가 중대한 논리 오류를 피하기 위해 특정 방법을 수행한다고 가정하지 않아야합니다. 그렇지 않으면 부서지기 쉬우 며 보장 할 수 없습니다. 인터페이스가 구현 클래스를 수행 throw new Error();하거나 어리석은 것을 강요 할 수 있거나 강요해야한다고 말하지 는 않으며 인터페이스 자체default메소드를 통해 취성 계약을 맺지 않아야 합니다.

@Snowman에 동의합니다. 지뢰입니다. 나는 그것의 교과서 존 소총 수단한다는 의미에서 '악의 코드 "생각 - 악마가 동일하지 않습니다 나쁜 , 그것은 악인의 / 영리 /의 유혹하지만, 여전히 잘못된 :) 내가 추천 youtu.be/lGbQiguuUGc?t=15m26s을 ( 또는 더 넓은 맥락에 대한 전체 대화-매우 흥미 롭습니다).
Konrad Morawski 2016 년

1
각 함수가 다른 함수로 정의 될 수 있다고해서 둘 다 서로의 용어로 정의 될 수 있다는 것을 의미하지는 않습니다 . 그것은 어떤 언어로도 날지 않습니다. 두 개의 추상 상속자가있는 인터페이스가 필요합니다. 각각은 다른 하나의 측면에서 하나를 구현하지만 다른 것은 추상적으로 구현하므로 올바른 추상 클래스에서 상속하여 구현하려는 측면을 선택하십시오. 한쪽은 다른 쪽과 독립적으로 정의되어야합니다 . 그렇지 않으면 pop은 스택으로갑니다 . 당신은 당신을 위해 문제를 해결할 구현을 추정 미친 기본값을 가지고 abstract할 수있는 강제 를 해결하도록.
Jimmy Hoffa 2016 년

답변:


16

TL; DR :이 작업을 수행하지 마십시오.

여기에 표시되는 것은 취성 코드입니다.

인터페이스는 계약입니다. "어떤 개체를 얻든지 관계없이 X와 Y를 수행 할 수 있습니다." 이 기록되면, 귀하의 인터페이스는 수행 가 있기 때문에 X도 Y 보장 스택 오버 플로우를 야기 할 수 있습니다.

오류 또는 서브 클래스를 던지면 심각한 오류가 발생하지 않았 음을 나타냅니다.

Error는 합리적인 응용 프로그램이 포착하려고하지 않아야하는 심각한 문제를 나타내는 Throwable의 하위 클래스입니다.

또한 StackOverflowError 의 상위 클래스 인 VirtualMachineError 는 다음과 같이 말합니다.

JVM (Java Virtual Machine)이 손상되었거나 계속 작동하는 데 필요한 자원이 부족함을 나타냅니다.

프로그램은 JVM 자원과 관련이 없어야합니다 . 이것이 JVM의 일입니다. 정상 조작의 일부로 JVM 오류를 발생시키는 프로그램을 작성하는 것은 좋지 않습니다. 프로그램이 중단되거나이 인터페이스의 사용자가 걱정하지 않아야 할 오류를 잡도록 강요합니다.


Eric Lippert 는 "C # 언어 디자인위원회 회원"이라는 명예와 같은 노력을 통해 알 수 있습니다 . 그는 사람들을 성공 또는 실패로 이끄는 언어 기능에 대해 이야기합니다. 언어 기능이나 언어 디자인의 일부는 아니지만 인터페이스 구현이나 객체 사용과 관련하여 그의 요점도 똑같이 유효합니다.

웨슬리가 깨어 났을 때 절망적 인 알비노와 불길한 여섯 손가락의 남자 루겐 백작과 함께 절망의 구덩이에 갇힌 것을 발견했을 때 공주 신부에서 기억하십니까? 절망의 구덩이의 기본 아이디어는 두 가지입니다. 첫째, 그것은 구덩이이므로 빠지기 쉽지만 어려운 작업이 아닙니다. 둘째, 절망을 유발합니다. 따라서 이름입니다.

출처 : C ++와 절망의 구덩이

StackOverflowError기본적으로 인터페이스를 사용하면 개발자가 절망의 구덩이에 빠지게되고 나쁜 생각 입니다. 대신 개발자를 성공구덩이로 밀어 넣으십시오 . 이 확인 쉽고 정확하고 JVM이 충돌하지 않고 인터페이스를 사용 할 수 있습니다.

메소드 간 위임은 여기에서 좋습니다. 그러나 종속성은 한 방향으로 진행되어야합니다. 나는 메서드 위임을 직접 그래프 처럼 생각하고 싶다 . 각 방법은 그래프의 노드입니다. 메소드가 다른 메소드를 호출 할 때마다 호출 메소드에서 호출 된 메소드로 에지를 그립니다.

그래프를 그리면서 주기적으로 나타나는 경우 코드 냄새가납니다. 그것은 절망의 구덩이에서 개발자들을 밀어 낼 수있는 잠재력입니다. 범주 적으로 금지되어서는 안되며 주의해야합니다 . 재귀 알고리즘은 특히 호출 그래프에주기를 갖습니다. 문서화하고 개발자에게 경고하십시오. 재귀 적이 지 않으면 해당주기를 중단하십시오. 당신이 할 수 없다면, 어떤 입력이 스택 오버플로를 일으킬 수 있는지 알아 내고 그것을 완화 시키거나 다른 것이 작동하지 않으면 그것을 마지막으로 문서화하십시오.


좋은 대답입니다. 왜 이것이 Haskell에서 그렇게 일반적인 관행인지 궁금합니다. 내가 생각하는 다른 개발 문화.
Tavian Barnes 2016

나는 Haskell에 경험이 없으며 이것이 함수형 프로그래밍에서 더 많은 이유나 이유에 대해 말할 수 없습니다.

조금 더 살펴보면, Haskell 커뮤니티는 그다지 행복하지 않은 것 같습니다. 또한 컴파일러는 최근에 "최소 완전한 정의"를 확인하는 법을 배웠으므로 빈 구현은 적어도 경고를 생성합니다.
Tavian Barnes

1
대부분의 기능적 프로그래밍 언어에는 테일 콜 최적화 기능이 있습니다. 이 최적화를 사용하면 테일 재귀가 스택을 날려 버리지 않으므로 이러한 방법이 적합합니다.
Jason Yeo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.