Архитектура: Packaging

Packaging


Рано или поздно любой программный продукт потребует изменней. Простота внедрения изменений напрямую зависит от того тренда и принципов построения продукта, который был определен при инициации проекта. Чем более понятным, простым и управляемым будет архитектура, там успешнее и живучее будет сам продукт!

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

Для того, чтобы избежать подобной “архитектурной” проблемы, необходимо заранее правильно ее определить и неукоснительно следовать намеченному пути. Ключевыми помощниками могут выступить инкаплуляция (Encapsulation), низкая взаимозависимость элементов (Low Coupling) и (High Cohesion).

Encapsulation

Довольно простая идея - реализация функции приложения сокрыта от ее клиента. Клиент требует исполнителя (приложение) выполнить нелое действие, ожидая результата определенного вида или уведомление об ошибке.

Low Coupling

Высокая взаимозависимость характеризуется чрезмерными зависимостями между различными компонентами, что приводит к огромным издержкам при малейших изменениях. Иногда, даже, изрядное тестирование не исправляет ситуацию. Низкая взаимозависимость позволяет, наоборот, добиться гибкости и управляемости. Кроме того, логику приложения проще понять, а так же покрыть “ценными” тестами (которые действительно тестируют бизнес-кейсы, а не просто покрывают код).

High-Cohesion

Целостность показывает насколько хорошо элементы в рамках одного модуля образуют целостную бизнес-единицу, которая полностью выполняет ту или иную задачу. Модули с хорошей целостностью (High-Cohesion) привносят высокую заменяемость и позволяют избежать дублирований.

Стурктурные элементы

Указанные выше характеристики кода больше относятся к классам (если мы говорим об объектно-ориентированном программировании), далее будут именоваться юнитами (Unit). Зачастую их группируют по какому-то принципу, объединяя в пакеты (Package), иногда именуемые модули, (Module) (если они выполняют бизнес-функции) или компоненты (Component), (если они исполняют роль субъекта). Все эти элементы так или иначе связаны между собой и чем меньше будет между ними взаимозависимость (Low Coupling) и чем выше целостность каждого элемента (High-Cohesion), тем лучше:

  1. Упрощает внедрение изменений
  2. Позволяет распределять ответственных членовы команды на элементы (крупные, конечно), в которых они чувствуют большую уверенность
  3. Меньше конфликтов в разработке (в программных элементах, а следовательно, и между членами команды)
  4. Элементы становятся более управляемыми и поддерживаемыми

Принципы пакетирования

Robert C. Martin выводит следующие принципы:

  • Взаимозависимость (Coupling)
    • Acyclic Dependencies Principle, ADP - Зависимости можду элементами не могут быть взаимными! Иерархия элементов архитектуры лучше изображать в виде древовидной системы, которая носит название Direct Acyclic Graph, DAG;
    • Stable Dependencies Principle, SDP - лучше опираться на стабильные элементы, особенно если речь идет про внешние элементы (например, используемые библиотеки);
    • Stable Abstractions Principle, SAP - между уровнем абстракции элемента и уровнем его стабильности существует прямая связь - чем элемент стабильнее, тем он абстрактнее. Если элемент имеет мало связей и внешних зависимостей, он будет считаться более авбстрактным, но, вместе с этим, и более стабильным.
  • Целостность (Cohesion)
    • Reuse Equivalency Principle, REP - помимо очевидного, избегания дублирования кода, следует рассматривать элементы как детали конструктора, которые могут быть применены в том или ином месте, а потребитель этих элементов не должен волноваться за их содержимое - он просто пользователь, который хочет получить доступ к определенной функции и решить собственную задачу. Это говорит о том, что каждый элемент должен быть легко интегрируемым другими элементами;
    • Common Closure Principle, CCP - классы, объединенные в пакеты, модули или компоненты, являются единым целым и повторное их использование влечет за собой использование всего элемента. Безусловно, уровень использования элемента может различаться, что накладывает дополнительные требования к декомпозиции (атомизации) элементов;
    • Common Reuse Principle, CRP - изменение, которое касается одного юнита (Unit) [может] влечет к изменению всех или части юнитов (Unit) в рамках элемента. Но за границы определенного уровня изменения выходить не должны.

Именование

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

Литература

2008 – Johannes Brodwall – Package by feature
2012 -Johannes Brodwall – How Changing Java Package Names Transformed my System Architecture
2012 – sivaprasadreddy.k – Is package by feature approach good?
2013 – Lahlali Issam – Lessons to Learn from the Hibernate Core Implementation
2013 – Manu Pk – Package your classes by Feature and not by Layers
2015 – Simon Brown – Package by component and architecturally-aligned testing
2015 – César Ferreira – Package by features, not layers
2017* – javapractices.com – Package by feature, not layer

 Comments
Comment plugin failed to load
Loading comment plugin