2009-08-01 3 views
1

구현할 OO 디자인을 해독하려고합니다. 기본적으로 PstnNumber는 본질적으로 항상 0으로 시작하는 10 자리 전화 번호입니다 (예 : 0195550000). 선행 0이 누락되면 번호 자동 수정을 허용하는 규칙이 도입되었습니다 (예 : 195550000). 어떤 설계 옵션이 시공시 자동 수정에 더 적합합니까?

START 편집

내가 원래 질문은 오해되었을 수 있습니다 실현 (감사합니다 친절 이미 대답 한 누구에게), 그래서 나는 시도하고 더 나은 시나리오를 설명하기 위해 편집했습니다.

최종 편집

나는 일부 예비 개념을 연주하기 시작하고 (일부 수준)이 충분할 중 하나를 이동하거나 할 수있는 더 적절한 방법이 있다면 내가 물어 줄 알았는데?

개념 1

public class PstnNumber 
{ 
    public virtual string Number { get; set; } 

    public PstnNumber() { } 

    public PstnNumber(string number) 
    { 
     this.Number = number; 
    } 
} 

public class AutoFormattedPstnNumber : PstnNumber 
{ 
    public override string Number 
    { 
     get { return base.Number; } 
     set { base.Number = value.PadLeft(10, '0'); } 
    } 

    public AutoFormattedPstnNumber() : base() { } 

    public AutoFormattedPstnNumber(string number) 
    { 
     this.Number = number; 
    } 
} 

개념 2 (제거)

개념 3

public class PstnNumber 
{ 
    public bool AutoCorrect { get; set; } 

    private string number; 
    public virtual string Number 
    { 
     get { return (this.AutoCorrect) ? this.number.PadLeft(10, '0') : this.number; } 
     set { this.number = value; } 
    } 

    public PstnNumber() : this(false) { } 

    public PstnNumber(bool autoCorrect) 
    { 
     this.AutoCorrect = autoCorrect; 
    } 

    public PstnNumber(string number) : this(false) 
    { 
     this.Number = number; 
    } 

    public PstnNumber(string number, bool autoCorrect) : this(autoCorrect) 
    { 
     this.Number = number; 
    } 
} 

나는 서브 클래스는 수의 동작을 변경하기 때문에 개념 1은 Liskov 교체 규칙을 위반하는 생각 재산 (내가 잘못 이해했는지 알기를 기쁘게 생각한다).

다른 제안 사항은 행복하게 접수됩니다.

+0

클래스를 전혀 확장하지 않고 단순히 숫자를 자동 서식 지정하고 pstnnumber 개체를 반환하는 정적 생성자 함수를 사용하는 옵션이 없습니까? – Zed

+0

@Zed : 예를 들어 PstnNumber AutoPstnFormatter.CreatePstn ("195550000"); ? –

답변

4

개체를 인스턴스화 할 때 자동 서식 지정을 수행해야합니까? 그렇지 않은 경우, 것에 대해 : 옵션 1, 옵션 2에서

public class PstnNumber 
    { 
    public virtual string Number { get; set; } 
    public PstnNumber() { } 
    public PstnNumber(string number) { this.Number = number; } 
    public AutoFormatNumber { get { return Numer.PadLeft(10, '0'); } } 
    } 
+0

@Charles : 감사합니다 Charles, 내 관심사는 Validate 메소드를 추가 할 때 어떤 속성의 유효성을 검사합니까? 195550000에 대해 Number와 Auto Format 규칙을 통과시켜야합니다. –

+0

@Davide, 새 속성에는 getter 만 있고 Number에서 사용하는 것과 동일한 private (암시 적) 필드를 사용하므로 유효성 검사기가 필요하지 않습니다. –

+0

은 두 형식을 모두 지원해야하므로 비교와 같은 추가 작업이 복잡해질 수 있습니다. – peterchen

1

, 당신은이 '아무튼 어떤 점에서 autoformatted 것을 알고 제외 (서브 클래스 쓸모없는 렌더링, 어쨌든 원래의 수를 유지하지 않습니다 유용한 정보처럼 보입니다.) 이 옵션을 더 유용하게 사용하는 대안은 설정 대신 가져 오기에서 형식을 지정하는 것입니다.

옵션 3은이 세 가지 옵션 중에서 선호되는 패턴이지만, PstnNumber도 단순히 자릿수를 감지하고 그에 따라 자동 서식을 지정할 수없는 이유는 무엇입니까?

1

규칙을 따르는 경우 "각 루틴 (읽기 클래스)은 한 가지만하고 잘 수행해야합니다"라는 규칙이 있습니다.

에 따르면 PstnNumber은 숫자를 보유하고 올바른 숫자를 생성하는 일종의 팩토리를 만듭니다.

동일한 클래스에서 두 개 모두한다는 것은 도메인 논리와 표현을 짜고 있음을 의미합니다. 나는 그들을 분리하는 것이 더 좋다.

+0

+1 - 동의 - 및 PstnNumber는 올바른 형식의 숫자 만 보유하도록 허용해야합니다. 끝난. 다른 솔루션들 중 많은 부분이 정신병 적으로 뒤얽힌 것입니다. –

1

나는 당신의 클래스 이름이 왜 그렇게 이상한 지 물어볼 것이다. "번호"는 나에게 명확하고 "P"는 "전화"를 제안하지만, "stn"은 무엇입니까? 몇 가지 추가 키 입력으로이 클래스를보다 자체적으로 문서화 할 수 있습니다.

나는 기본 데이터 멤버를 어떤 값으로 초기화하지 않는 기본 생성자의 논리에 대해서도 물어볼 것이다. 가능하다면 기본 생성자는 합리적인 기본값을 가져야한다고 생각합니다.

나는 선택의 여지가 과잉이라고 느낀다. 나는 상속이이 모델을 더 분명하게 또는 더 좋게 만들고 있다고 생각하지 않습니다. 기본 클래스를 호출하는 모든 상황에서 하위 클래스를 사용할 수 있어야한다는 Liskov 대체가 어떻게 깨지는지 알 수 없습니다. 이 방법은 내가 볼 수있는 한 1 : 1을 매핑합니다. 리 코스프로는 어떻게 침해 당했습니까?

옵션 2는이 두 클래스가 관계가없는 별도의 클래스라고합니다. 그건 나에게 맞는 것 같지 않아.

이 모든 작업을 통해 두 클래스를 모두 사용해야하는 문제가 있음을 알 수 있습니다. 선행 제로가 필수가 아닌 상황과 그렇지 않은 상황이 있습니다. 그게 사실이야? 아니면 항상 앞의 0을 요구할 것입니까?

귀하의 선택에 상관하지 않습니다. 인터페이스 나 정적 팩토리를 선호하거나 제안한 클래스에 수정을 가할 수도 있습니다. 단순한 형식 지정 문제처럼 느껴집니다. 당신은 선행 제로와 함께 번호를 저장합니까? 그렇지 않다면 아마도 그것은 단지 관심사 일뿐입니다.

+0

참조 : http://en.wikipedia.org/wiki/Public_switched_telephone_network – Zed

+1

Zed에게 감사 드려요. 그러나 "PstnNumber"가 "PhoneNumber"보다 더 명확하게 보이지 않습니다. 어떤 부가 가치가 추가됩니까? – duffymo

+0

나는 당신에 동의합니다. "PhoneNumber"는 훨씬 더 명확합니다. 스티브 맥코넬 (Steve McConnell)은 "올바른 이름을 제시하는 효과적인 방법은 변수가 나타내는 단어를 기술하는 것입니다. 종종 그 명령문 자체가 가장 좋은 변수 이름이며, _cryptic abbreviations_가 없기 때문에 읽기 쉽습니다. . " (p260 - 강조 추가됨) –

0

는 전 C#에 익숙하지 않은,하지만 나는이 작업을 수행 할 것 :

물론
public class PstnNumber { 
    readonly string number; 

    public PstnNumber(string number) { 
    this.number = number; 
    } 

    public string getNumber() { 
    return number; 
    } 

    static public PstnNumber createNumber(string number) { 
    return new PstnNumber(number.PadLeft(10, '0')); 
    } 
} 

나는 속성이 작동하는 방법을 알고 있다면, 아마 다르게 할 것 :

+0

"public string number {get; private set;}" –

3

피하기 게터를 -setter-surprise
getter가 setter에서 허용 한 값과 다른 값을 반환하지 않도록하십시오. 다음 코드를 상상해

temp = PstnNumber.FromString(input.Value); 
if (temp != current) { ... } 

표준 형식
일부 데이터가 서로 다른 표현이있는 경우, 장점 많은 저장에있다 :

if (input.Value != current.Number) 
{ 
    NumberChangedAgain = true; 
    current.Number = input.Value; 
} 

간단한 해결책은 PstnNumber 불변하게하는 것 표준 표현으로 변환하고 형식 변환을 팩토리 함수 및 getter/형식 작성자로 이동합니다. 예를 들어 짧은 대 긴 대, 짧은 대 짧은 대 짧은 대 짧은 대, 대 긴 비교를 테스트 할 필요가 없습니다.

다양한 측면
은 당신이 "autoformatted"과 "정상"수 사이의 구별을해야합니까, 또는 입력 및 출력이 단지 질문이다 - 즉

  • 은 (짧은 표시 형식 않습니다 또는 오래)는 번호 입력 방법 또는 표시 위치에 따라 다릅니다.
  • 0195550000 == 195550000?

("또는 0 잊어 수없이 입력"때 즉) 나는 가능하다면 하나에 두 클래스를 접어 원합니다 : 그렇지 않으면 내가 옵션 3으로 갈 것

public class PstnNumber 
{ 
    private string m_number; // always in long format 
    public static PstnNumber(string s) { ... } // accepts short and long form 

    public string Number { get { return m_number; } } 
    public string AutoFormatted { { get { ... } } 
} 

하지만, 항상 긴 형식을 m_number에 저장하십시오.

1

세터를두고 정말로 회원이없는 이유가 무엇입니까? 그렇지 않다면 아마 그 차이는 다른 세 가지 변이보다 더 큰 문제 일 것입니다.

그래서 나는 autoFormat 변수를 최종적으로 제거하고 gettng을 없애는 것을 의미하는 무국적 # 3을 원합니다.

단순화하기 위해 난 그냥 당신이 가진 수있는, 아직 getNumberRaw 및 getNumberFormatted

더 나은 거라고 formatType 실제로 형식은 나중에 다시 변경할 수 있기 때문에 숫자를 포맷 코드가 포함 getNumberRaw 및 getNumber (formatType) 전화 번호 (모델)와 형식 (보기)을 결합하는 것이 최적이 아닙니다.

(PS/EDIT) : 전화 번호가 바뀔 수 있다는 사실만으로도 세터가있는 것은 아닙니다! 새 전화 번호 개체를 만들고 이전 전화 번호 개체를 대체하면 거의 항상 작동합니다!

0

훨씬 간단한 버전으로 ToString 메서드를 재정의하거나 심지어 숫자 서식이 지정되었음을 나타내는 bool 매개 변수를받는 ToString 오버로드를 만들 수도 있습니다.