За последние 24 часа нас посетили 23379 программистов и 1519 роботов. Сейчас ищут 788 программистов ...

Миссион импоссибру: распилить 13 тысяч строк кода

Тема в разделе "PHP для новичков", создана пользователем NerdRage, 21 май 2017.

  1. NerdRage

    NerdRage Активный пользователь

    С нами с:
    6 июл 2016
    Сообщения:
    439
    Симпатии:
    42
    Взялся наконец-то за распиливание своего говнокода. Уже раскидал методы из одного класса по четырем, но столкнулся с дилеммой. У меня есть один родительский класс (небольшой), там лежат всякие базовые штуки, которые используются везде + в конструкторе инициализируется всё необходимое. Все другие классы наращиваются на него обычно. То есть, у меня было примерно так:
    PHP:
    1. class typical {
    2.     function __construct() {
    3.         // инициализируем всякое
    4.         // подключаем вордпресс
    5.         // подрубаемся к БД
    6.     }
    7.     // тут типичные штуки для работы с БД, с текстом и т.п.
    8. }
    9.  
    10. class govnokod extends typical {
    11.     function __construct() {
    12.         parent::__construct();
    13.     }
    14.     function aaa() {
    15.         echo 'пример';
    16.     }
    17.     function bbb() {
    18.         $this->aaa();
    19.     }
    20.     function ccc() {
    21.         $this->aaa();
    22.         echo '2';
    23.     }
    24.     // тут 13к строк говнокода
    25. }
    Потом я распилил класс govnokod на два. Получилось так:
    PHP:
    1. class typical {
    2.     function __construct() {
    3.         // инициализируем всякое
    4.         // подключаем вордпресс
    5.         // подрубаемся к БД
    6.     }
    7.     // тут типичные штуки для работы с БД, с текстом и т.п.
    8. }
    9.  
    10. class govnokod extends typical {
    11.     function __construct() {
    12.         parent::__construct();
    13.     }
    14.     function aaa() {
    15.         echo 'пример';
    16.     }
    17.     function ccc() {
    18.         $this->bbb();
    19.         echo '2';
    20.     }
    21.     // тут 13к строк говнокода
    22. }
    23.  
    24. class mlg_code extends typical {
    25.     function bbb() {
    26.         $this->aaa();
    27.     }
    28. }
    Но, как видите, в bbb() идёт обращение к aaa(). А в ccc() идёт обращение к bbb(). И я вот теперь не знаю как всё это структурировать чтобы оно работало. И вот таких мест у меня полно. Как быть? Подключать класс govnokod в каждом методе mlg_code где нужны его методы? А класс mlg_code в методы govnokod, где нужно bbb()? Может можно как-то проще? А то спагетти-код получается.
    --- Добавлено ---
    Если сделать чтобы новый класс mlg_code был дочерним классом govnokod, то это исправит проблему только на половину - все методы в mlg_code будут доступны без подключения чего-то сверху. Но в govnokod используются методы из mlg_code и если попытаться подрубить mlg_code внутри govnokod, то произойдёт следующее:
    1. Выполняется конструктор typical.
    2. Выполняется конструктор govnokod.
    3. Обращаемся к mlg_code.
    4. Опять выполняется конструктор typical.
    5. Опять выполняется конструктор govnokod.
    По-моему такое решение отпадает сразу. Оно может подойти только для классов, в которых используются методы из govnokod, но в govnokod при этом не должны использоваться методы дочернего класса.
     
  2. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    А может здесь стоит наследование заменить на создание экземпляра? Наследование ведь не совсем для того, чтоб в один суперумный класс выносить всё, и потом от него наследовать. Плюс ещё можно рассмотреть трейты
     
  3. NerdRage

    NerdRage Активный пользователь

    С нами с:
    6 июл 2016
    Сообщения:
    439
    Симпатии:
    42
    @mkramer Ну вот через создание экземпляра я сейчас и начал делать, но тоже чушь получается. Распишу:
    PHP:
    1. class typical {
    2.     function __construct() {
    3.         // инициализируем всякое
    4.         // подключаем вордпресс
    5.         // подрубаемся к БД
    6.     }
    7.     // тут типичные штуки для работы с БД, с текстом и т.п.
    8. }
    9.  
    10. class govnokod extends typical {
    11.     function __construct() {
    12.         parent::__construct();
    13.     }
    14.     function aaa() {
    15.         echo 'пример';
    16.     }
    17.     function ccc() {
    18.         require_once('mlg_code.php');
    19.         $mlg = new mlg_code();
    20.         $mlg->bbb();
    21.         echo '2';
    22.     }
    23.     // тут 13к строк говнокода
    24. }
    25.  
    26. class mlg_code extends typical {
    27.     function bbb() {
    28.         require_once('govnokod.php');
    29.         $gk = new govnokod();
    30.         $gk->aaa();
    31.     }
    32. }
    Что имеем в итоге при обращении к методу bbb():
    1. Выполняется конструктор typical.
    2. Обращаемся к govnokod.
    3. Опять выполняется конструктор typical.
    4. Выполняется конструктор govnokod.
    Мало того, что в каждом методе где используется govnokod, придётся подрубать файл и создавать экземпляр, и тоже самое для mlg_code. Так ещё и, как не крути, оба класса наследуются от typical и его конструктор будет выполняться многократно. Трейты - по-моему ещё более запутанная фигня и я не представляю как они могут упростить мою задачу.
     
  4. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Что такое typecal, что от него всё наследуется? Там реально методы, которые должны быть у всех классов в системе, или методы, которыми все классы пользуются?
    --- Добавлено ---
    Может стоит применить этот рефакторинг? https://refactoring.guru/ru/replace-inheritance-with-delegation
     
  5. NerdRage

    NerdRage Активный пользователь

    С нами с:
    6 июл 2016
    Сообщения:
    439
    Симпатии:
    42
    Методы, которыми все классы пользуются. Для работы с БД, для вывода ошибок, для перевода дат с локального времени в UTC, для отправки имейлов и т.п. А в конструкторе инициализируется Вордпресс, подключается к БД, вытаскивается сессия юзера и выставляются его привилегии. Конструктор не тяжёлый и в принципе загружается быстро, но всё-таки это не круто, что он загружается много раз для каждого подключенного класса. Вообще тут идеально сработали бы глобальные переменные. Объявляем все классы по одному разу, экземпляры в глобальные переменные, а потом используем их где надо. Но так ведь делают быдлокодеры, а не программисты?
    --- Добавлено ---
    Что-то я вообще ничего отсюда не понял...
     
  6. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Ну так от него не надо наследовать, его надо использовать. И в синглтон его преобразовать, дёргать инстансы.
     
  7. NerdRage

    NerdRage Активный пользователь

    С нами с:
    6 июл 2016
    Сообщения:
    439
    Симпатии:
    42
    А в чём профит? Всё-равно его придётся в конструкторе каждого класса дёргать, иначе ничего работать не будет.
     
  8. NerdRage

    NerdRage Активный пользователь

    С нами с:
    6 июл 2016
    Сообщения:
    439
    Симпатии:
    42
    Короче углубившись чуть дальше я прихожу к выводу, что распилить это действительно импосибру. Всё используется везде, картина примерно такая:
    PHP:
    1. class typical {
    2.     function __construct() {
    3.         // инициализируем всякое
    4.         // подключаем вордпресс
    5.         // подрубаемся к БД
    6.     }
    7.     // тут типичные штуки для работы с БД, с текстом и т.п.
    8. }
    9.  
    10. class govnokod extends typical {
    11.     function __construct() {
    12.         parent::__construct();
    13.         require_once('mlg_code.php');
    14.         require_once('more_code.php');
    15.         $mlg = new mlg_code();
    16.         $more = new more_code();
    17.     }
    18.     function govno_func() {
    19.         $mlg->mlg_func();
    20.         $more->more_func();
    21.     }
    22.     function govno2() {
    23.         echo 'я не очень';
    24.     }
    25. }
    26.  
    27. class mlg_code extends typical {
    28.     function __construct() {
    29.         parent::__construct();
    30.         require_once('govnokod.php');
    31.         require_once('more_code.php');
    32.         $govno = new govnokod();
    33.         $more = new more_code();
    34.     }
    35.  
    36.     function mlg_func() {
    37.         $govno->govno2();
    38.         $more->more_func();
    39.     }
    40.  
    41.     function esports() {
    42.         echo 'ай эм профешшынал';
    43.     }
    44.  
    45. }
    46.  
    47. class more_code extends typical {
    48.     function __construct() {
    49.         parent::__construct();
    50.         require_once('govnokod.php');
    51.         require_once('mlg_code.php');
    52.         $govno = new govnokod();
    53.         $mlg = new mlg_code();
    54.     }
    55.     function more1() {
    56.         $govno->govno2();
    57.         $mlg->esports();
    58.     }
    59. }
    То есть, обратившись к govno_func() что происходит:
    1. Стреляет конструктор typical
    2. Стреляет конструктор govnokod
    3. Вызывается конструктор mlg_code
    4. Стреляет конструктор typical
    5. Опять стреляет конструктор govnokod
    6. Опять стреляет конструктор mlg_code
    7. Опять стреляет конструктор govnokod
    8. Опять стреляет конструктор mlg_code
    9. ...
    10. PROFIT!?
     
  9. NerdRage

    NerdRage Активный пользователь

    С нами с:
    6 июл 2016
    Сообщения:
    439
    Симпатии:
    42
    Даже если убрать наследование. Вот как быть, когда есть два класса и оба используют методы друг друга?
    PHP:
    1. class govnokod {
    2.     function __construct() {
    3.         // загружается в конструкторе, потому что много методов этого класса используют класс mlg_code
    4.         require_once('mlg_code.php');
    5.         $mlg = new mlg_code();
    6.     }
    7.  
    8.     function govno1() {
    9.         $mlg->mlg_func3();
    10.     }
    11.  
    12.     function govno2() {
    13.         $mlg->mlg_func3();
    14.         echo ' май инглиш из вэри гуд';
    15.     }
    16.  
    17.     function govno3() {
    18.         echo 'я совсем унылое';
    19.     }
    20. }
    21.  
    22. class mlg_code {
    23.     function __construct() {
    24.         // загружается в конструкторе, потому что много методов этого класса используют класс govnokod
    25.         require_once('govnokod.php');
    26.         $govno = new govnokod();
    27.     }
    28.  
    29.     function mlg_func1() {
    30.         $govno->govno3();
    31.     }
    32.  
    33.     function mlg_func2() {
    34.         $govno->govno3();
    35.         echo ' гауно';
    36.     }
    37.  
    38.     function mlg_func3() {
    39.         echo 'ай эм профешшынал';
    40.     }
    41. }
    Создаём экземпляр второго класса в коде и получается, что он выполняет свой конструктор, где вызывает первый класс, а в его конструкторе вызывается второй класс, где опять вызывается конструктор первого класса... Тут кроме как слить два класса в один выхода и нет по-моему.
    --- Добавлено ---
    Получается, единственный способ что-то выпилить из говнокода это вытащить оттуда стопку методов, которые самодостаточны. Они могут обращаться друг к другу, но не к классу с 13 тысячами строк. Такой новый класс можно будет подрубить в конструктор говнокода и ничего при этом не зациклится.
    --- Добавлено ---
    Либо второй сценарий - вытащить в отдельный класс методы, которые НЕ используются в классе с говнокодом из 13 тысяч строк. Такой новый класс можно сделать даже дочерним от говнокода, но обращаться к нему из говнокода уже будет нельзя.
     
  10. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Разделить зависимость, чтоб они использовали третий класс, а не методы друг друга. Двунаправленная зависимость между классами - это очень плохо. Надо создать третий класс. Но тут ещё и я не понимаю, на каком основании вы выбирали классы, и назначали им ответственности.
     
  11. NerdRage

    NerdRage Активный пользователь

    С нами с:
    6 июл 2016
    Сообщения:
    439
    Симпатии:
    42
    С тремя классами пример я тоже выкладывал, там где есть "more_code" - нифига это не сработает, потому что и в третьем классе будут методы, которые используются в других двух и там же вызываются какие-то методы из основного класса. Выбирал методы я по смыслу. В первый файл я вытащил те, которые отвечают за построение HTML-страниц, во второй - формирование и отправка SMS-сообщений (их кстати возможно получится выпилить) и в третий - перевод строк с языка компутеров на язык человеков (БД -> страница). Но придётся походу распиливать не по смыслу, а по сценариям, которые я написал.