2011-08-31 2 views
7

우리는 당신이 용어를 인텔리 당신에게 모든 것을 보여 주려 포기 너무 커서 공격적으로 큰 생성자를 코믹하게 될지 우리의 도메인 모델에 약간의 개체가 ...리팩토링 큰 생성자

큐 대부분 값 유형, 몇 가지 참조 유형이있는 유형 :

public class MyLegacyType 
{ 
    public MyLegacyType(int a1, int a2, int a3, ... int a50) // etc 
    { 
    } 
} 

이 유형은 변경할 수 없습니다. 유형 자체는 논리적으로 하나의 엔티티를 나타내며, 이는 속성이 많이 발생합니다. 이 유형을 구성하는 호출자는 여러 소스에서 나온 인수의 대부분을 제공하지만 일부는 기본값으로 제공됩니다. 아마도 결과 대신 건설에 제공 될 원천에 대한 패턴이있을 것입니다.

그러나 형식을 변경하는 방법은 변경할 수 있습니다. 현재 다음과 같은 코드 섹션이 있습니다.

  • 유형에 IntelliSense가 부족합니다.
  • 추악하고 읽을 수없는 코드.
  • 합병 통증이 Connascence of Position으로 인해 발생했습니다.

즉각적인 대답은 병합에 도움이되는 기본값 및 명명 된 인수에 선택적 매개 변수를 이용하는 것입니다. 우리는 어느 정도 다른 형식으로이 작업을 수행합니다.

그러나 전체 리팩토링의 중간 정도 인 것처럼 느껴집니다.

다른 명백한 해결 방법은 생성자 인수로 사용되던 것에 대한 속성을 가진 컨테이너 유형으로 생성자 매개 변수를 줄이는 것입니다. 이렇게하면 생성자를 멋지게 정리할 수 있으며 컨테이너에 기본값을 포함시킬 수 있지만 기본적으로 문제를 다른 유형으로 이동시킬 수 있으며 선택적/명명 된 매개 변수 사용과 같을 수도 있습니다.

속성마다 (WithIntA, WithIntB) 또는 컨테이너 유형 (WithTheseInts(IntContainer c)) 기준으로 모두 유창한 생성자 개념이 있습니다. 개인적으로, 나는이 접근법을 호출 측에서는 좋아하지만, 다시 한번 말하자면 큰 유형에 대해서 마치 하나의 문제를 푸는 대신 문제를 옮긴 것처럼 느껴진다.

내 질문에,이 혼란에 묻혀있는 사람이 있다면 : 이 문제에 대한 이러한 실행 가능한 리팩토링 전술입니까? 몇 가지 관련 경험, 함정 또는 비판으로 답을 조금 더 살피십시오. 나는 그것이 멋지게 보이고 읽기 쉽고 병합하기 쉽기 때문에 유창한 것들에 기대고있다.

나는 생성자 리팩터링의 성배가 빠져있는 것처럼 느껴진다 - 그래서 나는 제안에 개방적이다. 물론 이것은 또한 처음에는 많은 속성을 가진 유형을 갖는 불행하고 피할 수없는 부작용 일 수 있습니다 ...

+1

선택적 생성자 인수에 대해 두 번째 접근법 (생성자 인수로 사용 된 특성에 대한 특성을 가진 컨테이너 유형)을 사용할 것입니다. 유창한 인터페이스는 좋지만 메서드 호출을 많이 연결해야하는 경우 약간 지저분해질 수 있습니다. IMO –

답변

12

당연히 여기에는 많은 컨텍스트가 없지만 50 개 이상의 매개 변수에는 제 해석 이 수업이 너무 많이하고 너무 복잡하다는 것입니다. 청크를보다 단순하고보다 집중된 유형으로 나눌 수있는 방법을 모색하는 것으로 시작합니다. 은 각각의 개념을 구체화 한 인스턴스를 복합 클래스에 캡슐화합니다.그래서이된다 :

public MyLegacyType(SomeConcept foo, AnotherConcept bar, ...) 
{ 
} 

을 개념 사이의을 조율 을 위해 필요한 경우에만 논리 (등, 간다 SomeConcept 특히 어떤 논리) MyLegacyType에 남아있는 곳.

이것은 생성자 인수를 대체하는 객체를 사용하는 것뿐만 아니라 논리를 근본적으로 재구성하므로 "생성자 인수로 사용되는 속성을 가진 컨테이너 유형의 생성자 매개 변수 축소"와는 다릅니다.

+0

여기에서 컴포지션을 살펴 보았지만 본질적으로 유형은 한 가지 작업을 수행합니다. 속성이되는 엔티티의 표현 -무거운. 당신이 말했듯이 그것은 상황의 부족에서 비롯된 것입니다. 제가 제 질문을 수정할 수 있는지 알게 될 것입니다. –

+0

실제로이 아이디어를 취한 다음, 호출자의 컨텍스트에서 항목을 작성하면 생성자 인수가 적절하게 변경 될 수 있습니다. 일례에서, 항목은 모든 속성을 반드시 제공하는 코드의 DAL 영역으로 구성됩니다. 이들은 모든 속성을 충족시키는 제공 유형으로 래핑 될 수 있습니다. 다른 호출자는 특정 속성이 항상 기본값으로 설정된 특정 구술을 호출합니다.이 속성은 다른 생성자 컨테이너를 사용하여이 사실을 숨길 수 있습니다. 나는 그 패턴이 있어야한다고 확신합니다. –

4

컨테이너 유형을 사용하고 C# 4.0의 즉각적인 속성 할당을 사용합니다. 이렇게하면 원래 형식에서 적절한 디커플링을 유지하면서 결과 형식에 Intellisense를 쉽게 사용할 수 있습니다. 다음

public class MyLegacyType 
{ 
    public MyLegacyType(MyConfiguration configuration) // etc 
    { 
     // ... 
    } 
} 

public class MyConfiguration 
{ 
    public int Value1 { get; set; } 
    public int Value2 { get; set; } 
    // ... 
} 

그리고 : : 예를 들어

var myInstance = new MyLegacyType(new MyConfiguration 
{ 
    Value1 = 123, 
    Value2 = 456 
}); 
1

이 나는 ​​귀하의 질문에 대해 확실하지 않다 한 가지, 그리고 생성자에서 이러한 모든 매개 변수를 원하는 않는 이유는 ? 생성자 코드의 모든 매개 변수를 사용하고 있습니까? 인텔리 센스에 대한 귀하의 문제는 아마 하나의 방법에 너무 많은 매개 변수를 사용하는 것으로부터옵니다. 하나의 유형에 많은 수의 필드/속성이 있으면 문제가 발생하지 않습니다.

args의 수를 관리하는 몇 가지 방법을 본 것처럼 보이지만 생성자에서 모든 인수를 받아야하는 이유를 설명 할 수 있다면이 상자 밖에서 생각할 수 있습니다. 거기에 뭔가가있을 수 있습니다.

+0

현재 생성자의 모든 인수에 대한 이유 중 하나는 현재 최악의 경우이며 레거시 코딩 스타일의 결과이므로 DAL 코드는 판독기에서 개체를 구성 할 수 있습니다. 다른 "충분히 좋은"이유가 없다고 생각합니다. 코드를 리팩터링하지 않고 그냥 추가하는 사람들의 희생양이라고 생각합니다. 대부분의 속성은 생성자에서 내부 필드로 간단하게 바뀝니다. –

+0

DAL에서 엔터티 필드를 채우는 데 속성을 사용하지 않는 이유는 무엇입니까? 또는 단일 C# 문에 있어야하는 경우 C#에서 객체 이니셜 라이저 구문을 사용할 수 있습니다. - 새 클래스 이름 {Prop1 = value, Prop2 = value, ...} – Iravanchi

+0

모든 속성이 setter를 노출하지는 않습니다. 나는이 방식으로 행해진 유일한 이유는 그것이 항상 이루어 졌기 때문이라고 생각합니다. 아무도 스타일을 바꾸기 위해 그것을 취하지 않았습니다. 실제로 최악의 유형 중 하나는 DAL에서 독점적으로 사용되며 다른 곳에서는 테스트 프로젝트입니다. –