Дублирование кода или создание универсальных компонентов?

2024-01-23 22:23:15 Время чтения 8 мин 175

Исходная задача - проекты исполнителей и заказчиков. Представьте ситуацию. У вас есть 3 роли - Заказчик, Исполнитель, Администратор, Все 3 роли имеют свой профиль, а также работают с некой сущностью проект.

Вам нужно выводить для каждой роли Список доступных ему проектов, страницу проекта, а также дать возможность редактирования своих данных.

Как вы сделаете разбиение по компонентам.Самое простое, что напрашивается - реализовать для всех ролей:

  1. editProfile - форма изменения профиля
  2. project - форма проекта
  3. projects - таблица проектов.

Всего 3 компонента, которые все обслуживают. Красота.

Если думать с точки зрения того, кто создает это и пытается уменьшить свои трудозатраты, то возможно.

С точки зрения того, кто это будет потом поддерживать и развивать - это ужасное решение.

Почему это решение плохое:

  1. Каждая роль будет иметь свои нюансы (например, Заказчик и Админ могут редактировать некоторые поля проекта). Это создаст некоторые ветвления бизнес-логики.
  2. Созданные ветвления и нюансы доступа создают риски по несанкционированному доступу (в код где-то закралась ошибка, и Заказчик получает какую-то функцию Админа в форме проекта).
  3. При изменениях нужно распутывать весь клубок с учетом работы всех ролей на этой форме. К примеру, хотим добавить новое поле (например, заметки Заказчика по проекту) - значит сразу должны учесть эту бизнес-логику для других ролей, которых вообще никаким боком она не касается. Но у них доступ есть к этой форме, а значит это нужно обработать.
  4. Любое изменение в такой монстр-форме - это обязательное тестирование под всеми ролями, т.к. изменение для одной роли может повлечь изменение для другой роли.
  5. Зачастую для Заказчика, Исполнителя есть правки дизайна, стилистики (т.к. это обложка), и они совершенно не нужны админу.

Как я предлагаю решать подобную задачу

Важно сразу учитывать, как будет развиваться компонент. Например, попробовать предсказать развитие формы проекта для Заказчика - что там может добавиться, что измениться.

Что очевидно - формы для Заказчика, Исполнителя и Администратора будут развиваться совершенно по-разному.Если бы у нас была еще роль Модератор, то скорее всего можно предположить, что форма будет примерно одинаково развиваться с Администратором.

Предлагаю сделать такое разбиение:

  1. Редактирование профиля Админа;
  2. Редактирование профиля Заказчика;
  3. Редактирование профиля Исполнителя;
  4. Таблица проектов Админа;
  5. Таблица проектов Заказчика;
  6. Таблица проектов Исполнителя;
  7. Форма проекта Админа;
  8. Форма проекта Заказчика;
  9. Форма проекта Исполнителя.

Изначально это кажется избыточным и сложным. Но именно это рождает простоту дальнейшей поддержки и развития проекта.Даже если какие-то формы на начальном этапе очень похожи (например, профиль Заказчика и Исполнителя), в будущем они "разойдутся" в разные стороны.Какие минусы этого решения: надо создать больше компонентов.

А теперь про плюсы (по аналогии со списком выше):

  1. Компоненты будут максимально простыми, они учитывают только одну роль, минимум ветвлений + мы изначально знаем, кто пришел, его права и обязанности относительно сущности.
  2. В компоненте мы сразу можем идентифицировать пользователя и проверять доступ к конкретным объектам. Ниже риски ошибок доступа.
  3. Изменения касаются только одной роли - проще разобраться, что менять.
  4. При изменениях нет риска задеть что-то для других ролей. Меняем для админа - можем быть уверенными, что ничего не упадет у Заказчика.
  5. Разметка формы под конкретную роль - меньше кода и заточка именно под эту роль без учета других ролей.

И что? Теперь создавать N ролей * K форм компонентов?

В данном примере да, но в общем случае нужно рассуждать исходя именно из будущих изменений и функций блока для конкретной роли.

В каких случаях делать компонент X отдельно для ролей A и B:

  1. роли A и B кардинально разные. Имеют разные доступы и в целом в системе имеют разные цели;
  2. роли A и B будут по-разному развиваться (к примеру, роль Заказчик и Агентство-Заказчик - в целом похожи, но функционал второй роли явно будет в будущем шире);
  3. бизнес-логика по работе компонента для ролей A и B будет разная.

В каких случаях можно делать один компонент на двоих:

  1. роли очень похожи относительно этого компонента (Модератор, Админ);
  2. роли будут в дальнейшем развиваться похожим образом в отношении этого компонента;
  3. доступ ролей в целом похож, и не будет больших рисков даже в случае несанкционного доступа одной роли.

В целом, вопрос только в будущих причинах изменения компонента. Например, в системе бух захотел изменить что-то в своем интерфейсе. А это затрагивает почему-то формы в кабинете Клиента - это не очень хорошо. В идеале это должно влиять только на формы буха и не трогать "чужие" компоненты.

Важно. Не стоит думать, что, если вы создали 2 очень похожих формы для разных ролей, которые будут развиваться по-разному - это дублирование кода. Это не разные объекты в системе, и у каждой свой путь развития. В целом, и человек на ранней стадии не сильно отличается от других животных, но это не значит, что это одно и то же. Стол и стул - дублирование? Нет. Они чем-то похожи, но у них разное назначение, и развились они исторически по-разному. Вполне возможно в допотопные времена они изначально были очень похожи, а потом постепенно стали изменяться под возникающие потребности.

Особенности подхода по созданию отдельных компонентов под роль

Разделение на компоненты не должно вызывать дублирование кода в плане типовых действий. Их можно вынести в отдельные функции или хранимые процедуры (если мы говорим про SQL).

Читайте подробнее про качество кода программы.

Также некие дополнительные возможности для отдельных ролей можно просто добавлять как доп компонент. К примеру, форма проекта для Модератора и Администратора может быть одна. Но у Админа есть на форме еще дополнительные формы и таблицы для более плотного управления (и эти таблицы, формы уже доступны только Админу).

Заключение

Подобный подход значительно упростит поддержку системы.

Универсальный подход только в теории выглядит красиво, на практике поддерживать такой проект с кучей универсальных монстр-компонентом - это хождение по минному полю.

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

Принимайте правильные решения, и это упростит ваш продукт, а значит уменьшит расходы на сопровождение в перспективе.

Источник: https://falconspace.ru/blog/naskolko-dolzhen-byt-universalnym-komponent-v-programmnom-produkte