В этом посте я дам вам несколько простых советов, которые при тщательном соблюдении немедленно приведут к созданию простой в обслуживании и масштабируемой архитектуры вашего Java-приложения. Хотя этот пост посвящен Java, концепции будут в равной степени применимы и к другим языкам, которые позволяют упорядочивать код в пакетах.
Можно было бы написать книги о том, как добиться хорошей архитектуры (и люди это сделали), но вам нужна лучшая архитектура прямо сейчас, и у вас мало времени – и у меня тоже, – так что давайте перейдем к делу. Все, что я собираюсь вам сейчас сказать, сводится к одному самому важному совету:
Используйте package private область действия свободно
Если вы это сделаете, это решит сразу так много проблем, что, как только вы привыкнете к этому, вы, надеюсь, будете так же поражены, как и я, когда понял, насколько ценен этот совет. Если вы это сделаете, это решит сразу так много проблем, что, как только вы привыкнете к этому, вы, надеюсь, будете так же поражены, как и я, когда понял, насколько ценен этот совет. Позвольте мне объяснить это подробно.
Если вы это сделаете, это решит сразу так много проблем, что, как только вы привыкнете к этому, вы, надеюсь, будете так же поражены, как и я, когда понял, насколько ценен этот совет. Позвольте мне объяснить это подробно. В больших приложениях ключом к ремонтопригодности является поддержание связи отдельных компонентов приложения под контролем. Если вы это сделаете, это решит сразу так много проблем, что, как только вы привыкнете к этому, вы, надеюсь, будете так же поражены, как и я, когда понял, насколько ценен этот совет. Позвольте мне объяснить это подробно. В больших приложениях ключом к ремонтопригодности является поддержание связи отдельных компонентов приложения под контролем. Это предполагает, что ваше приложение на самом деле должно быть структурировано в компоненты в первую очередь. Если вы это сделаете, это решит сразу так много проблем, что, как только вы привыкнете к этому, вы, надеюсь, будете так же поражены, как и я, когда понял, насколько ценен этот совет. Позвольте мне объяснить это подробно. В больших приложениях ключом к ремонтопригодности является поддержание связи
Если вы это сделаете, это решит сразу так много проблем, что, как только вы привыкнете к этому, вы, надеюсь, будете так же поражены, как и я, когда понял, насколько ценен этот совет. Позвольте мне объяснить это подробно. В больших приложениях ключом к ремонтопригодности является поддержание связи отдельных компонентов
Если вы это сделаете, это решит сразу так много проблем, что, как только вы привыкнете к этому, вы, надеюсь, будете так же поражены, как и я, когда понял, насколько ценен этот совет. Позвольте мне объяснить это подробно. В больших приложениях ключом к ремонтопригодности является поддержание связи отдельных компонентов приложения под контролем. Это предполагает, что ваше приложение на самом деле должно быть структурировано по компонентам в Случае, если это не так, вы, вероятно, уже столкнулись с какой-то зависимостью Зависимость является ключевой проблемой при разработке программного обеспечения на всех уровнях ( Кент Бек ) inter-package-dependency-hell wJava предоставляет концепцию пакетов
Если вы это сделаете, это решит сразу так много проблем, что, как только вы привыкнете к этому, вы, надеюсь, будете так же поражены, как и я, когда понял, насколько ценен этот совет. Позвольте мне объяснить это подробно. В больших приложениях ключом к ремонтопригодности является поддержание || связи || отдельных компонентов || приложения под контролем. Это предполагает, что ваше приложение на самом деле должно быть структурировано на компоненты в, Если это не так, вы, вероятно, уже столкнулись с какой-то зависимостью || Зависимость является ключевой проблемой при разработке программного обеспечения на всех уровнях ( || Кент Бек || ) межпакетная зависимость-ад || Но опыт научил меня, что в большинстве случаев один компонент – это происходит, когда программисты выбирают свой пакет. Локальность связанного кода является ключевым аспектом наличия кода, который легко рассуждать в этом сценарии, возможно, несвязанные классы расположены рядом друг с другом в одном пакете, в то время как связанные классы расположены далеко. Например, если у вас есть пакет || org.domain.app.controllers ||, в котором находятся все ваши контроллеры, и другой пакет || org.domain.app.services ||, в котором находятся все ваши сервисы, у вас есть техническая структура пакета. es по || техническим || аспектам. nt распространяется по нескольким пакетам. Java предоставляет концепцию || packages || для структурирования вашего кода в компоненты. с циклами упаковки и тому подобным (старый добрый || большой ком грязи || ). первое место.
Если вы это сделаете, это решит сразу так много проблем, что, как только вы привыкнете к этому, вы, надеюсь, будете так же поражены, как и я, когда понял, насколько ценен этот совет. Позвольте мне объяснить это подробно. В больших приложениях ключом к ремонтопригодности является поддержание связи отдельных компонентов
Если вы это сделаете, это решит сразу так много проблем, что, как только вы привыкнете к этому, вы, надеюсь, будете так же поражены, как и я, когда понял, насколько ценен этот совет. Позвольте мне объяснить это подробно. В больших приложениях ключом к ремонтопригодности является поддержание связи отдельных компонентов приложения под контролем. Это предполагает, что ваше приложение на самом деле должно быть структурировано на компоненты в, Если это не так, вы, вероятно, уже столкнулись с какой-то зависимостью Зависимость является ключевой проблемой при разработке программного обеспечения во всех масштабах (
Дайте как можно большему количеству классов package private область видимости
На самом деле вы должны, по умолчанию, сделать каждый класс package закрытым и расширять его область применения только в случае необходимости. Через некоторое время у вас возникнет плохое предчувствие всякий раз, когда вы увидите, что что-то происходит публичный – и это хорошо. Это заставляет вас явно задуматься об открытом интерфейсе вашего пакета. Следуя этому совету, вы автоматически создадите пакеты со следующими характеристиками:
- высокая когезия: все в упаковке как бы связано с другими вещами. Местоположение связанного кода позволит легко рассуждать об этом.
- низкое сцепление с другими упаковками: потому что существует только минимальный открытый интерфейс вашего пакета
Хотя это и хорошо, вы также почувствуете, что ваши посылки становятся все больше и больше до размеров, которые заставляют вас чувствовать себя некомфортно.
Если вы чувствуете, что ваш пакет становится слишком большим, это явный признак того, что может быть лучшее сокращение для конкретного домена. В этой ситуации вам следует пересмотреть и подвергнуть сомнению всю цель текущего пакета. По моему опыту, вы сталкиваетесь со следующими случаями:
- Ваша исходная функция была подорвана несвязанным кодом, который на самом деле обслуживает другую функцию.
- С течением времени требования к исходной функции изменились настолько, что исходная структура больше не подходит в достаточной степени. Также может оказаться возможным, что функция не изменилась, но ваше понимание ее изменилось, когда вы ее кодировали.
В большинстве случаев первый случай решить просто. Если вы действительно находитесь в ситуации, когда в ваш пакет функций проскользнул в основном несвязанный код, его должно быть довольно легко изолировать и переместить в собственный пакет.
Если изолировать более мелкие части не так просто, вы можете столкнуться со вторым случаем. Именно здесь волшебство package private достигло своих пределов, и вам придется выполнять реальную работу. Теперь вы приступили к некоторому рефакторингу на уровне пакета – то есть вам нужно разделить ваш текущий пакет на несколько новых, которые лучше соответствуют требованиям проблем домена, которые вы пытаетесь решить. Скорее всего, это невозможно решить, просто переместив некоторые классы между пакетами, но может потребовать фактических изменений кода.
Но поскольку все, что связано, находится так близко друг к другу, и вы знаете, что большинство вещей не используются вне пакета, это дает вам большую уверенность при рефакторинге.
Вы когда-нибудь задумывались, что такое unit в модульном тестировании? Возможно, вы сталкивались с наборами тестов, в которых для каждого производственного класса существует тестовый класс. Если это так, то вы, скорее всего, столкнулись с тем, что ваши модульные тесты не очень надежны. Они легко ломаются, если вы настраиваете класс реализации, даже если вы действительно правильно сохранили поведение. Это потому, что единица измерения не означает класс . Unit относится ко всему коду, который вы хотите протестировать изолированно, чтобы решить проблему, специфичную для конкретной области. Единица измерения означает особенность а функция, в нашем случае, означает общедоступный интерфейс вашего пакета.
Не пишите тестовый класс для каждого производственного класса. Напишите тестовый класс для каждой функции
Это позволяет слабо связать ваш тестовый код с производственным кодом точно так же, как ваш производственный код слабо связан с другими пакетами. Вы можете свободно изменять все детали реализации (например, даже удалять классы) за общедоступным интерфейсом, не нарушая ваши тесты. В этом и заключается само значение сокрытия информации .
Подводя итог, можно сказать, что, щедро используя пакет private scope, вы получаете (бесплатно!)
- высокая когезия в ваших упаковках
- низкое сцепление между упаковками
- надежная архитектура благодаря четко определенным интерфейсам между компонентами/пакетами
- код, о котором легче рассуждать
- хороший намек на то, что вы должны протестировать, чтобы добиться более надежных модульных тестов
И еще раз: вы получаете это за то, что просто пропускаете модификатор public в объявлениях вашего класса! Всякий раз, когда вы чувствуете необходимость создать новый класс, сделайте его закрытым пакетом и поместите его в пакет, где, с точки зрения домена или функциональности, по вашему мнению, он подходит лучше всего. Это ставит вас в положение, в котором вы можете со временем тщательно разрабатывать макет своего пакета.
Добавление Внимательный читатель, возможно, заметил следующее: приведенные выше советы по структурированию ваших пакетов на самом деле являются теми же советами, которым мы следовали десятилетиями на уровне класса. Бесспорно, что лучше всего сохранять вспомогательные методы частными , чтобы иметь четко определенный общедоступный интерфейс. Если “зависимость является проблемой во всех масштабах” вполне вероятно и ожидаемо, что решения для управления зависимостями также выглядят одинаково во всех масштабах.
Дополнительная информация:
- Саймон Браун о “упаковке по компонентам”: Саймон Браун о “упаковке по компонентам”:
- https://github.com/olivergierke/moduliths
- ((((Расширение spring Boot, которое пытается применить этот способ структурирования вашего приложения)
Оригинал: “https://dev.to/skuzzle/how-a-great-package-structure-can-make-a-great-application-22ng”