0

多くの反復的な switch ステートメントは、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;
        }
    }
4

2 に答える 2

1

他のすべての下にあるものはすべて、関連するステップを近づけるために1つのスイッチにまとめる必要があります。例えば

case DIR_FORWARD_LOOPING:
    _iter->second->Next();
    if (_iter->second->IsAtEnd()) {
        _iter->second->First();
    }
    break;

...その1つの場合すべて。いくつかの関数呼び出しを繰り返すことは、アクションの全体的なシーケンスをより明確にする場合、大したことではありません。

于 2012-07-11T04:27:54.483 に答える
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());
    }
于 2012-07-04T22:34:28.863 に答える