Взялся наконец-то за распиливание своего говнокода. Уже раскидал методы из одного класса по четырем, но столкнулся с дилеммой. У меня есть один родительский класс (небольшой), там лежат всякие базовые штуки, которые используются везде + в конструкторе инициализируется всё необходимое. Все другие классы наращиваются на него обычно. То есть, у меня было примерно так: PHP: class typical { function __construct() { // инициализируем всякое // подключаем вордпресс // подрубаемся к БД } // тут типичные штуки для работы с БД, с текстом и т.п. } class govnokod extends typical { function __construct() { parent::__construct(); } function aaa() { echo 'пример'; } function bbb() { $this->aaa(); } function ccc() { $this->aaa(); echo '2'; } // тут 13к строк говнокода } Потом я распилил класс govnokod на два. Получилось так: PHP: class typical { function __construct() { // инициализируем всякое // подключаем вордпресс // подрубаемся к БД } // тут типичные штуки для работы с БД, с текстом и т.п. } class govnokod extends typical { function __construct() { parent::__construct(); } function aaa() { echo 'пример'; } function ccc() { $this->bbb(); echo '2'; } // тут 13к строк говнокода } class mlg_code extends typical { function bbb() { $this->aaa(); } } Но, как видите, в bbb() идёт обращение к aaa(). А в ccc() идёт обращение к bbb(). И я вот теперь не знаю как всё это структурировать чтобы оно работало. И вот таких мест у меня полно. Как быть? Подключать класс govnokod в каждом методе mlg_code где нужны его методы? А класс mlg_code в методы govnokod, где нужно bbb()? Может можно как-то проще? А то спагетти-код получается. --- Добавлено --- Если сделать чтобы новый класс mlg_code был дочерним классом govnokod, то это исправит проблему только на половину - все методы в mlg_code будут доступны без подключения чего-то сверху. Но в govnokod используются методы из mlg_code и если попытаться подрубить mlg_code внутри govnokod, то произойдёт следующее: Выполняется конструктор typical. Выполняется конструктор govnokod. Обращаемся к mlg_code. Опять выполняется конструктор typical. Опять выполняется конструктор govnokod. По-моему такое решение отпадает сразу. Оно может подойти только для классов, в которых используются методы из govnokod, но в govnokod при этом не должны использоваться методы дочернего класса.
А может здесь стоит наследование заменить на создание экземпляра? Наследование ведь не совсем для того, чтоб в один суперумный класс выносить всё, и потом от него наследовать. Плюс ещё можно рассмотреть трейты
@mkramer Ну вот через создание экземпляра я сейчас и начал делать, но тоже чушь получается. Распишу: PHP: class typical { function __construct() { // инициализируем всякое // подключаем вордпресс // подрубаемся к БД } // тут типичные штуки для работы с БД, с текстом и т.п. } class govnokod extends typical { function __construct() { parent::__construct(); } function aaa() { echo 'пример'; } function ccc() { require_once('mlg_code.php'); $mlg = new mlg_code(); $mlg->bbb(); echo '2'; } // тут 13к строк говнокода } class mlg_code extends typical { function bbb() { require_once('govnokod.php'); $gk = new govnokod(); $gk->aaa(); } } Что имеем в итоге при обращении к методу bbb(): Выполняется конструктор typical. Обращаемся к govnokod. Опять выполняется конструктор typical. Выполняется конструктор govnokod. Мало того, что в каждом методе где используется govnokod, придётся подрубать файл и создавать экземпляр, и тоже самое для mlg_code. Так ещё и, как не крути, оба класса наследуются от typical и его конструктор будет выполняться многократно. Трейты - по-моему ещё более запутанная фигня и я не представляю как они могут упростить мою задачу.
Что такое typecal, что от него всё наследуется? Там реально методы, которые должны быть у всех классов в системе, или методы, которыми все классы пользуются? --- Добавлено --- Может стоит применить этот рефакторинг? https://refactoring.guru/ru/replace-inheritance-with-delegation
Методы, которыми все классы пользуются. Для работы с БД, для вывода ошибок, для перевода дат с локального времени в UTC, для отправки имейлов и т.п. А в конструкторе инициализируется Вордпресс, подключается к БД, вытаскивается сессия юзера и выставляются его привилегии. Конструктор не тяжёлый и в принципе загружается быстро, но всё-таки это не круто, что он загружается много раз для каждого подключенного класса. Вообще тут идеально сработали бы глобальные переменные. Объявляем все классы по одному разу, экземпляры в глобальные переменные, а потом используем их где надо. Но так ведь делают быдлокодеры, а не программисты? --- Добавлено --- Что-то я вообще ничего отсюда не понял...
Ну так от него не надо наследовать, его надо использовать. И в синглтон его преобразовать, дёргать инстансы.
А в чём профит? Всё-равно его придётся в конструкторе каждого класса дёргать, иначе ничего работать не будет.
Короче углубившись чуть дальше я прихожу к выводу, что распилить это действительно импосибру. Всё используется везде, картина примерно такая: PHP: class typical { function __construct() { // инициализируем всякое // подключаем вордпресс // подрубаемся к БД } // тут типичные штуки для работы с БД, с текстом и т.п. } class govnokod extends typical { function __construct() { parent::__construct(); require_once('mlg_code.php'); require_once('more_code.php'); $mlg = new mlg_code(); $more = new more_code(); } function govno_func() { $mlg->mlg_func(); $more->more_func(); } function govno2() { echo 'я не очень'; } } class mlg_code extends typical { function __construct() { parent::__construct(); require_once('govnokod.php'); require_once('more_code.php'); $govno = new govnokod(); $more = new more_code(); } function mlg_func() { $govno->govno2(); $more->more_func(); } function esports() { echo 'ай эм профешшынал'; } } class more_code extends typical { function __construct() { parent::__construct(); require_once('govnokod.php'); require_once('mlg_code.php'); $govno = new govnokod(); $mlg = new mlg_code(); } function more1() { $govno->govno2(); $mlg->esports(); } } То есть, обратившись к govno_func() что происходит: Стреляет конструктор typical Стреляет конструктор govnokod Вызывается конструктор mlg_code Стреляет конструктор typical Опять стреляет конструктор govnokod Опять стреляет конструктор mlg_code Опять стреляет конструктор govnokod Опять стреляет конструктор mlg_code ... PROFIT!?
Даже если убрать наследование. Вот как быть, когда есть два класса и оба используют методы друг друга? PHP: class govnokod { function __construct() { // загружается в конструкторе, потому что много методов этого класса используют класс mlg_code require_once('mlg_code.php'); $mlg = new mlg_code(); } function govno1() { $mlg->mlg_func3(); } function govno2() { $mlg->mlg_func3(); echo ' май инглиш из вэри гуд'; } function govno3() { echo 'я совсем унылое'; } } class mlg_code { function __construct() { // загружается в конструкторе, потому что много методов этого класса используют класс govnokod require_once('govnokod.php'); $govno = new govnokod(); } function mlg_func1() { $govno->govno3(); } function mlg_func2() { $govno->govno3(); echo ' гауно'; } function mlg_func3() { echo 'ай эм профешшынал'; } } Создаём экземпляр второго класса в коде и получается, что он выполняет свой конструктор, где вызывает первый класс, а в его конструкторе вызывается второй класс, где опять вызывается конструктор первого класса... Тут кроме как слить два класса в один выхода и нет по-моему. --- Добавлено --- Получается, единственный способ что-то выпилить из говнокода это вытащить оттуда стопку методов, которые самодостаточны. Они могут обращаться друг к другу, но не к классу с 13 тысячами строк. Такой новый класс можно будет подрубить в конструктор говнокода и ничего при этом не зациклится. --- Добавлено --- Либо второй сценарий - вытащить в отдельный класс методы, которые НЕ используются в классе с говнокодом из 13 тысяч строк. Такой новый класс можно сделать даже дочерним от говнокода, но обращаться к нему из говнокода уже будет нельзя.
Разделить зависимость, чтоб они использовали третий класс, а не методы друг друга. Двунаправленная зависимость между классами - это очень плохо. Надо создать третий класс. Но тут ещё и я не понимаю, на каком основании вы выбирали классы, и назначали им ответственности.
С тремя классами пример я тоже выкладывал, там где есть "more_code" - нифига это не сработает, потому что и в третьем классе будут методы, которые используются в других двух и там же вызываются какие-то методы из основного класса. Выбирал методы я по смыслу. В первый файл я вытащил те, которые отвечают за построение HTML-страниц, во второй - формирование и отправка SMS-сообщений (их кстати возможно получится выпилить) и в третий - перевод строк с языка компутеров на язык человеков (БД -> страница). Но придётся походу распиливать не по смыслу, а по сценариям, которые я написал.