Pull to refresh

Вы препарируете труп используя SOLID

Reading time5 min
Views8.8K
Как говорится «это безумие, делая снова и снова одно и тоже, ничего при этом не меняя, надеяться на какой-нибудь другой результат». Но порой используя одни и те же подходы, утверждения и действия для получения, казалось бы, предсказуемого результата, человек искренне удивляется почему не вышло на этот раз.

Есть область где подобное действия не только вызывали бы скептицизм, но могут преподносится как единственно верные – объектно-ориентированное программирование.

Начнем мы, как и положено, с самой слабой из парадигм «принципов SOLID», которые хорошо, что в граните не выбиваю. Приготовитесь много букв…

Дадим краткое определение: SOLID сокр. от англ. single responsibility, open-closed, Liskov substitution, interface segregation и dependency inversion. Т.е. достаточно небольшой набор принципов из всего многообразия, но проводящие четкие границы между тем что можно делать, что лучше не делать, а что надо точно переделывать в Вашем проекте.

Начнем.

Принцип подстановки Барбары Лисков


L, LSP, Liskov substitution principle
«объекты в программе должны быть заменяемыми на экземпляры их подтипов без изменения правильности выполнения программы»

Один из самых слабых и не выполнимых принципов, предписывающий что мы можем заменить абстракцию на её подтип, при этом ничего не должно произойти. Мне даже сложно представить, что-то более далекое от реальности и не возможное выполнить уже из самого определения. (Очень интересно услышать бы определение «правильности выполнения программы», но Нам это и не потребуется).

Для буквоедов
Дословное утверждение звучало примерно как:

Subtype Requirement: Let f(x) be a property provable about objects x of type T. Then f(y) should be true for objects y of type S where S is a subtype of T.

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

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

Пойдем дальше.

Размер потребляемых ресурсов: памяти, процессорного времени, используемых ядер, необходимость или отсутствие доп. оборудования.

Иногда замена одной сущности, к примеру, способа логирования из файла в базу данных требует не тривиальных вещей: подключения дополнительных библиотек, изменения конфигурационных файлов (Предвижу спор, считать ли конфигурационный файл частью, подпадающей под этот принцип или нет).

Если конечно покопать, то конечно можно уменьшить требования: мол не для всех типов, не для всех свойств, да и не всегда. Но тогда и суть принципа очень размыта. Что-то из разряда «Вы можете переходить только на зелёный свет, но если сломался светофор … или в прямой видимости на расстоянии двух километров не видно машин … или пролетает единорог ^_^''»

Как проектировщики или разработчики Мы уже идем на риск (часто оправданный) нарушая Принцип подстановки Барбары Лисков когда оптимизируем или рефакторим код.

Данный принцип не выполним никогда, простая замена Int32 на Int64 уже делает его не выполнимым. Надеюсь обратная замена Int64 на Int32 не вызывает ни у кого сомнений его нарушения.

Фанатично придерживаясь его, Вы создается что-то уже «мертвое», поскольку оно не «дышит» при рождении и не когда не задышит после. Вы сами с завидным упорством будете отрезать всё «лишнее», чтобы не менять поведения нового. Однажды создав нечто, Вы обречены создавать тоже и в будущем. Поздравляю Вас, Вы создали труп и бережно следите за множеством рук в резинных перчатках.

Принцип открытости/закрытости


O, OCP, Open/closed principle
«программные сущности… должны быть открыты для расширения, но закрыты для модификации»

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

Возможно Вас утешает что можно изменить код: до тестирования, до передачи в продакшен, до выпуска версии, до … (выберите несколько, или подчеркните нужное, или допишите своё). Не важно, у Вас всегда будет это «ДО». Слабое утешение в системах, жизнь которых не исчисляется часами и неделями, а длиться годами.

Вы когда-нибудь наблюдали чтобы в природе, что-то развивается «до»? Не вырастает дерево два метра ровно, всегда чуть выше, чуть ниже. И пока его не срубят будет расти, какая-то ветка засохнет, какая-то разовьётся. Единственно что не достижимо в реальном мире – постоянство.

Зачем далеко ходить: C => C++ => (Java =>) C# и Java => Scala => Kotlin попытки избежать эту проблему, а не решить. Вынужденные придерживаясь это принципа Вы рано или поздно сядете и перепишите всё, если, конечно, к тому времени Ваш проект уже не протух настолько, что его закопали.

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

Оставшиеся принципы можно оставить для следующей статьи (если конечно она последует)…

Вывод прозаичен. Современная разработка походит на создание в кунсткамерах тупиков и дружное их препарирование в процессе создания, внедрения и сопровождения проектов. Поэтому часто даже самого понятия «утилизации» (завершение, снятия с эксплуатации) нет во многих жизненных циклах методологий. Или им уделяется пара параграфов (Для примера посмотрите на библиотеки по хирургии, когда действительно стараются оставить в «живых»).

Зачем писать о том, что и так уже было создано и так тщательно скрывается, дезодорируется и препарируется. Когда каждому из участников действия, кому раньше, кому позже, становится ясно что «пора».

Надежда?


Но что делать, спросите Вы? (Если конечно дочитали и задумались). Создание «мутантов» тоже не выход. Если нечто изменяет своё поведение непредсказуемо, без надобности, то обычно оно либо умирает само, либо его удаляют.

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

Если кто-то обошел вашу «фичу» лучше пусть он удалить этот костыль, ставший не нужным, чем Вы дальше будете с упорством продолжать поддерживать ставшее ошибочным решение. (Хорошая аналогия с пациентом, не желающим оставить ставшие не нужными костыли после снятия гипса, он же к ним привык. Удобно, а нога болит при ходьбе)

Если кто-то (клиент, менеджер, PM) требует остаться на месте, заведите для него версию и пусть препарирует, помогайте иногда ему (особенно если он платит). Но не стесняйтесь показывать более удачное решение. Дайте человеку шанс изменить решения.

Не уходите в бесконечный цикл. Нет смысла оправдываться отсутствием результата желанием создать вечное, это невозможно. Создайте малое, но нужное сейчас и «живое».

Остерегайтесь, когда в следующий раз Вы будите обучать, наставлять и требовать выполнение поставленных задач. Посмотрите не глядит ли Вам в глаза «безумец», который будет «препарировать труп» в полной уверенности что спасает «мир».

Не создавайте трупы. Развивайтесь или умрите.
Tags:
Hubs:
Total votes 62: ↑23 and ↓39-16
Comments85

Articles