Статьи

Требуется пакет по функции

В комментариях DZone под моим постом о многоуровневой архитектуре некоторые люди полагали, что расслоение должно быть реализовано как то, что я называю « Упаковка по функциям» . Я намеренно отложил писать об этом, чтобы  сначала покрыть шестиугольники и лук, но теперь, когда они у нас есть, мы можем прыгнуть прямо в столь востребованный архитектурный стиль.

Что такое пакет по функции?

В типичной многоуровневой архитектуре организация кода следует горизонтальной декомпозиции, созданной путем разделения системы на слои. Это то, что часто называют  Package by Layer .

Проблема этого подхода заключается в том, что когезия внутри каждой упаковки обычно низкая, а связь между упаковками очень высокая. Это похоже на то, что мы хотим достичь. В то же время большинство людей сходятся во мнении, что разделение задач представления, приложения, домена и инфраструктуры имеет смысл.  Package by Feature  использует обе точки, перемещая уровень на уровень вниз — до уровня класса — и концентрируясь на соединении и связности на более высоком уровне, сохраняя все классы, связанные с одной и той же  функцией,  в одном пакете / модуле:

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

Суть пакета по особенностям

Я вижу две вещи, которые формируют суть  Package by Feature : поддержание высокой когезии и низкой связи на уровне пакета / модуля и возможность сказать, что делает приложение, глядя на его структуру пакета / модуля.

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

Два приведенных выше термина полезны, но, если честно, это метрики ботаников. Более человеческая сторона  Package by Feature заключается в том, что вам не нужно быть ботаником, который знает каждый фрагмент кодовой базы, чтобы иметь возможность сказать, что он делает — быстрый взгляд на структуру пакета / модуля скажет вам об этом. Это один шаг к тому, что дядя Боб называет «  Кричащей архитектурой» .

package com.ecommerce.catalog; // enables user to browse the products
package com.ecommerce.checkout; // enables user to make an order
package com.ecommerce.orders; // enables the shop to process the orders

Реализация пакета по функциям

Название  Package by Feature настоятельно рекомендует вам реализовать этот стиль, поместив каждую функцию в отдельный пакет, и это в основном так. Единственное предостережение, которое я вижу, это то, что это может быть также модуль, пространство имен или любой другой механизм, доступный на вашем языке, если вы не используете Java.

Вторая важная вещь в  Package by Feature состоит в том, что когда связанные вещи находятся в одном пакете, можно, наконец, использовать модификаторы доступа, то есть сделать большинство вещей локальными, а не общедоступными. Таким образом, мы можем ограничить общедоступный интерфейс нашей функции только теми вещами, которые мы действительно хотим показать. В стиле  Package by Layer это было невозможно, потому что связанные классы должны были взаимодействовать между пакетами, что вынуждает нас делать все общедоступным.

пример

Несмотря на то, что я чувствую, что Spring Pet Clinic — не лучший ресурс для изучения разработки программного обеспечения, она довольно неплохо представляет презентацию  Package by Feature . В  особенности , в этом случае представляют собой наборы операций , выполняемых на тех же объектов предметной области:

Как видите, у нас есть три доминирующие функции — управление владельцами, ветеринарами и визитами. Является ли это разложение на особенности хорошим или нет, это очень сложная тема. На данный момент, мы должны сосредоточиться на том , что классы , представляющие различные слои , такие как контроллеры, хранилище и объекты предметной области все держались вместе, и что структура пакета больше  функции ориентированной.

Преимущества пакета по функции

  • Более информативная структура пакета  — вы можете вывести некоторые основные функции или поведение системы из структуры кода
  • High Cohesion & Low Coupling — мы объяснили этот момент уже в основной части, хотя и немного идеалистически
  • Лучшая инкапсуляция  — вы можете эффективно использовать модификаторы доступа, чтобы скрыть информацию, которая должна оставаться скрытой
  • Лучший потенциал роста , в смысле объема кода — если вы не разрабатываете слишком большие или слишком маленькие функции , вы не должны сталкиваться с проблемой слишком большого или слишком большого количества пакетов

Недостатки пакета по особенностям

  • Unspecified Feature Size  — я не нашел четких указаний или доказательств того, что одно понимание  функции лучше, чем другое
  • Кривая обучения  — концепция проста, но поскольку вам нужно найти свой собственный способ разбить систему на функции , освоить ее может быть очень сложно
  • Потенциал беспорядка  — в запутанной области, в которой все связано со всем, разделение на функции может стать искусственным, и обещание низкой связи может не быть выполнено

Когда использовать пакет по функции?

Очевидно, что он может работать для небольших приложений, в которых вы можете перетасовать вещи и пробовать разные вещи по очень низкой цене. В то же время, поскольку он обещает более высокую когезию , более низкое сцепление и лучший потенциал роста, он идеально подходит для более крупных применений, которые могут фактически страдать от недостатков  упаковки за слоем . Учитывая его умеренную кривую обучения, то есть необходимость выбора лучшего определения  функции , я бы с осторожностью использовал ее впервые при работе с критически важным приложением. Я бы предпочел разделить проблему на ограниченные контексты и реализовать каждый из них слоистым / гексагональным способом.

Резюме

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