Пример рефакторинга «извлечение метода» для устранение дублирования при формировании массива информации


Исходный код

function GetNext($bTextHtmlAuto=true, $use_tilda=true)
{
    $res = parent::GetNext($bTextHtmlAuto, $use_tilda);
    if($res)
    {
        if(strlen($res["IBLOCK_ID"])>0)
        {
            $res["LIST_PAGE_URL"] =
                str_replace("//", "/",
                    str_replace("#LANG#", $res["LANG_DIR"],
                        str_replace("#SITE_DIR#", SITE_DIR,
                            str_replace("#SERVER_NAME#", SITE_SERVER_NAME,
                                str_replace("#IBLOCK_ID#", $res["IBLOCK_ID"], $res["LIST_PAGE_URL"])
                            )
                        )
                    )
                );

            if(array_key_exists("DETAIL_PAGE_URL", $res))
                $res["DETAIL_PAGE_URL"] = CIBlock::ReplaceDetailUrl($res["DETAIL_PAGE_URL"], $res, true);
            if(array_key_exists("SECTION_PAGE_URL", $res))
                $res["SECTION_PAGE_URL"] = CIBlock::ReplaceDetailUrl($res["SECTION_PAGE_URL"], $res, true);
        }
        else $res["LIST_PAGE_URL"] =
                str_replace("//", "/",
                    str_replace("#LANG#", $res["LANG_DIR"],
                        str_replace("#SITE_DIR#", SITE_DIR,
                            str_replace("#SERVER_NAME#", SITE_SERVER_NAME,
                                str_replace("#IBLOCK_ID#", $res["ID"], $res["LIST_PAGE_URL"])
                            )
                        )
                    )
                );
    }
    return $res;
}

Как улучшить исходный код

Тут дважды повторяется реализация алгоритма для получения LIST_PAGE_URL. Это одновременно и дублирование реализации, и отдельное знание о деталях формирования LIST_PAGE_URL.

Как извлечь этот алгоритм в отдельную функцию, я уже показывал в рефакторинге за 14 июля.

Для начала перепишу исходный код с применением функции interpolateURL.

function GetNext($bTextHtmlAuto=true, $use_tilda=true)
{
    $res = parent::GetNext($bTextHtmlAuto, $use_tilda);
    if($res)
    {
        if(strlen($res["IBLOCK_ID"])>0)
        {
            $res["LIST_PAGE_URL"] = interpolateURL($res["LIST_PAGE_URL"], $res["LANG_DIR"], $res["IBLOCK_ID"]);

            if(array_key_exists("DETAIL_PAGE_URL", $res))
                $res["DETAIL_PAGE_URL"] = CIBlock::ReplaceDetailUrl($res["DETAIL_PAGE_URL"], $res, true);
            if(array_key_exists("SECTION_PAGE_URL", $res))
                $res["SECTION_PAGE_URL"] = CIBlock::ReplaceDetailUrl($res["SECTION_PAGE_URL"], $res, true);
        }
        else
            $res["LIST_PAGE_URL"] = interpolateURL($res["LIST_PAGE_URL"], $res["LANG_DIR"], $res["ID"]);
    }
    return $res;
}

В целом, на этом можно и остановиться, так как в получившемся варианте никакого дублирования и лишних знаний уже нет.

Теория