모든 클래스 속성을 가진 생성자입니까, 아니면 setter를 가진 기본 생성자입니까?

StackOverflow https://stackoverflow.com/questions/830657

  •  06-07-2019
  •  | 
  •  

문제

다음은 두 가지 접근 방식입니다.

  • 모든 클래스 속성을 가진 생성자

장점:정확한 개수의 매개변수 유형을 입력해야 하므로 오류가 발생하면 컴파일러에서 경고합니다. (그런데 매개변수 목록에서 두 개의 Integer를 실수로 전환하는 문제를 방지할 수 있는 방법이 있습니까?)

단점:속성이 많으면 인스턴스화 줄이 너무 길어지고 두 개 이상의 줄에 걸쳐 있을 수 있습니다.

  • setter 및 기본 빈 생성자

장점:내가 무엇을 설정하고 있는지 명확하게 알 수 있으므로 뭔가 잘못하고 있는 경우 입력하자마자 바로 찾아낼 수 있습니다. (같은 유형의 두 변수를 전환하는 이전 오류를 범할 수 없습니다.)

단점:많은 속성을 가진 개체의 인스턴스화에는 여러 줄이 필요할 수 있으며(이것이 실제로 사기인지는 알 수 없음) 속성 설정을 잊어버린 경우 컴파일러는 아무 말도 하지 않습니다.

무엇을 할 것이며 그 이유는 무엇입니까?제안할 조명 패턴(7개 이상의 속성을 가진 개체가 인스턴스화될 때마다 사용해야 한다는 점을 고려)에 대해 알고 계십니까?나는 내가 찾고 있는 변수가 어디에 있는지 빨리 알아낼 수 없는 대형 생성자를 싫어하는 경향이 있기 때문에 이것을 묻는 것입니다. 반면에 "모든 속성 설정"은 일부 속성이 누락될 수 있다는 것을 알았습니다.

제 생각일 뿐이므로 장단점을 자유롭게 주장해 보세요 :)

업데이트 - 이와 관련된 질문을 찾았습니다. 긴 매개변수 목록이 있는 생성자를 사용하지 않고 크고 불변하는 객체 구축

도움이 되었습니까?

해결책

Joshua Bloch가 옹호하고 설명된 빌더 패턴을 볼 수 있습니다. 효과적인 자바.주요 내용을 담은 프레젠테이션이 있습니다. http://developers.sun.com/learning/javaoneonline/2007/pdf/TS-2689.pdf;의심할 바 없이 더 나은 참고 자료를 찾아볼 수 있을 것입니다.

기본적으로 설정되는 속성의 이름을 딴 메서드를 제공하고 호출을 연결할 수 있도록 원래 빌더를 반환하는 내부 클래스와 같은 또 다른 클래스가 있습니다.이는 꽤 읽기 쉬운 코드 덩어리를 만듭니다.

예를 들어, 내가 간단한 Message 몇 가지 속성이 있습니다.이를 구성하는 클라이언트 코드는 빌더를 사용하여 Message 다음과 같이:

Message message = new Message.Builder()
    .sender( new User( ... ) )
    .recipient( new User( ... ) )
    .subject( "Hello, world!" )
    .text( messageText )
    .build();

의 단편 Message.Builder 다음과 유사할 수 있습니다.

public class Builder {

    private User sender = null;
    // Other properties

    public Builder sender( User sender ) {
        this.sender = sender;
        return this;
    }
    // Methods for other properties

    public Message build() {
        Message message = new Message();
        message.setSender( sender );
        // Set the other properties
        return message;
    }

}

다른 팁

매개변수가 많은 생성자를 갖는 가장 큰 이점을 놓쳤습니다.불변 유형을 생성할 수 있습니다.

불변 유형을 생성하는 일반적인 방법 없이 거대한 생성자 불쾌함은 도우미 유형을 갖는 것입니다. 건축업자 이는 최종 개체에서 원하는 값을 유지한 다음 준비가 되면 변경할 수 없는 개체를 만듭니다.

API 유용성에 대한 최근 학술 연구(CMU 및 Microsoft)에서는 setter가 있는 기본 생성자가 유용성 측면에서 좋은 방법이라고 제안합니다.이것은 Jeff Stylos와 Steven Clarke가 쓴 "객체 생성자에서 매개변수 요구의 유용성 함의"에서 발췌한 것이며 소프트웨어 엔지니어링 국제 회의에서 발표되었습니다.

추상적인:API의 유용성은 프로그래머 생산성에 점점 더 중요해지고 있습니다.특정 API의 유용성 연구 경험을 바탕으로 많은 API에 공통적인 디자인 선택의 유용성을 연구하기 위한 기술을 탐구했습니다.매개변수가 없는 "기본" 생성자와 달리 전문 프로그래머가 개체 생성자에서 필수 매개변수가 있는 API를 사용하는 방법을 평가하기 위해 비교 연구가 수행되었습니다.필수 매개변수는 프로그래머에게 객체의 올바른 사용을 안내하고 오류를 방지함으로써 더 유용하고 자체 문서화되는 API를 생성할 것이라는 가설이 세워졌습니다.그러나 연구 결과, 예상과는 달리 프로그래머들은 생성자 매개변수가 필요하지 않은 API를 훨씬 더 선호하고 더 효과적인 것으로 나타났습니다.참가자의 행동은 인지 차원 프레임워크를 사용하여 분석되었으며 필수 생성자 매개변수가 일반적인 학습 전략을 방해하여 바람직하지 않은 조기 몰입을 유발한다는 사실이 밝혀졌습니다.

귀하의 게시물에서 이에 대해 언급하셨지만, 저는 이것이 더 주목받아야 할 중요한 사항이라고 생각합니다.모든 입력 매개변수가 다른 유형이 아닌 한, 거대한 생성자의 가장 큰 문제는 매우 몇 가지 변수를 쉽게 바꿀 수 있습니다.컴파일러는 신뢰할 수 없는 안전망입니다. 일부 실수는 잡아내지만, 빠져나가는 실수는 식별하고 디버깅하기가 훨씬 더 어렵습니다.특히 다른 창에서 API를 열지 않는 한 거대한 생성자의 입력 목록이 상당히 불투명하기 때문입니다.

Getter 및 Setter는 디버깅하기가 훨씬 쉽습니다. 특히 개체가 제대로 채워지지 않은 경우 런타임 예외를 발생시키는 보호 장치를 설치하는 경우 더욱 그렇습니다.그리고 저는 "디버깅하기 쉽다"는 점을 매우 좋아합니다.

이 스레드 이전에는 Rob이 언급한 빌더 패턴에 대해 들어본 적이 없습니다.(분명히) 직접 사용해본 적은 없지만 정말 흥미롭습니다.

나는 앞서 언급한 불변성 때문에 생성자 인수를 사용하는 것을 선호합니다.그것이 많은 인수(예를 들어 4개 이상)를 취하는 생성자를 제공한다면 그것은 나에게 코드 냄새입니다.이러한 인수 중 일부는 자체 유형으로 함께 묶어야 합니다.

예를 들어, 다음과 같은 것이 있다면:

class Contact
{
    public Contact(string firstName, string lastName, string phoneNumber,
        string street, string city, string state, int zipCode) { ... }
}

나는 그것을 다음과 같이 리팩토링하겠습니다.

class Contact
{
    public Contact(Person person, PhoneNumber number, Address address) { ... }
}

class Person
{
    public Person(string firstName, string lastName) { ... }
}

class PhoneNumber
{
    public PhoneNumber(string digits) { ... }
}

class Address
{
    public Address(string street, string city, string state, int zipCode) { ... }
}

너무 큰 클래스는 OOP 코드베이스에서 매우 일반적인 디자인 문제입니다.

다른 측면도 있습니다.런타임이 아닌 디자인 타임에 클래스를 사용하여 특정 작업을 수행할 수 있으려면(예를 들어 클래스를 개체 팔레트(Netbeans를 사용하는 Java)에 개체로 추가하는 경우) 인수 없는 생성자를 제공해야 합니다. 그렇게 할 수 있도록 말이죠.

여기에는 다른 전략도 있습니다.많은 매개변수를 처리하는 방법을 파악하기 전에 디자인을 다시 방문하여 수업이 너무 많은 일을 하고 있는지 살펴보는 것이 중요하다고 생각합니다.일부 매개변수를 새 클래스로 그룹화하고 일부 동작을 해당 클래스로 이동할 수 있는지 확인하세요.

setter 및 기본 빈 생성자

JRL이 비스듬히 만졌어, 하지만 setter 사용을 고려하는 한 가지 이유는 객체가 자바빈즈 사양.이는 인스턴스를 다음과 같은 사항에 적합하게 만듭니다. 편집 내성 도구와 특정 도구를 사용한 지속성을 통해 직렬화 기술.

둘 다 할 수 없다고 누가 말했나요?필수 속성은 생성자에 들어가고 선택 속성은 setter로 처리됩니다.그런데, 누가 항상 속성당 하나의 세터가 필요하다고 말했습니까?두 속성이 개념적으로 함께 속해 있다면 함께 설정해 ​​보는 것은 어떨까요?

저는 Builder 패턴도 좋아하지만 가장 중요한 규칙은 다음과 같습니다.항상 두뇌를 사용하여 특정 문제에 가장 적합한 디자인을 찾으십시오.모든 경우에 적용되는 단일 솔루션은 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top