2012-07-04 2 views
0

많은 반복적 인 스위치 구문이 DRY 될 필요가있는 것처럼 보입니다. 어떤 제안? (포함하여이 아무것도하지!)반복적 인 스위치 명령문에 필요한 리팩토링

AnimMapIter _iter; 
    _iter = _animations->find(name); 
    if(_iter == _animations->end()) return; 

    if(_curName != name) { 
     _curName = name; 

     switch(dir) { 
     case DIR_FORWARD_LOOPING: /* Fall through to DIR_FORWARD_NONLOOPING */ 
     case DIR_FORWARD_NONLOOPING: 
      _iter->second->First(); 
      break; 
     case DIR_REVERSE_LOOPING: /* Fall through to DIR_REVERSE_NONLOOPING */ 
     case DIR_REVERSE_NONLOOPING: 
      _iter->second->Last(); 
      break; 
     } 
    } else { 

     switch(dir) { 
     case DIR_FORWARD_LOOPING: /* Fall through to DIR_FORWARD_NONLOOPING */ 
     case DIR_FORWARD_NONLOOPING: 
      _iter->second->Next(); 
      break; 
     case DIR_REVERSE_LOOPING: /* Fall through to DIR_REVERSE_NONLOOPING */ 
     case DIR_REVERSE_NONLOOPING: 
      _iter->second->Previous(); 
      break; 
     } 

     switch(dir) { 
      case DIR_FORWARD_LOOPING: 
       if(_iter->second->IsAtEnd()) 
        _iter->second->First(); 
       break; 
      case DIR_FORWARD_NONLOOPING: 
       if(_iter->second->IsAtEnd()) 
        _iter->second->Last(); 
       break; 
      case DIR_REVERSE_LOOPING: 
       if(_iter->second->IsAtFront()) 
        _iter->second->Last(); 
       break; 
      case DIR_REVERSE_NONLOOPING: 
       if(_iter->second->IsAtFront()) 
        _iter->second->First(); 
       break; 
     } 
    } 
+0

함수 포인터가 도움이 될 것 같습니다. –

+0

[Code Review] (http://codereview.stackexchange.com/)에 좋은 질문입니까? – jrok

+0

@jrok 나는 조심스러운쪽으로 잘못했다. 이동해야하는 경우 계속하십시오. – Casey

답변

1

else 아래에있는 모든 항목은 관련 단계를보다 가까워 지도록 단일 스위치로 축소되어야합니다. 예 :

... 모두 하나의 경우. 두 번의 함수 호출을 반복하는 것은 전체적인 동작 시퀀스가 ​​더 명확 해지면 큰 문제가되지 않습니다.

1

푸시 _iter->second 무엇이든에 논리를,이 라인을 따라 (당신이 이미 보여준 방법이 존재 가정) :

class WhateverItIs 
{ 
public: 
    void Start() { if (m_forward) First(); else Last(); } 
    void Stop() { if (m_forward) Last(); else First(); } 
    void Advance() 
    { 
     if (m_forward) 
     Next(); 
     else 
     Previous(); 
     if (IsLast()) 
     { 
     if (m_loop) 
      Start(); 
     else 
      Stop(); 
     } 
    } 

private: 
    bool IsLast() const 
    { 
     return m_forward ? IsAtEnd() : IsAtFront(); 
    } 
    // Direction and looping are independent concepts.  
    bool m_forward; 
    bool m_loop; 
}; 

을 그럼 당신은 쓸 수 있습니다 :

AnimMapIter _iter; 
_iter = _animations->find(name); 
if(_iter == _animations->end()) return; 

if(_curName != name) { 
    _curName = name; 
    _iter->second->Start(); 
} else { 
    _iter->second->Advance(); 
} 

편집 : 무료 기능을 사용하고 상수를 유지하는 예.

void Start(Strip* s, bool forward) 
     { if (forward) s->First(); else s->Last(); } 
    void Stop(Strip* s, bool forward) 
     { if (forward) s->Last() else s->First(); } 
    void Advance(Strip* s, bool forward, bool loop) 
    { 
     if (forward) 
     s->Next(); 
     else 
     s->Previous(); 
     if (IsLast(s, forward)) 
     { 
     if (loop) 
      Start(s); 
     else 
      Stop(s); 
     } 
    } 

    bool IsLast(const Strip* s, bool forward) const 
    { 
     return forward ? s->IsAtEnd() : s->IsAtFront(); 
    } 

    bool Projector::IsForward() const 
    { 
     return dir == DIR_FORWARD_LOOPING || dir == DIR_FORWARD_NONLOOPING; 
    } 

    bool Projector::IsLooping() const 
    { 
     return dir == DIR_REVERSE_LOOPING || dir == DIR_FORWARD_LOOPING; 
    } 

    if(_curName != name) { 
     _curName = name; 
     Start(_iter->second, IsForward()); 
    } else { 
     Advance(_iter->second, IsForward(), IsLooping()); 
    } 
+0

두 번째 매개 변수는 프레임 스트립입니다. 그것들을 한 장의 필름으로 생각하십시오. 그들 자신은 전방 또는 후방에 대한 개념이 없으며, 첫 번째, 마지막, 그리고 각 프레임에 대해서만 개념을 가지고 있습니다. 그것은 특정 방향으로 필름을 움직이는 필름 영사기입니다. – Casey

+0

@Casey : 동일한 아이디어를 적용하고 제어 클래스에서 (매개 변수로 스트립과 함께) 메소드를 사용할 수 있습니다. 그것들을 자유로운 기능으로 가질 수도 있습니다. DRYing은 논리를 함수로 추상화하는 것입니다. 편집을 참조하십시오. – molbdnilo