태그 보관물: class-design

class-design

객체의 상태가 유효하지 않은 경우 getter에서 예외가 발생해야합니까? getCompleteName() {return name + ” ” +

일반적인 OOP 문제라고 생각하더라도 특히 Java 에서이 문제가 자주 발생합니다. 즉, 예외를 발생 시키면 디자인 문제가 드러납니다.

String name필드와 필드 가있는 클래스가 있다고 가정하십시오 String surname.

그런 다음 해당 필드를 사용하여 인보이스와 같은 일종의 문서에 표시하기 위해 사람의 완전한 이름을 작성합니다.

public void String name;
public void String surname;

public String getCompleteName() {return name + " " + surname;}

public void displayCompleteNameOnInvoice() {
    String completeName = getCompleteName();
    //do something with it....
}

이제 displayCompleteNameOnInvoice이름을 지정하기 전에 호출 하면 오류가 발생하여 클래스의 동작을 강화하고 싶습니다 . 좋은 생각 같지 않습니까?

getCompleteName메소드에 예외 발생 코드를 추가 할 수 있습니다 . 그러나 이런 식으로 나는 클래스 사용자와의 ‘암시 적’계약을 위반하고 있습니다. 일반적으로 게터는 값을 설정하지 않으면 예외를 throw하지 않습니다. 좋아, 이것은 단일 필드를 반환하지 않기 때문에 표준 게터가 아니지만 사용자 관점에서 구별하기가 너무 미묘 할 수 있습니다.

또는 에서 내부에서 예외를 던질 수 있습니다 displayCompleteNameOnInvoice. 그러나 그렇게하려면 직접 name또는 surname필드를 테스트해야하며로 표현하는 추상화를 위반합니다 getCompleteName. 완전한 이름을 확인하고 작성하는 것은이 방법의 책임입니다. 다른 데이터를 기반으로 한 결정으로 일부 경우에 충분하다고 결정할 수도 surname있습니다.

그래서 유일한 가능성이 방법의 의미를 변경하는 것 getCompleteName까지 composeCompleteName, 그것보다 ‘적극적인’행동과, 예외를 던지는 능력이 있음을 의미합니다.

이것이 더 나은 디자인 솔루션입니까? 나는 항상 단순성과 정확성 사이의 최상의 균형을 찾고 있습니다. 이 문제에 대한 디자인 참조가 있습니까?



답변

이름을 지정하지 않고 수업을 구성하지 마십시오.


답변

DeadMG가 제공 한 답변은 거의 손톱을 깎지 만 조금 다르게 표현 해 보겠습니다. 상태가 잘못된 객체는 피하십시오. 개체는 수행하는 작업의 맥락에서 “전체”이어야합니다. 또는 존재하지 않아야합니다.

유동성을 원한다면 Builder Pattern 과 같은 것을 사용하십시오 . 또는 “실제”와 대조적으로 구성중인 개체를 개별적으로 구체화하는 다른 것 getCompleteName.


답변

상태가 잘못된 개체가 없습니다.

생성자 또는 빌더의 목적은 오브젝트의 상태를 일관되고 사용 가능한 것으로 설정하는 것입니다. 이 보증이 없으면 개체의 상태가 잘못 초기화되어 문제가 발생합니다. 이 문제는 동시성을 처리하고 개체 설정을 완료하기 전에 개체에 액세스 할 수있는 경우 더욱 복잡해집니다.

따라서이 부분에 대한 질문은 “이름이나 성을 null로 허용하는 이유는 무엇입니까?”입니다. 그것이 제대로 작동하기 위해 클래스에서 유효한 것이 아닌 경우 허용하지 마십시오. 객체의 생성을 올바르게 검증하는 생성자 또는 작성기를 보유하고 옳지 않은 경우 해당 시점에서 문제를 제기하십시오. 존재 하는 @NotNull주석 중 하나를 사용하여 “널이 될 수 없음”을 알리고 코딩 및 분석에 적용 할 수 있습니다.

이러한 보장을 통해 코드에 대해 추론하고 코드의 기능을 쉽게 파악할 수 있으며 홀수 위치에서 예외를 발생 시키거나 getter 함수를 과도하게 검사 할 필요가 없습니다.

더 많은 게터.

이 주제에 대해서는 약간의 내용이 있습니다. 당신이있어 게터에 얼마나 많은 논리어떻게 getter 및 setter 내에서 허용되어야 하는가? 여기 에서 스택 오버플로에서 추가 논리수행하는 게터 및 세터 . 이것은 클래스 디자인에서 계속해서 발생하는 문제입니다.

이것의 핵심은 다음과 같습니다.

일반적으로 게터는 값을 설정하지 않으면 예외를 throw하지 않아야합니다.

그리고 당신 말이 맞아요 그들은해서는 안됩니다. 그들은 세계의 다른 사람들에게 ‘멍청한’모습을 보여야하고 예상되는 일을해야합니다. 거기에 너무 많은 논리를 넣으면 가장 놀랍게도 법을 위반하는 문제가 발생합니다. 그리고 try catch우리가 일반적으로하는 것을 얼마나 많이 알고 있기 때문에 게터를 감싸고 싶지는 않습니다 .

거기 상황 또한 있어야 용도 getFoo등의 자바 빈즈 프레임 워크로 방법은 당신이 뭔가를 할 때 EL 있도록 (빈을 얻을 것으로 예상 호출 <% bar.foo %>실제로 호출 getFoo()클래스에 – (가) ‘빈이 구성을 수행하거나해야한다 따로 설정 어느 쪽이든 다른 쪽이 분명히 정답이 될 수있는 상황을 쉽게 생각 해낼 수 있기 때문입니다.)

또한 주어진 getter가 인터페이스에 지정되거나 리팩토링되는 클래스에 대해 이전에 공개 된 공개 API의 일부일 수 있음을 인식하십시오 (이전 버전에는 ‘completeName’이 리턴되었고 리팩토링이 중단되었습니다) 두 필드로).

하루의 끝에서…

추론하기 가장 쉬운 것을하십시오. 이 코드를 설계하는 것보다이 코드를 유지하는 데 더 많은 시간을 할애 할 것입니다 (디자인에 소요되는 시간이 적을수록 유지 관리에 더 많은 시간을 할애합니다). 이상적인 선택은 유지하기 위해 많은 시간이 소요되지 않는 방법으로 그것을 설계,하지만 일 동안 그것에 대해 생각하고 거기에 앉아하지 않는 것입니다 중 하나 -이 정말 디자인 선택하지 않는 것입니다 나중에 의미의 일을 가지고는 .

게터의 의미 적 순결을 고수하려고하면 private T foo; T getFoo() { return foo; }어떤 시점에서 문제 가 생길 수 있습니다. 때로는 코드가 해당 모델에 맞지 않고 그 방식으로 유지하려고 시도하는 변형이 의미가 없습니다 … 결국 디자인하기가 더 어려워집니다.

코드에서 원하는 방식으로 디자인의 이상을 실현할 수없는 경우가 있습니다. 지침은 족쇄가 아닌 지침입니다.


답변

나는 자바 사람이 아니지만 이것은 당신이 제시 한 두 가지 제약 조건을 모두 준수하는 것 같습니다.

getCompleteName이름이 초기화되지 않은 경우 예외가 발생 displayCompleteNameOnInvoice하지 않습니다.

public String getCompleteName()
{
    if (name == null || surname == null)
    {
        return null;
    }
    return name + " " + surname;
}

public void displayCompleteNameOnInvoice()
{
    String completeName = getCompleteName();
    if (completeName == null)
    {
        //throw an exception.
    }
    //do something with it....
}

답변

귀하의 질문에 아무도 대답하지 않는 것 같습니다.
사람들이 믿고 싶어하는 것과 달리, “유효하지 않은 객체를 피하는” 것은 종종 실용적인 해결책이 아닙니다.

정답은:

그렇습니다.

쉬운 예 : FileStream.LengthC # / .NETNotSupportedException 에서 파일을 찾을 수 없으면 던집니다 .


답변

당신은 전체 확인 이름을 거꾸로 가지고 있습니다.

getCompleteName()어떤 기능을 사용하는지 알 필요가 없습니다. 따라서 name전화를 거는 displayCompleteNameOnInvoice()것은 getCompleteName()책임 이 없습니다 .

그러나에 name대한 명확한 전제 조건입니다 displayCompleteNameOnInvoice(). 따라서 상태를 확인해야 할 책임이 있습니다 (또는 원하는 경우 다른 방법으로 확인 책임을 위임 해야 함 ).


답변