У ООП-программистов есть две профессиональных болезни: наследование и методы. Нет ничего более поганого, чем наследование. Наследованием пытаются имитировать древовидную логическую структуру, когда вышестоящий объект заключает в себе некие базовые особенности, а дочерние объекты реализуют частные отличия.
Лютый ад и баттхерт начинается, когда надо породить объект, не только включающий в себя особенности сразу нескольких дочерних классов, но и имеющий парочку совсем маааленьких отличий. Выкинь наследование из своего проекта, будь мужиком, блеать! Используй behaviour injection. Или хотя бы DI, тем более что в нормальных фреймворках оно по-дефолту встроено.
Вторая лютая болезнь – это методы, обозначающие действия объекта (или над объектом). Во-первых, вечный холивар “Земля копайся”, когда люди спорят может ли объект выполнять действия *над собой* или *над ним* выполняет действия некий вышестоящий объект-менеджер. Во-вторых, и самое главное, в юную девелоперскую головку никак не ложится мысль, что само *действие*, которое привело объект из состояния A в состояние B, – это тоже объект.
Да-да, объект, который может быть сохранён в базу данных, у которого может быть дата-время (когда действие произошло), у него может быть инициатор (кто произвёл действие) и масса других параметров. И более того, действие-как-объект может быть применено многократно к другим объектам с воспроизводимым результатом, либо откачено назад в случае проблем.
Более того, исходный объект с наложенными на него действиями представляет собой историю – отличную аналитическую базу для понимания того, когда и что с объектом происходило, а всё вместе представляет собой “матрёшку”, слоистый пирог, в котором текущее состояние объекта сложено из слоёв действий над ним.
Выпили из своего проекта все действия кроме CRUD, будь мужиком, блеать!