2013-05-20 3 views
2

우선 리팩토링에 대한 경험이 많지 않으며이 주제가 아닌지 잘 모릅니다.부울 플래그를 속성으로 사용하지 마십시오.

많은 부울 속성이 사용되는 주어진 코드로 작업하고 있습니다. 이는 가독성 때문에 피하고 싶습니다. 적절한 방법으로 처리하는 방법을 모르겠습니다.

class MyClass(){ 
    boolean a; 
    ... 
    void function(){ 
     ... 
     a = true; 
     ... 
    } 

    void anotherFunction(){ 
     ... 
     if(a == true){ 
      //do something 
     } else { 
      //do something else 
     } 
     ... 
    } 
    ... 
} 

boolean a

복수에 anotherFunctiona에 대한 코드를 실행하는이 같은 function들, 사용된다. anotherFunction에서 다중 속성 및 로컬 변수를 사용하기 때문에 코드 및 종속성을 이해하기가 어렵고 리팩터링하기가 어렵습니다. 이것을 리펙토링하려는 노력은 매우 높을 수 있습니다.

저는 항상 내 눈이 좋지 않기 때문에 이런 부울을 사용하지 않기 위해 노력했습니다. 내가 틀렸다면 저를 바로 잡으려고 주저하지 마십시오.

이제 코드를 리팩토링하고 노력을 기울여야하는지 알고 싶습니다. 이 경우 사용할 수있는 패턴이 있습니까?

답변

5

상태 패턴을 사용할 수 있습니다. 부울 변수에 따라 상태 및 동작을 별도의 추상 State 클래스로 캡슐화합니다. 부울을 false로 설정하면 상태를 인스턴스 FalseState (State까지 확장)로 변경하고이 FalseState 인스턴스에 위임합니다. 부울을 true로 설정하면 상태를 TrueState의 인스턴스로 변경하고 TrueState 인스턴스에 위임합니다. 예를 들어

, 다음 클래스

public class Apple { 

    private boolean fresh = false; 

    public String getColor() { 
     if (fresh) { 
      return "green"; 
     } 
     else { 
      return "brown"; 
     } 
    } 

    public void setFresh(boolean fresh) { 
     this.fresh = fresh; 
    } 
} 

나는 내부 클래스를 사용
public class Apple { 

    private AppleState state = new OldAppleState(); 

    public String getColor() { 
     return state.getColor(); 
    } 

    public void setFresh(boolean fresh) { 
     this.state = state.nextState(fresh); 
    } 

    public String getColor() { 
     return this.state.getColor(); 
    } 

    private static abstract class State { 
     public abstract State nextState(boolean fresh); 
     public abstract String getColor(); 
    } 

    private static class OldAppleState extends State{ 
     public State nextState(boolean fresh) { 
      return fresh ? new FreshAppleState() : this; 
     } 
     public String getColor() { 
      return "brown"; 
     } 
    } 


    private static class FreshAppleState extends State{ 
     public State nextState(boolean fresh) { 
      return fresh ? this : new OldAppleState(); 
     } 
     public String getColor() { 
      return "green"; 
     } 
    } 
} 

에 리팩토링 할 수 있지만, 당신은 물론 최상위 클래스를 사용할 수 있습니다.

+0

다른 상태를 정의하는 것이 좋습니다. 고마워. –

2

코드 샘플은 분명히 다소 잘 렸지만이 클래스가 state machine처럼 동작하는 것처럼 들립니다.

클래스 내에 다수의 부울 속성이 있고 그 함수 내에서 메소드의 동작을 결정하면 매우 빠르게 폭발 할 수 있으며 코드는 따라 잡기 어려울 수 있습니다. 같은 코드 :

if (true == a && false == b){ 
    ... 
} 
elseif (false == a && false == b){ 
    .... 
} 

등등.

적용 할 수있는 첫 번째 리팩토링은 상태 조회 방법을 만드는 것입니다. 이 코드에 위의 변환합니다

if (aNotB == getState(a, b)){ 
    .... 
} 
elseif (notANotB == getState(a, b)){ 
    ... 
} 

이 응용 프로그램이 아닌 개별 논리 값의 상태의 관점에서 생각하는 것이 좀 더 쉽게, 그리고 힘의 코드를합니다.

필요한 경우 전체 상태 시스템으로 이동할 수 있습니다. 대부분의 프로그래밍 언어에 대해 interwebs 전체에 참조 구현이 있습니다.

+0

예, 가능한 조합으로 상태를 정의하는 것이 정말 짜증나게합니다! –

1

상태 전환 측면에서 논리를 생각하는 것이 중요합니다. enum을 사용하여 상태를 깨끗하게 정의하려면 한 걸음 더 나아갈 것입니다.Template methods using enums를 - 열거를 사용

public enum AppState { 
    ST1(false, false), 
    ST2(false, true), 
    ST3(true, false), 
    ST4(true, true); 
    private Boolean x, y; 
} 

하나 특히 유용한 장점은 템플릿 메소드를 정의 할 수있는 기능입니다. 상태에 맞게 기능을 간소화하고보다 객체 지향적으로 만들 수 있습니다.

+0

상태를 enum으로 정의하는 것이 나에게 좋다고 들립니다. –

1

부울 a가 여러 번 사용되는 경우, 나는 모나드와 같은 내부 클래스 함수를 선호합니다.

public class BoolAHandler{ 
    public bool A = false; 
    public BoolAHandler IfTrue(Action act){ 
     if(A){ 
      act(); 
     } 
     return this; 
    } 
    public BoolAHandler IfFalse(Action act){ 
     if(!A){ 
      act(); 
     } 
     return this; 
    } 
} 

사용법 : 부울 A가 의미가있는 경우

boolAHandler.IfTrue(() => { doFunctionA(); }) 
      .IfFalse(() => { doFunctionB(); }); 

는 물론, 당신이 너무 의미로 조정할 수 있습니다. 게시 된 상태를 처리하는 경우 IfTrueIfAlreadyPublishedIfFalseIfNotPublished으로 변경할 수 있습니다.

+0

전에 모나드에 대해 들어 본 적이 없습니다. 고마워. –

관련 문제