Зачем ограничивать наследование с помощью final? Часть 4. Заключение

Зачем ограничивать наследование с помощью final? Часть 4. Заключение

https://habr.com/ru/post/482154/


Часть 1 тут

https://telegra.ph/Zachem-ogranichivat-nasledovanie-s-pomoshchyu-final-01-08


Часть 2 тут

https://telegra.ph/Zachem-ogranichivat-nasledovanie-s-pomoshchyu-final-CHast-2-01-08


Часть 3 тут

https://telegra.ph/Zachem-ogranichivat-nasledovanie-s-pomoshchyu-final-CHast-3-01-08


Заключение


Итак, мораль сей статьи такова: добавляйте к своим классам final по умолчанию! А лучше настройте шаблон в своей IDE, чтобы это происходило автоматически.


Кажется, что это лишь незначительное ограничение на наследование, но оно существенно влияет на развитие архитектуры приложения. И влияет в лучшую сторону – в направлении к SOLID и слабому зацеплению. Связь между элементами в классе усиливается, а сами классы становятся похожи на компактные зафиналенные блоки, поддающиеся тестированию и готовые к использованию в других местах кода.


Однако, путь агрегации не легок и требует четкого следования принципам ослабления зависимостей. Теперь вам следует:


  • явно формировать контракт взаимодействия между классами и оформлять его в коде в виде интерфейса;
  • использовать только final классы, которые, при необходимости, реализуют поведение некоторых контрактов;
  • использовать агрегацию для зацепления классов и внедрять зависимости в конструктор через интерфейс.


И суть не в том, чтобы следовать каким-то установленным формальным правилам и придуманным кем-то принципам. Вы тратите большую часть своего времени на анализ и обслуживание ранее написанного кода. И от его качества напрямую зависит скорость разработки и внедрения фич. Каждый раз, когда я видел в коде нарушение базовых принципов построения слабозацепленного дизайна, например, повсеместное использование наследования и нарушение инкапсуляции, это выливалось в конце концов в его полный рефакторинг. Хотя бы потому, что неизолированные блоки кода не поддаются тестированию. Разве у вас есть лишнее время переписывать код?


Возможно вам кажется, что все эти модные принципы – всего лишь теоретические формулировки, не имеющие отношения к реальности. Однако построение архитектуры на интерфейсах и final классах имеет конкретный практический смысл. Борьба со сложностью системы и сокращение когнитивной нагрузки (cognitive load) – вот ради чего мы выполняем декомпозицию системы на изолированные блоки. И слабое зацепление классов – один из важных шагов в этом направлении.


Теперь вы можете разделить процесс проектирования на два этапа: выделение интерфейсов и их реализация в виде final классов. На первом этапе вы размышляете на уровне контрактов и взаимоотношений между классами. На втором – на уровне конкретной изолированной реализации контракта. Это позволяет сосредоточиться на небольшом количестве деталей одновременно. Ведь мы не в состоянии держать в голове одновременно слишком много сущностей. И при увеличении количества, сложность их совместного поведения растет экспоненциально. А значит, растет и число случайных ошибок.


Начните использовать final как один из важных инструментов построения кодовой базы. Вам понравится твердая (SOLID) архитектура без всяких хрупких (fragile) классов. А вашему проджект менеджеру понравится скорость внедрения новых фич, которые не поломали ничего вокруг себя.


Report Page