Что такое программный компонент

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

Компонент — это логически завершенная единица кода с собственным жизненным циклом и чётко определённым интерфейсом.

Основным критерием логической завершённости является не формальный признак, а видение авторов кода. Логически завершённым считается такой фрагмент кода, который с точки зрения автора полностью решает выделенную им задачу. Например, StringUtils из Spring можно использовать для работы со строками, однако этот класс нельзя рассматривать как логически завершённую часть, поскольку он задумывался разработчиками Spring как вспомогательный элемент Spring Core. В то же время похожий по функциональности StringUtils из библиотеки Apache Commons Lang можно рассматривать как логически завершённую единицу кода, поскольку авторы изначально задумывали библиотеку по работе со строками, и их StringUtils делает именно это.

Под жизненным циклом компонента понимается наличие точки запуска, которая разворачивает его в памяти и возвращает публично доступный объект-фасад, предоставляющий доступ к инетрфейсу компонента. Концептуально точку запуска можно выразить следующей сигнатурой: Component.start(): Facade.

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

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

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

Сервис, напротив, обладает всеми перечисленными признаками: он логически завершён, имеет собственный жизненный цикл и предоставляет чётко определённый интерфейс взаимодействия. Однако сервис предполагает взаимодействие через протокол передачи данных и выполняется в отдельном процессе, тогда как несколько компонентов могут работать в рамках одного процесса. Поэтому сервис можно рассматривать как частный случай компонента.