좋은 습관입니까? 게터에서 객체 초기화


167

동료에 따르면 적어도 이상한 습관이 있습니다. 우리는 작은 프로젝트를 함께 진행하고 있습니다. 내가 수업을 쓴 방법은 (단순화 된 예)입니다.

[Serializable()]
public class Foo
{
    public Foo()
    { }

    private Bar _bar;

    public Bar Bar
    {
        get
        {
            if (_bar == null)
                _bar = new Bar();

            return _bar;
        }
        set { _bar = value; }
    }
}

따라서 기본적으로 getter가 호출되고 필드가 여전히 null 일 때만 필드를 초기화합니다. 어디서나 사용되지 않는 속성을 초기화하지 않으면 과부하가 줄어 듭니다.

ETA : 내가 한 이유는 내 클래스에 다른 클래스의 인스턴스를 반환하는 여러 속성이 있기 때문에 더 많은 클래스가있는 속성도 있습니다. 최상위 클래스의 생성자를 호출하면 나중에이 클래스가 아닌 모든 클래스의 모든 생성자를 호출합니다. 항상 필요한 아니지만 모든 합니다.

개인적 취향 외에이 관행에 대한 반대 의견이 있습니까?

업데이트 : 나는이 질문에 관해 많은 다른 의견을 고려했으며 받아 들인 대답을 기다릴 것입니다. 그러나 이제는 개념에 대해 훨씬 더 잘 이해하게되었으며 사용시기와 사용하지 않을시기를 결정할 수 있습니다.

단점 :

  • 스레드 안전 문제
  • 전달 된 값이 null 일 때 "세터"요청을 따르지 않음
  • 마이크로 최적화
  • 예외 처리는 생성자에서 발생해야합니다
  • 클래스 코드에서 null을 확인해야합니다.

장점 :

  • 마이크로 최적화
  • 속성은 null을 반환하지 않습니다
  • "무거운"오브젝트로드 지연 또는 방지

대부분의 단점은 현재 라이브러리에 적용 할 수 없지만 "마이크로 최적화"가 실제로 어떤 것을 최적화하고 있는지 테스트해야합니다.

마지막 업데이트:

좋아, 나는 대답을 바꿨다. 내 원래의 질문은 이것이 좋은 습관인지 아닌지였습니다. 그리고 나는 그것이 아니라고 확신합니다. 어쩌면 나는 현재 코드의 일부 부분에서 여전히 사용하지만 무조건적이고 확실하지는 않습니다. 그래서 나는 습관을 잃고 그것을 사용하기 전에 그것에 대해 생각할 것입니다. 모두 감사합니다!


14
이것은 게으른로드 패턴으로, 여기에 훌륭한 이점을 제공하지는 않지만 여전히 좋은 점입니다.
Machinarius

28
게으른 인스턴스화는 성능에 상당한 영향을 미치거나 해당 멤버가 거의 사용되지 않고 엄청난 양의 메모리를 소비하지 않거나 인스턴스화하는 데 시간이 오래 걸리고 필요할 때만 수행하려는 경우에 의미가 있습니다. 여하튼 스레드 안전 문제 (현재 코드가 아님 )를 설명하고 제공된 Lazy <T> 클래스 사용을 고려하십시오 .
Chris Sinclair

10
나는에 더 나은이 질문에 맞는 생각 codereview.stackexchange.com
에두아르도 Brites

7
@PLB 싱글 톤 패턴이 아닙니다.
Colin Mackay

30
아무도이 코드에 심각한 버그를 언급하지 않은 것에 놀랐습니다. 외부에서 설정할 수있는 공공 재산이 있습니다. NULL로 설정하면 항상 새 객체를 만들고 내 setter 액세스를 무시합니다. 이것은 매우 심각한 버그 일 수 있습니다. 개인 재산의 경우 okie 일 수 있습니다. 개인적으로, 나는 그러한 조기 최적화를 좋아하지 않습니다. 추가 혜택없이 복잡성을 추가합니다.
SolutionYogi

답변:


170

여기에 "게으른 초기화"의 순진한 구현이 있습니다.

짧은 답변:

지연 초기화를 무조건 사용 하는 것은 좋은 생각이 아닙니다. 그것은 그 자리를 가지고 있지만이 솔루션의 영향을 고려해야합니다.

배경과 설명 :

구체적 구현 :
먼저 구체적인 샘플을 살펴보고 구현 순진한 이유를 살펴 보겠습니다.

  1. 그것은 최소한의 서프라이즈 원칙 (POLS)을 위반합니다 . 값이 속성에 할당되면이 값이 반환 될 것으로 예상됩니다. 귀하의 구현에서는 다음과 같은 경우가 아닙니다 null.

    foo.Bar = null;
    Assert.Null(foo.Bar); // This will fail
  2. 스레딩 문제가 많이 발생합니다. foo.Bar다른 스레드 의 두 호출자 는 잠재적으로 두 개의 다른 인스턴스를 얻을 수 Bar있으며 그 중 하나는 인스턴스에 연결되지 않습니다 Foo. 해당 Bar인스턴스에 대한 모든 변경 사항 은 자동으로 손실됩니다.
    이것은 POLS 위반의 또 다른 경우입니다. 속성의 저장된 값만 액세스하면 스레드로부터 안전해야합니다. 클래스가 단순히 스레드 안전하지 않다고 주장 할 수는 있지만 속성의 getter를 포함하여 일반적인 경우가 아니라는 것을 올바르게 문서화해야합니다. 또한 우리가 곧 보게 되겠지만이 문제의 도입은 불필요하다.

일반적으로 :
이제는 초기화 지연을 살펴볼 차례입니다.
지연 초기화는 일반적으로 구성 하는 데 시간이 오래 걸리거나 완전히 구성된 후 많은 메모리를 사용하는 개체의 구성을 지연시키는 데 사용됩니다 .
이것이 게으른 초기화를 사용하는 매우 유효한 이유입니다.

그러나 이러한 속성에는 일반적으로 세터가 없으므로 위에서 지적한 첫 번째 문제를 제거합니다.
또한 Lazy<T>두 번째 문제를 피하기 위해 스레드 안전 구현이 사용됩니다 .

게으른 속성을 구현할 때이 두 가지 사항을 고려하더라도이 패턴의 일반적인 문제는 다음과 같습니다.

  1. 객체 생성에 실패하여 속성 getter에서 예외가 발생할 수 있습니다. 이것은 POLS에 대한 또 다른 위반이므로 피해야합니다. "클래스 라이브러리 개발을위한 디자인 지침"의 속성 섹션 에서도 속성 게터가 예외를 발생시키지 않아야한다고 명시하고 있습니다.

    속성 게터에서 예외를 발생시키지 마십시오.

    속성 게터는 사전 조건이없는 간단한 작업이어야합니다. getter가 예외를 throw 할 수있는 경우 특성을 메소드로 재 설계하는 것이 좋습니다.

  2. 컴파일러에 의한 자동 최적화, 즉 인라인 및 분기 예측이 손상됩니다. 자세한 설명 은 Bill K의 답변 을 참조하십시오 .

이러한 사항의 결론은 다음과 같습니다.
느리게 구현 된 각 단일 속성에 대해 이러한 사항을 고려해야합니다.
즉, 결정은 사례마다 다르며 일반적인 모범 사례로 간주 할 수 없습니다.

이 패턴은 그 자리에 있지만 클래스를 구현할 때 일반적인 모범 사례는 아닙니다. 위에 언급 한 이유 때문에 무조건 사용해서는 안됩니다 .


이 섹션에서는 다른 사람들이 지연 초기화를 무조건적으로 사용하기위한 인수로 제시 한 몇 가지 사항에 대해 논의하고자합니다.

  1. 직렬화 :
    EricJ는 한 의견에서 다음과 같이 말합니다.

    직렬화 될 수있는 객체는 직렬화 해제 될 때 생성자가 호출되지 않습니다 (직렬화기에 따라 다르지만 많은 일반 객체는 이와 같이 동작 함). 생성자에 초기화 코드를 넣으면 역 직렬화에 대한 추가 지원을 제공해야합니다. 이 패턴은 특별한 코딩을 피합니다.

    이 주장에는 몇 가지 문제가 있습니다.

    1. 대부분의 객체는 직렬화되지 않습니다. 필요하지 않을 때 지원을 추가하면 YAGNI를 위반 합니다 .
    2. 클래스가 직렬화를 지원해야 할 때 직렬화와 관련이없는 해결 방법없이 클래스를 활성화하는 방법이 있습니다.
  2. 미세 최적화 : 주된 논점은 누군가가 실제로 액세스 할 때만 오브젝트를 구성한다는 것입니다. 따라서 실제로 메모리 사용 최적화에 대해 이야기하고 있습니다.
    다음과 같은 이유로이 주장에 동의하지 않습니다.

    1. 대부분의 경우 메모리에 몇 개의 객체가 더 이상 영향을 미치지 않습니다. 최신 컴퓨터에는 충분한 메모리가 있습니다. 프로파일 러가 확인한 실제 문제가없는 경우 이는 조기 최적화 이므로 이에 대한 충분한 이유가 있습니다.
    2. 나는 때때로 이런 종류의 최적화가 정당하다는 사실을 인정한다. 그러나 이러한 경우에도 게으른 초기화는 올바른 해결책이 아닌 것 같습니다. 그것에 대해 말하는 두 가지 이유가 있습니다.

      1. 지연 초기화는 잠재적으로 성능을 저하시킵니다. 어쩌면 미미할 지 모르지만 Bill의 답변에서 알 수 있듯이 영향은 언뜻보기에 생각하는 것보다 큽니다. 따라서이 방법은 기본적으로 성능과 메모리를 교환합니다.
      2. 클래스의 일부만 사용하는 일반적인 유스 케이스 인 디자인이있는 경우 이는 디자인 자체의 문제점을 암시합니다. 문제의 클래스는 둘 이상의 책임이 있습니다. 해결책은 클래스를 몇 가지 더 집중된 클래스로 나누는 것입니다.

4
@ JohnWillemse : 아키텍처의 문제입니다. 더 작고 집중적 인 방식으로 수업을 리팩토링해야합니다. 5 가지 다른 작업 / 작업에 대해 하나의 클래스를 만들지 마십시오. 대신 5 개의 클래스를 작성하십시오.
Daniel Hilgarth

26
@JohnWillemse 아마도 이것이 조기 최적화의 경우라고 생각할 것입니다. 성능 / 메모리 병목 현상 이 측정 되지 않는 한 복잡성이 증가하고 스레딩 문제가 발생하므로 이에 대해 권장합니다.
Chris Sinclair

2
+1, 이것은 수업의 95 %에 적합한 디자인 선택이 아닙니다. 게으른 초기화에는 장점이 있지만 모든 속성에 대해 일반화해서는 안됩니다. 99 %의 경우에 최적화 할 수없는 복잡성, 코드 읽기 어려움, 스레드 안전성 문제 등을 추가합니다. 또한 SolutionYogi가 의견으로 말했듯이 OP의 코드는 버그가 많으 므로이 패턴이 구현하기가 쉽지 않으며 게으른 초기화가 실제로 필요하지 않는 한 피해야합니다.
ken2k

2
@DanielHilgarth이 패턴을 무조건적으로 사용하는 데있어 거의 모든 문제를 적어 두는 것에 감사드립니다. 잘 했어!
Alex

1
@DanielHilgarth 잘 그렇습니다. 위반은 여기서 문제이므로 그렇습니다. 그러나 POLS는 아마도 코드에 놀라지 않을 원칙이기 때문에 '아니오' 입니다. Foo가 프로그램 외부에 노출되지 않은 경우 취할 수있는 위험이 있습니다. 이 경우 속성에 액세스하는 방식을 제어하지 않기 때문에 결국 놀라게 될 것 입니다. 위험은 방금 버그 null가되었으며 사건 에 대한 귀하의 주장 은 훨씬 강력 해졌습니다. :-)
atlaste

49

좋은 디자인 선택입니다. 라이브러리 코드 또는 핵심 클래스에 강력히 권장됩니다.

"지연된 초기화"또는 "지연된 초기화"에 의해 호출되며 일반적으로 모두 좋은 디자인 선택으로 간주됩니다.

먼저 클래스 수준 변수 또는 생성자의 선언에서 초기화하면 객체가 생성 될 때 절대 사용할 수없는 리소스를 만드는 오버 헤드가 발생합니다.

둘째, 필요한 경우에만 리소스가 생성됩니다.

셋째, 사용되지 않은 객체를 가비지 수집하지 않도록합니다.

마지막으로, 속성에서 발생할 수있는 초기화 예외와 클래스 수준 변수 또는 생성자의 초기화 중에 발생하는 예외를 처리하는 것이 더 쉽습니다.

이 규칙에는 예외가 있습니다.

"get"속성에서 초기화에 대한 추가 검사의 성능 인수와 관련하여 중요하지 않습니다. 객체를 초기화하고 배치하는 것은 간단한 null 포인터 확인으로 점프하는 것보다 훨씬 중요한 성능 저하입니다.

디자인 지침 클래스 라이브러리 개발을위한 에서 http://msdn.microsoft.com/en-US/library/vstudio/ms229042.aspx

에 관해서 Lazy<T>

일반 Lazy<T>클래스는 포스터가 원하는대로 정확하게 작성되었습니다 . http://msdn.microsoft.com/en-us/library/dd997286(v=vs.100).aspx의 Lazy Initialization 을 참조 하십시오 . 이전 버전의 .NET을 사용하는 경우 질문에 설명 된 코드 패턴을 사용해야합니다. 이 코드 패턴은 매우 일반화되어 패턴을보다 쉽게 ​​구현할 수 있도록 최신 .NET 라이브러리에 클래스를 포함시키는 데 적합했습니다. 또한 구현에 스레드 안전성이 필요한 경우이를 추가해야합니다.

기본 데이터 유형 및 단순 클래스

명백히, 기본 데이터 유형이나 간단한 클래스 사용에 지연 초기화를 사용하지 않을 것 List<string>입니다.

Lazy에 대해 언급하기 전에

Lazy<T> .NET 4.0에 도입되었으므로이 클래스에 대한 또 다른 의견을 추가하지 마십시오.

마이크로 최적화에 대해 언급하기 전에

라이브러리를 구축 할 때는 모든 최적화를 고려해야합니다. 예를 들어, .NET 클래스에는 코드 전체에서 부울 클래스 변수에 사용되는 비트 배열이 표시되어 메모리 소비 및 메모리 조각화를 줄이고 두 개의 "마이크로 최적화"라고합니다.

사용자 인터페이스에 대하여

사용자 인터페이스에서 직접 사용하는 클래스에는 지연 초기화를 사용하지 않습니다. 지난 주에는 콤보 상자의 뷰 모델에 사용되는 8 개의 컬렉션을 지연 로딩하여 하루 중 더 좋은 시간을 보냈습니다. LookupManager사용자 인터페이스 요소에 필요한 컬렉션의 느린로드 및 캐싱을 처리 하는 을 가지고 있습니다 .

"세터"

게으른로드 된 속성에 대해 set-property ( "setters")를 사용한 적이 없습니다. 따라서을 허용하지 않습니다 foo.Bar = null;. 설정 해야하는 경우 lazy-initialization을 사용하지 않고 Bar라는 메소드를 작성합니다.SetBar(Bar value)

컬렉션

클래스 컬렉션 속성은 null이 아니 어서 선언 될 때 항상 초기화됩니다.

복잡한 수업

이것을 다르게 반복하겠습니다. 복잡한 클래스에는 지연 초기화를 사용합니다. 일반적으로 제대로 설계되지 않은 클래스입니다.

마지막으로

나는 모든 수업이나 모든 경우에 이것을하지 않았다. 나쁜 습관입니다.


6
값을 설정하지 않고 다른 스레드에서 foo.Bar를 여러 번 호출 할 수 있지만 다른 값을 얻으면 열악한 클래스가 있습니다.
Lie Ryan

25
나는 이것이 많은 고려가없는 나쁜 경험 법칙이라고 생각합니다. Bar가 알려진 자원 돼지가 아닌 한, 이것은 불필요한 마이크로 최적화입니다. Bar가 리소스를 많이 사용하는 경우 .net에 스레드 안전 Lazy <T>가 내장되어 있습니다.
Andrew Hanlon

10
"속성에서 발생할 수있는 초기화 예외와 클래스 수준 변수 또는 생성자의 초기화 중에 발생하는 예외를 처리하는 것이 더 쉽습니다." -이건 바보 야 어떤 이유로 객체를 초기화 할 수 없다면 최대한 빨리 알고 싶습니다. 즉, 그것이 구성되면 즉시. 게으른 초기화를 사용하는 것에 대한 좋은 주장이 있지만, 광범위 하게 사용하는 것이 좋은 생각은 아닙니다 .
millimoose 2013

20
다른 개발자 들이이 답변을보고 이것이 실제로 좋은 습관이라고 생각 할까 걱정됩니다 (오 소년). 무조건 사용하는 경우 이것은 매우 나쁜 습관입니다. 이미 말한 것 외에도 적은 이익을 얻으려면 모든 고객의 삶을 (고객 개발자와 유지 보수 개발자에게) 훨씬 더 어렵게 만들고 있습니다. 도널드 크 누스 (The Donald Knuth) 시리즈의 컴퓨터 프로그래밍 기술 (Art of Computer Programming) 시리즈는“미숙 한 최적화는 모든 악의 근원”이라고 말했다. 당신이하는 일은 악마 일뿐만 아니라 악마입니다!
Alex

4
틀린 답과 틀린 프로그래밍 결정을 선택하는 지표가 너무 많습니다. 당신은 당신의 목록에 찬성보다 더 많은 단점이 있습니다. 그보다 더 많은 사람들을 보증합니다. 이 질문에 게시 된이 사이트의보다 숙련 된 회원 (@BillK 및 @DanielHilgarth)은 이에 반대합니다. 동료가 이미 틀렸다고 말했습니다. 진심으로, 잘못되었습니다! 이 작업을 수행하는 팀 개발자 (팀 리더) 중 한 명을 잡으면 5 분의 시간 초과가 발생하고 왜 그렇게하지 않아야하는지 강의하게됩니다.
Alex

17

Lazy<T>?를 사용하여 이러한 패턴을 구현하는 것을 고려하고 있습니까?

지연로드 된 객체를 쉽게 만들 수있을뿐만 아니라 객체가 초기화되는 동안 스레드 안전성을 얻을 수 있습니다.

다른 사람들이 말했듯이 실제로 리소스가 많거나 객체 생성 시간 동안 객체를로드하는 데 시간이 걸리는 경우 지연로드하십시오.


고마워, 나는 지금 그것을 이해하고 나는 확실히 Lazy<T>지금 조사하고 , 내가 항상했던 방식을 사용하지 마십시오.
John Willemse 2013

1
당신은 마법 실 안전을 얻지 못합니다 ... 여전히 생각해야합니다. MSDN에서 :Making the Lazy<T> object thread safe does not protect the lazily initialized object. If multiple threads can access the lazily initialized object, you must make its properties and methods safe for multithreaded access.
Eric J.

@EricJ. 물론 이죠 객체를 초기화 할 때 스레드 안전성 만 확보하지만 나중에 다른 객체와의 동기화를 처리해야합니다.
Matías Fidemraizer

9

나는 그것이 당신이 초기화하는 것에 달려 있다고 생각합니다. 건설 비용이 상당히 적기 때문에 목록을 작성하지 않을 것이므로 생성자에 들어갈 수 있습니다. 그러나 그것이 미리 채워진 목록이라면 처음으로 필요할 때까지는 아마 없을 것입니다.

기본적으로 건설 비용이 각 액세스에 대해 조건부 검사를 수행하는 비용보다 큰 경우 게으른 생성합니다. 그렇지 않은 경우 생성자에서 수행하십시오.


감사합니다! 말이 되네요
John Willemse 2013

9

내가 볼 수있는 단점은 Bars가 null인지 묻기를 원한다면 결코 존재하지 않으며 거기에 목록을 작성한다는 것입니다.


나는 그것이 단점이라고 생각하지 않습니다.
피터 포피

왜 단점이 있습니까? null 대신 대신 확인하십시오. if (! Foo.Bars.Any ())
s.meijer 2013

6
@PeterPorfy : POLS를 위반 합니다 . 넣었 null지만 다시는 가져 오지 마십시오. 일반적으로 속성에 넣은 것과 같은 값을 얻는다고 가정합니다.
Daniel Hilgarth 2013

@DanielHilgarth 다시 감사합니다. 그것은 내가 전에 고려하지 않은 매우 유효한 주장입니다.
John Willemse 2013

6
@AMissico : 구성 개념이 아닙니다. 현관 옆에있는 버튼을 누르면 초인종이 울리는 것과 거의 같은 방식으로 속성처럼 보이는 것은 속성처럼 행동 할 것으로 예상됩니다. 발 아래에 트랩 도어를 열면 특히 단추에 레이블이없는 경우 놀라운 동작이 발생합니다.
Bryan Boettcher

8

게으른 인스턴스화 / 초기화는 완벽하게 실행 가능한 패턴입니다. 그러나 API의 일반적인 규칙으로서 게터와 세터가 최종 사용자 POV로부터 식별 가능한 시간을 갖거나 실패 할 것으로 예상하지 않습니다.


1
동의하며 질문을 약간 수정했습니다. 기본 생성자의 전체 체인은 클래스가 필요할 때만 인스턴스화하는 것보다 더 많은 시간이 걸릴 것으로 예상합니다.
John Willemse 2013

8

나는 다니엘의 대답에 대한 의견을 말하려고했지만 솔직히 그것이 충분하다고 생각하지 않습니다.

특정 상황 (예 : 데이터베이스에서 객체가 초기화 될 때)에서 사용하기에는 매우 좋은 패턴이지만, 들어가는 것은 나쁜 습관입니다.

개체의 가장 좋은 점 중 하나는 안전하고 신뢰할 수있는 환경을 제공한다는 것입니다. 가장 좋은 경우는 가능한 한 많은 필드를 "최종"으로 만들어 생성자로 채우는 것입니다. 이것은 당신의 수업을 방탄하게 만듭니다. setter를 통해 필드를 변경하는 것은 약간 덜하지만 끔찍한 것은 아닙니다. 예를 들어 :

SafeClass 클래스
{
    문자열 이름 = "";
    정수 연령 = 0;

    공공 무효 setName (문자열 newName)
    {
        assert (newName! = null)
        name = newName;
    } // 연령에 따라이 패턴을 따릅니다.
    ...
    공개 문자열 toString () {
        String s = "세이프 클래스는 이름 :"+ name + "및 연령 :"+ age입니다.
    }
}

패턴을 사용하면 toString 메소드는 다음과 같습니다.

    if (이름 == null)
        새로운 IllegalStateException을 던집니다 ( "SafeClass가 잘못된 상태가되었습니다! 이름이 null입니다").
    if (나이 == null)
        새로운 IllegalStateException을 던집니다 ( "SafeClass가 잘못된 상태가되었습니다! 나이가 null입니다").

    공개 문자열 toString () {
        String s = "세이프 클래스는 이름 :"+ name + "및 연령 :"+ age입니다.
    }

이뿐 만 아니라 클래스에서 해당 객체를 사용할 수있는 모든 곳에서 null 검사가 필요합니다 (게터의 null 검사로 인해 클래스 외부에서는 안전하지만 대부분 클래스 내부에서 클래스 멤버를 사용해야합니다)

또한 클래스가 불확실한 상태에 있습니다. 예를 들어 몇 가지 주석을 추가하여 해당 클래스를 최대 절전 모드 클래스로 설정 한 경우 어떻게해야합니까?

요구 사항과 테스트없이 일부 미세 광학 화를 기반으로 결정을 내리는 것은 거의 잘못된 결정입니다. 실제로 if 문이 CPU에서 분기 예측 실패를 일으켜서 여러 번 더 느려질 수 있기 때문에 가장 이상적인 상황에서도 패턴이 실제로 시스템 속도를 늦출 가능성이 매우 높습니다. 생성하는 객체가 상당히 복잡하거나 원격 데이터 소스에서 오는 경우가 아니면 생성자에 값을 할당하면됩니다.

brance 예측 문제의 예 (한 번도 반복적으로 발생하지 않음)는이 멋진 질문에 대한 첫 번째 답변을 참조하십시오 . 정렬되지 않은 배열보다 정렬 된 배열을 처리하는 것이 왜 더 빠릅니까?


입력 해 주셔서 감사합니다. 필자의 경우 클래스 중 어느 것도 null을 확인해야 할 메소드가 없으므로 문제가되지 않습니다. 다른 이의 제기를 고려하겠습니다.
John Willemse 2013

나는 그것을 정말로 이해하지 못한다. 이는 멤버가 저장된 클래스에서 멤버를 사용하지 않고 클래스를 데이터 구조로 사용하고 있음을 의미합니다. 이 경우 javaworld.com/javaworld/jw-01-2004/jw-0102-toolbox.html 을 읽으면 외부에서 객체 상태를 조작하지 않고 코드를 개선하는 방법에 대한 좋은 설명이 있습니다. 내부적으로 조작하는 경우 모든 것을 반복적으로 null 검사하지 않고 어떻게합니까?
Bill K

이 답변의 일부는 훌륭하지만 일부는 생각한 것 같습니다. 일반적으로이 패턴을 사용할 때는 직접 toString()호출 getName()하지 않고를 호출 name합니다.
이즈 카타

@BillK 예, 클래스는 거대한 데이터 구조입니다. 모든 작업은 정적 클래스에서 수행됩니다. 링크에서 기사를 확인하겠습니다. 감사!
John Willemse 2013

1
@izkata 실제로 수업 내에서 게터를 사용하는 날씨와 관련하여, 내가 일한 대부분의 장소가 회원을 직접 사용한 장소에 대해서는 버림받은 것 같습니다. 따로, 항상 getter를 사용하는 경우 분기 예측 실패가 더 자주 발생하고 분기로 인해 런타임이 getter를 인라인하는 데 더 많은 문제가 있기 때문에 if () 메소드는 훨씬 더 해 롭습니다. 그러나 데이터 구조와 정적 클래스라는 요한의 계시에 따르면 그것이 가장 우려되는 부분입니다.
Bill K

4

다른 사람들이 만든 많은 좋은 점에 하나의 점을 더 추가하겠습니다 ...

디버거는 ( 기본적으로 ) 코드를 단계별로 실행할 때 속성을 평가하므로 코드를 Bar실행하여 평상시보다 빨리 인스턴스화 할 수 있습니다. 다시 말해, 디버깅의 단순한 행동은 프로그램의 실행을 바꾸는 것입니다.

이것은 부작용에 따라 문제가 될 수도 있고 아닐 수도 있지만 알고 있어야합니다.


2

Foo가 무엇이든 인스턴스화해야합니까?

나에게 (반드시는 아니지만 냄새 나는 것 같다 잘못된 전혀 푸 인스턴스화 아무것도 수 있도록). Foo가 팩토리가되기위한 명시적인 목적이 아니라면, 그것은 자신의 공동 작업자를 인스턴스화하지 말고 대신 생성자에 주입해야합니다 .

그러나 Foo의 목적이 Bar 유형의 인스턴스를 작성하는 것이라면 게으른 일에 아무런 문제가 없습니다.


4
@BenjaminGruenbaum 아니오, 실제로는 아닙니다. 그리고 정중하게, 그랬더라도, 어떤 점을 만들려고 했습니까?
KaptajnKold
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.