Я согласен с вашей потребностью. Проверка необходимой среды выполнения обеспечивает:
- немедленная обратная связь , вместо случайного прерывания при доступе к некоторой функциональности
- надеюсь более опытный пользователь , поскольку непосредственный отзыв доступен парню, который устанавливает программное обеспечение, надеюсь, более квалифицированному, чем обычный пользователь, или, по крайней мере, менее уверенному (установка всегда является специальной операцией) , Более опытный пользователь меньше беспокоится, если в консоли появляется ошибка, он не зависит от графического интерфейса.
- улучшенная отчетность : сообщение об ошибке может быть явным (вы отвечаете), в то время как сообщения об ошибках по умолчанию бывают разных видов (они не всегда так полезны в отношении 1. что не так 2. предложение исправить).
Но учтите, что требования времени выполнения можно проверить в двух ситуациях:
- при установке: длительные проверки всегда приемлемы; Если библиотеки здесь нет, необходимая база данных или WebService недоступны, ее также не будет здесь во время выполнения, поэтому вы можете немедленно пожаловаться.
- при запуске выполнения: вы можете проверить еще раз (и некоторые проверки могут произойти только в этот момент)
Это предполагает создание установщика для вашего приложения.
Потенциально, не все ошибки будут блокировать установку. Некоторые, скорее, накапливаются в виде списка задач, которые необходимо выполнить после установки, возможно, красиво отформатированные в файле со всей справочной информацией.
Здесь мы снова сталкиваемся с понятием уровень ошибок при проверке (аналогично тому, что происходит с Log4j): некоторые ошибки проверки имеют фатальный уровень, другие - ошибки, возможно, также предупреждения ...
В наших проектах при запуске происходит какая-то инициализация и проверка. Исходя из нашего повседневного опыта, я бы предложил следующее:
Когда приложение становится большим, вы не хотите, чтобы все init были централизованы в одном классе, поэтому у нас есть модульная структура .
- Небольшое ядро настроено со списком модулей классов. Целая последовательность инициализации находится под строгим контролем, готова к любым исключениям (переводит их в соответствующие сообщения, но запоминает трассировки стека, которые так полезны для разработчиков), не делая предположений в доступные библиотеки и т. д. CheckStyle может быть настроен специально для этого кода.
Интерфейс (разумеется, абстрактный класс), который реализуют модули, обычно имеет несколько методов инициализации . Они могут быть:
- getDependencies: возвращает список модулей, от которых зависит этот.
- запуск: когда запускается все приложение. Это будет вызвано только один раз во время запуска и не может быть вызвано снова.
- запуск: когда модуль готовится к нормальной работе
- остановка: обратный от начала
- выключение: обратный запуск.
Ядро по очереди создает каждый модуль. Затем он вызывает один метод init для всех из них, затем другой метод init и так далее, по мере необходимости. Каждый метод инициализации может:
- условия ошибки сигнала (с использованием уровней, таких как Log4J).
- выданное исключение будет перехвачено ядром и переведено в состояние ошибки
- проконсультируйтесь с другим модулем относительно его статуса (потому что это общий случай зависимостей) и отреагируйте соответствующим образом. При необходимости зависимости могут быть сделаны декларативно.
Ядро в общем заботится о зависимостях модуля :
- Он сортирует модули так, чтобы были соблюдены зависимости.
- Он не инициализирует модуль, если одна из его зависимостей не может его сделать.
- Если его попросят остановить модуль, он сначала остановит модули, которые зависят от него.
Приятной особенностью этого подхода к ядру является то, что легко агрегировать ошибки на разных уровнях (хотя fatal может остановить это) и сообщать обо всех в конце, используя все доступные средства (SWT или нет, Log4J или нет ...). Таким образом, вместо того, чтобы обнаруживать проблемы одну за другой и каждый раз начинать заново, вы можете нанести один удар (конечно, с хорошим приоритетом).
По поводу ваших точных вопросов:
Должно ли приложение проверять себя на наличие необходимых зависимостей?
Да (см. Выше)
Если да, следует ли пользователю указывать конкретные детали того, что ему не хватает? Или просто сообщение и подробности в логах?
Как сказано выше, при установке пользователь более готов к этому.
При запуске мы используем простое сообщение для конечного пользователя, но предоставляем доступ к полным трассировкам стека для разработчика (у нас есть кнопка, которая копирует в буфер обмена среду приложения, трассировки стека и т. Д.).
Что делать, если библиотека log4J недоступна?
Вход без него (см. Выше).
Что лучше всего сделать тест? Проверка существования файла (с помощью file.exists () по указанному пути) или загрузка класса, скажем Class.forName ("org.apache.log4j.Logger")?
Я бы загрузил класс. Но если это не удалось, я мог бы проверить наличие файла на диске, чтобы выдать улучшенное сообщение, включая «как исправить».
Каким должен быть порядок выполнения проверок? Например, если я проверяю SWT, я понятия не имею, доступен ли регистратор или нет, и при попытке доступа к нему произойдет ошибка. В обратном порядке, если я проверю регистратор 1-го: а) Библиотека может быть недоступна - я не могу записать ошибку; б) SWT может быть недоступен - невозможно отобразить сообщение пользователя.
Как я сказал выше, я предлагаю, чтобы эти низкоуровневые ошибки накапливались в небольшой области кода (ядра), где вы могли бы использовать все, что доступно для их отображения. Если ничего не доступно, вы можете просто войти в консоль без Log4J.