Лучшие практики для API Gradle против реализации в многомодульном проекте - PullRequest
0 голосов
/ 06 февраля 2019

Это не часто задаваемый вопрос о разнице между api и implementation, и, будем надеяться, будет более продвинутым и интересным с точки зрения разработки многомодульного проекта.

Позвольтескажем, у меня есть следующие модули в приложении

  • library
  • base
  • feature1
  • feature2
  • app

Теперь отношения между модулями:

base обертывания library

feature1 и feature2использовать (зависит) от base

app, соединяющих feature1 и feature2

Все в этой многомодульной структуре должно работать с использованием зависимостей Gradle implementationи не нужно нигде использовать выражение api.

Теперь, скажем, feature1 требуется доступ к деталям реализации base, включенным в library.

.чтобы сделать library доступным для feature1, насколько я могу судить, у нас есть два варианта:

  1. Изменить implementation на api in base для утечки зависимости к модулям, которые зависят от base

  2. Добавьте library как implementation зависимость к feature1 без утечки base зависимостина library

Конечно, пример был упрощен ради вопроса, но вы понимаете, как это может стать адом конфигурации с большим количеством модулей с 4 или 5уровни зависимостей.

Мы могли бы создать промежуточный модуль base-feature, который может обернуть base и обеспечить другой уровень абстракции для feature1 для потребления без утечки library, но давайте оставим это решение внеОбъем этой проблемы сосредоточен на настройке зависимостей.


Некоторые компромиссы , которые я обнаружил в описанных выше опциях:

Вариант 1)Плюсы

  • Меньшие файлы build.gradle, так как нет необходимости повторять implementation пункты
  • Более быстрые правки сборок скриптов.Просто внесите одно изменение в предложение api и просмотрите изменения, распространяемые на все потребительские модули

Вариант 1) cons

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

Вариант 2) Плюсы

  • Это предельно ясно, какие зависимости у модуля.
  • Не догадываясь, откуда берутся классы (представьте, что 4 или 5 уровней модулей пропускают зависимости), поскольку их источник всегда объявляется в модуле.зависимости.

Вариант 2) cons

  • Делает обновление зависимости более утомительным, так как все модули с предложением implementation должны быть изменены.Несмотря на то, что я считаю, что это хорошо, потому что он точно отслеживает, как изменение изменило проект, я вижу, как это может занять больше времени.

Теперь вопросы :

  • Есть ли компромиссы с точки зрения компиляции этого многомодульного сценария?

  • Является ли модуль утечки зависимости "быстрее" для компиляции для пользовательских модулей?

  • Имеет ли это существенное значение во времени сборки?

  • Какие еще побочные эффекты, плюсы / минусы, я пропускаю?

Спасибо за ваше время.

1 Ответ

0 голосов
/ 13 февраля 2019

Репосты из ветки Gradle .

То, что вы описываете, является довольно распространенным обсуждением систем с многоуровневой архитектурой, также известных как "строгие" или "свободные" многоуровневые, или "открытые""против" закрытых "слоев.См. Эту (надеюсь, бесплатную для вас) главу из Шаблоны архитектуры программного обеспечения для некоторых семиотик, которые вряд ли помогут вам с вашим выбором

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

Если нескольким модулям нужно разбить слойТаким же образом, я могу рассмотреть возможность добавления отдельного базового модуля, предоставляющего эту функциональность, с именем, например base-xyz.Добавление нового модуля - большая вещь не из-за технической работы, а потому, что наш мозг может обрабатывать только очень много «вещей» за раз (чанкинг).Я полагаю, что то же самое относится и к «вариантам» Gradle, когда они станут доступны, но я не могу утверждать, что пока я не попробовал их на практике.

Если все клиенты модуля base нуждаютсячтобы получить доступ к library (т. е. поскольку вы используете классы или исключения из library в своих публичных подписях), вы должны выставить library как зависимость API от base.Недостатком этого является то, что library становится частью общедоступного API base, и, вероятно, он больше, чем вы хотели бы, и не находится под вашим контролем.Публичный API - это то, за что вы несете ответственность, и вы хотите, чтобы оно было небольшим, документированным и обратно совместимым.

В этот момент вы можете подумать о модулях головоломки (хорошо), osgi (ошибаться ... дон't), или обертывание частей lib, которые вам нужно представить в ваших собственных классах (может быть?)

Обтекание только ради разрыва зависимостей - не всегда хорошая идея.С одной стороны, это увеличивает объем поддерживаемого вами кода и (надеюсь) документа.Если вы начинаете делать небольшие адаптации в слое base, а library - это хорошо известная библиотека, вы вносите (добавленную стоимость) несоответствия - нужно всегда быть настороже, сохраняются ли их предположения для lib.Наконец, часто тонкие обертки заканчивают утечкой дизайна библиотеки, поэтому, даже если они обертывают API - это все равно заставляет вас прикасаться к клиентскому коду при замене / обновлении lib, и в этот момент вам, возможно, было бы лучше использовать lib напрямую.

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

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

...