2011-10-17 1 views
0

는 이러한 코드 있다고 가정 :"기본 클래스 PARAMS는 항상 사용되지 않습니다"코드 냄새가

public Base 
{ 
    abstract void Register(); 
} 

public Registrator1: Base 
{ 
    override void Register() 
    { 
     //uses the current state of the object to populate the UI captions 
    } 
} 

public Registrator2: Base 
{ 
    override void Register() 
    { 
     //uses the current state of the object to populate the UI captions 
    } 
} 

그러나 당신은 실제로 몇 가지 매개 변수에 따라 레지스터는 Registrator3를 작성 요구하는 새로운 비즈니스 규칙을 받고 당신은 변경할 때

public Base 
{ 
    abstract void Register(externalParam); 
} 

public Registrator1: Base 
{ 
    override void Register(externalParam) 
    { 
     //uses the current state of the object to populate theUI 
    } 
} 

public Registrator2: Base 
{ 
    override void Register(externalParam) 
    { 
     //uses the current state of the object to populate the UI 
    } 
} 

public Registrator3: Base 
{ 
    override void Register(externalParam) 
    { 
    //uses a DDD - service passed in the params to populate the UI 
    } 
} 

그러나 Registrator1과 Registrator2는 해당 param을 필요로하지 않으며 코드가 smelly가됩니다. 이 코드를 다시 작성하는 방법은 무엇입니까?

+0

oop을 언급하면 ​​메소드에 가상을 추가 할 수 있습니다. 이것은 코드 냄새가 "현재 같은 이름의 새 메소드"인 것처럼 보입니다. –

+0

@Valentin Kuzub, done –

+0

여전히 문제가 있습니다. 처음 메서드에는 params가 없습니다. 즉, 호출 된 객체의 상태를 조작하는 것입니다. 그 Register가 실제로하고있는 것이 명확하지 않아, 결함이나 더 나은 방법을 생각하기가 어렵습니다. externalParam을 추가하면 전체 그림이 완전히 바뀝니다. 등록자는 이제 매개 변수를 등록하거나 그 매개 변수를 기반으로 다른 매개 변수를 등록하여 상태가 충분하지 않습니다. 어쨌든 나는 좋은 조언을 원한다면 질문을 확장하고 예를 들어 등록 함수에 대한 의사 코드를 보여줄 수 있다고 생각한다. –

답변

2

개체를 매개 변수로 사용할 수 있습니다. 이 매개 변수는 사용되는 호출에 따라 매개 변수의 수가 다를 수있는 시나리오에서 일반적으로 사용됩니다.

struct RegistrationInfo 
{ 
    public static readonly RegistrationInfo Empty = new RegistrationInfo(); 
    public string Username; 
    public string CustomerName; 
    public string Validity; 
} 

abstract class Base 
{ 
    public abstract void Register(RegistrationInfo info); 
    // If you want to retain the paramaterless call: 
    public void Register() 
    { 
     Register(RegistrationInfo.Empty); 
    } 
} 

class Registrar1 : Base 
{ 
    public override void Register(RegistrationInfo info) 
    { 
     if (info.Username == null) throw new ArgumentNullException("info.Username"); 
    } 
} 

class Registrar2 : Base 
{ 
    public override void Register(RegistrationInfo info) 
    { 
     if (info.CustomerName == null) throw new ArgumentNullException("info.CustomerName"); 
    } 
} 

이렇게하면 매개 변수를 추가 할 때마다 메소드 매개 변수 (인터페이스 분리)를 변경할 필요가 없다는 장점이 있습니다. 사용법은 다소 자기 문서화된다 :

var r = new Registrar1(); 
r.Register(new RegistrationInfo(){ Username = "JimJoe" }); 
r.Register(RegistrationInfo.Empty); 

그것은, 코드 냄새 이러한 종류의 공기 청정기처럼 여전히 냄새 나는있는 동안; 당신은 더 좋은 냄새를 맡을 수 있습니다.

마지막으로 호출 사이트를 params 인수 (오버 헤드가 적음)로 만들 수 있습니다. 솔직히 말하면 언어 해킹이기 때문에 더 냄새가 난다. 마지막으로 generics로 개선 할 수 있습니다 :

class RegistrationInfo 
{ 

} 

class RegistrationInfo1 : RegistrationInfo 
{ 
    public string Arg; 
} 

class RegistrationInfo2 : RegistrationInfo 
{ 
    public int Arg; 
} 

interface IBase<in TRegistration> 
    where TRegistration : RegistrationInfo 
{ 
    void Register(TRegistration registration); 
} 

class Base : IBase<RegistrationInfo> 
{ 
    public void Register(RegistrationInfo registration) 
    { 

    } 
} 

class Registrar1 : IBase<RegistrationInfo1> 
{ 
    public void Register(RegistrationInfo1 arg) 
    { 
    } 
} 

class Registrar2 : IBase<RegistrationInfo2> 
{ 
    public void Register(RegistrationInfo2 arg) 
    { 
    } 
} 
+0

네, 당신의 솔루션은 멋지고 멋집니다. 고마워요.그러나 나는이 매개 변수가 좋지 않기 때문에 null (null) 타이핑 등록 정보를 90 %의 시간과 null을 받는다. 다른 방법으로 해결할 수는 없지만 –

+0

@Hohhi 기본 클래스에서 메소드를 호출하면 호출시 null을 통과합니다. –

+0

나는 당신이 말하는 것을 내 마음 속에서 실제로 묘사 할 수 없다. –

0

Registrator3에서 externalParam의 논리를 포함 할 수 있습니까? 즉, Registrator3은 param을 사용하고 수정되지 않은 매개 변수없는 기반을 호출합니까?

정말 많은 논리가 어디에 속하는 지에 따라 다릅니다. 그것이베이스에 내재 된 어떤 것이라면,베이스에 넣고, Register() 함수에 오버로드하거나 서브 클래스가 제공 할 필요가 없도록 param의 기본값을 제공하십시오. 다음과 같이 기본 클래스에서 등록 로직을 재사용 할 가정

0

, 당신은 코드를 업데이트 할 수 있습니다 :

public class Base 
{ 
    public virtual void Register(object externalParam) 
    { 
     // base registration logic goes here 
    } 
} 

public class Registrator1: Base 
{ 
    public override void Register(object externalParam) 
    { 
     base.Register(null); 
     // custom registration logic goes here 
    } 
} 

public class Registrator2: Base 
{ 
    public override void Register(object externalParam) 
    { 
     base.Register(null); 
     // custom registration logic goes here 
    } 
} 

public class Registrator3: Base 
{ 
    public override void Register(object externalParam) 
    { 
     base.Register(externalParam); 
     // custom registration logic goes here 
    } 
} 

HTH,

코스 민

편집 : 컴파일 업데이트 코드입니다.

+1

이 코드는 컴파일되지 않습니다 –

+0

코드를 업데이트했습니다. – CosminB