Выполнять различные методы согласно какой цепи Вы были, удаляя if-else if

Я хочу refactorizar следующий метод и оставлять чистый кодекс.

Метод в вопросе получает цепь. Согласно какой цепи Вы были выполняется метод. Этот метод, чтобы выполнять, может принадлежать отцу и матери, отличной от оставшейся части.

class MiClase : public QObject
{
    void metodoParaRefactorizar(QString cadena)
    {
        QJsonDocument jDoc;
        bool instructionFound = false;

        if(cadena.compare("instruccionUno") == 0)
        {
            jDoc = this->objClassOne->metodoPublico();
            instructionFound = true;
        }
        else if(cadena.compare("pepito") == 0)
        {
            jDoc = this->objeClassTwo->getList();
            instructionFound = true;
        }
        else if(cadena.compare("cadenaMolona") == 0)
        {
            jDoc = this->objeClassServer->getName();
            instructionFound = true;
        }
        else if(cadena.compare("otraCadenaDiferente") == 0)
        {
            jDoc = this->objeClassHtml->ejecutaScript();
            instructionFound = true;
        }
        .... 
        // Muchos más 'else if'
        ....
        else if(cadena.compare("ultima") == 0)
        {
            jDoc = this->objeClassLast->closeAll();
            instructionFound = true;
        }

        if(instructionFound)
        {
            sendAnswer(jDoc);
        }
    }
}

Я разыскивал из-за Интернета и увидел, что решение было бы полиморфизмом. Но в этом случае способы, которые нужно выполнять, могут быть очень различных классов.

Вы нюхаете у меня очень плохо этот кодекс. Это мне кажется непригодным для курения и тяжелым для того, чтобы настаивать. Вы производите много сопряжение. Что проблема - больше дизайна, что другая вещь. Хотелось бы учиться делать это лучше.

Какое решение Вы могли бы давать Вам? Как я это преобразовываю в кодекс, чистый и легкий для того, чтобы быть поддержанным?

1
задан 21.10.2016, 14:08
3 ответа

Возможное решение перемещает из-за indizar все возможные выборы в карте. Каждый возможный выбор будет к партнеру в lambda с кодом выполнять в каждом случае.

Как только была произведена карта, знание, если выбор действительный, - такое простое как консультировать существование ключа. Если ключ существует тогда, мы выполняем операцию, ассоциируемую с той же самой.

void metodoRefactorizado(QString cadena)
{
    static std::map<QString,std::function<QJsonDocument()>> opciones
    {
      std::make_pair("instruccionUno",[&]() { return this->ObjClassOne->metodoPublico(); }).
      std::make_pair("pepito",[&]() { return this->objClassTwo->getList(); })
    };

    auto it = opciones.find(cadena);
    if( it != cadena.end() )
    {
      QJsonDocument jDoc = it->second();
      sendAnswer(jDoc);
    }
}

Конечно ты можешь двигать, из-за читабельности, функцию инициализации в другой метод. Благодаря синтаксису Move (доступный начиная с C ++ 11) потеря результата (если он волнует тебя) - презренная.

std::map<QString,std::function<QJsonDocument()>> InitMap()
{
  return std::map<QString,std::function<QJsonDocument()>>
    {
      std::make_pair("instruccionUno",[&]() { return this->ObjClassOne->metodoPublico(); }).
      std::make_pair("pepito",[&]() { return this->objClassTwo->getList(); })
    };
}

void metodoRefactorizado(QString cadena)
{
    static std::map<QString,std::function<jDoc()>> opciones = InitMap();

    auto it = opciones.find(cadena);
    if( it != cadena.end() )
    {
      sendAnswer(it->second());
    }
}

Приветствие.

4
ответ дан 24.11.2019, 12:59
  • 1
    Посмотрим я становлюсь понятным немного. Я est и # 225; s предлагая, чтобы создал контейнер и #39; map и # 39; где я присоединяю цепь к одному м и # 233; все конкретный. и #191; Нет? – Jonathan 21.10.2016, 14:01
  • 2
    Точный. Карта, в отличие от последовательности if-else, не реализует одну b и # 250; squeda линейный, потом время b и # 250; squeda он меньше. С другой стороны ты est и # 225; s избавляя от бесконечной последовательности if-else. – eferion 21.10.2016, 14:07
  • 3
    Ok, гениальный я это разоряю. Понемногу, но я это вижу. – Jonathan 21.10.2016, 14:09
  • 4
    Вторая часть, что я нравиться и # 237; чтобы понимать немного лучше, и где я теряюсь немного. Я не понимаю из-за qu и # 233; есть 2 и #39; return и # 39; укрытые. Я понимаю, что каждый элемент - цепь и funci и # 243; n lambda, что возвращает результат выполнения instrucci и # 243; n корреспондент. Но... и #191; из-за qu и # 233; ты это помещаешь внутри этого и #39; return и # 39;? return std::map<QString, std::function<jDoc()>> podr и # 237; которые он было нужно определить, было элементы map, и #191; нет? и #191; Каждый раз, когда я выполняю opciones.find(cadena) ищи цепь, выполни funci и # 243; n lambda корреспондент и... и #191; он распределяет ее it? и #191; d и # 243; nde он приходит it->second()? В этой части я теряюсь... – Jonathan 21.10.2016, 14:20
  • 5
    то, что есть внутри std::make_pair, так это lambda , который не м и # 225; s, что funci и # 243; n впитанная в c и # 243; я говорю (доступный с C ++ 11). funci и # 243; n этой lambda состоит в том, чтобы возвращать один QDomDocument, а следовательно нуждается его собственный return. – eferion 21.10.2016, 14:22

Элегантное решение могло бы быть:

  • Ты строишь array со всеми цепями, которые нужно сравнивать
  • Ты строишь array функций и распределяешь в каждый элемент функцию, которая соответствует цепи, что tinene тот же индекс.
  • Ты определяешь функцию, которая возвращала бы индекс, если цепь существует.
  • В конце концов ты выполняешь функцию как возвращенный индекс.

Он будет гораздо более легким для того, чтобы быть поддержанным и для того, чтобы быть понятно, что наполняя функцию if-else.

0
ответ дан 24.11.2019, 12:59

Твоя функция metodoParaRefactorizar смоги быть обобщенным в этих линиях:

void metodoParaRefactorizar(std::string s)
{
    auto found = callbacks.find(s);
    bool instructionFound = false;
    QJsonDocument jDoc;

    if ((instructionFound = (found != callbacks.end())))
    {
        jDoc = (this->*found->second)();
    }
}

Но это значит, что мы переместили комплексность в другую сторону. Как он предложил, что mcNets ты можешь использовать callbacks. Для того, чтобы предыдущий код функционировал, ты должен делать что-то похожим в esto1:

class MiClase
{
    struct A { QJsonDocument metodoPublico() { return {}; } };
    struct B { QJsonDocument getList() { return {}; } };
    struct C { QJsonDocument getName() { return {}; } };
    struct D { QJsonDocument closeAll() { return {}; } };

    using callback = QJsonDocument(MiClase::*)();

    A a; B b; C c; D d;

    QJsonDocument metodoPublico() { return a.metodoPublico(); }
    QJsonDocument getList()       { return b.getList(); }
    QJsonDocument getName()       { return c.getName(); }
    QJsonDocument closeAll()      { return d.closeAll(); }

    const std::map<std::string, callback> callbacks =
    {
        {"instruccionUno",      &MiClase::metodoPublico},
        {"pepito",              &MiClase::getList},
        {"cadenaMolona",        &MiClase::getName},
        {"otraCadenaDiferente", &MiClase::closeAll},
    };

    void metodoParaRefactorizar(std::string s)
    {
        auto found = callbacks.find(s);
        bool instructionFound = false;
        QJsonDocument jDoc;

        if ((instructionFound = (found != callbacks.end())))
        {
            jDoc = (this->*found->second)();
        }
    }
};

Как ты будешь наблюдать, что он немного некомфортабельный, так как мы должны удваивать призывы к функциям суб-объектов посредством аналогичных функций в главном объекте. Это необходимо, чтобы усреднять все призывы к типу callback (указатель в функцию MiClase что возвращает QJsonDocument и он ничего не получает).

Однако есть у преимущества, что (с моей точки зрения) поддерживать callbacks - очень чистый и интуитивно:

const std::map<std::string, callback> callbacks =
{
    {"instruccionUno",      &MiClase::metodoPublico},
    {"pepito",              &MiClase::getList},
    {"cadenaMolona",        &MiClase::getName},
    {"otraCadenaDiferente", &MiClase::closeAll},
};

Добавлять или удалять цепи - функции - очень просто в карте, которую присоединяет каждая цепь к функции, которая должна быть вызовом.

0
ответ дан 24.11.2019, 12:59