1

我有一个新谜题要给你:-)。

我在想一个应用程序应该如何处理他自己的启动。比如:检查所需的库、正确的版本、数据库连接性、数据库兼容性等。具体来说,这里是测试用例。出于显而易见的原因,我使用 SWT 和 Log4J。现在,问题:

  • 应用程序是否应该自行检查所需的依赖项?如果是,是否应该向用户提供丢失的具体细节?或者只是一条消息,以及日志的详细信息?
  • 如果 log4J 库不可用怎么办?
  • 什么是最好的测试?验证文件是否存在(使用 file.exists(),在指定路径),或者加载一个类,比如 Class.forName("org.apache.log4j.Logger")?检查的正确顺序应该是什么?例如,如果我测试 SWT,我不知道记录器是否可用,当我尝试访问它时会发生错误。向后,如果我测试第一个记录器:a)库可能不可用 - 我无法记录错误;b) SWT 可能不可用 - 无法显示用户消息。
  • 我今天发现了 apache.commons.lang 框架,我发现这个方法非常有用org.apache.commons.lang.SystemUtils.isJavaVersionAtLeast(Float value) ,我相信还有很多其他的方法。但是,将过多的库导入您的项目不会使其难以维护吗?版本更改,兼容性丢失,例如。无法控制第 3 方的开发风格或方向。

谢谢你的回答。

4

3 回答 3

1

最简洁的答案是不。JVM 在初始化时或在运行时适当地处理此功能。如果在类路径中找不到所需的类,则会抛出 ClassNotFoundException。如果找到了一个类,但没有找到所需的方法,则抛出 NoSuchMethodException。

于 2009-10-04T01:29:16.070 回答
1

关于 1 到 3 ,这里有 2 个主要用例:

  • 应用程序打包在您的控制之下,并且可以确保正确打包所有必需的依赖项。运行时验证在这里没有用。
  • 应用程序打包不在您的控制之下,您需要提供主 jar 和有关要求的说明。运行时验证可能很有用,但是想要打包您的应用程序的人通常有足够的技能来理解它的ClassNotFoundException: org.apache.logging.LogManager含义。

关于4,只要保持项目中包含的相同版本的依赖项,在保持控制方面就没有问题。升级到更新版本是一个有意识的决定,需要思考和测试。

于 2009-10-04T06:36:21.240 回答
1

我同意你的需要。检查所需的运行时环境提供:

  • 即时反馈,而不是在访问某些功能时随机中断
  • 希望更熟练的用户,因为安装软件的人可以获得即时反馈,希望比普通用户更熟练,或者至少不那么自信(安装始终是一项特殊操作)。如果错误出现在控制台中,熟练的用户不会受到干扰,他不依赖于图形界面。
  • 改进的报告:错误消息可以是明确的(您负责),而默认错误消息有多种形式(它们并不总是那么有帮助 1. 出了什么问题 2. 建议修复)。

但请注意,可以在两种情况下检查运行时要求:

  • 安装时:总是可以接受长时间的验证;如果一个库不在这里,所需的数据库或 WebService 不可访问,它也不会在运行时在这里,所以你可以立即投诉。
  • 开始执行时:您可以再次验证(并且某些验证可能仅在那时发生)

这建议为您的应用程序创建一个安装程序。

潜在地,错误不会全部阻止安装。有些人宁愿将安装后要完成的任务列表累积起来,也许可以很好地格式化在包含所有参考信息的文件中。

在这里,我们再次触及了验证中错误级别的概念(类似于 Log4j 发生的情况):一些验证错误处于致命级别,其他是错误,也可能是警告......


在我们的项目中,我们在启动时会进行某种初始化和验证。根据我们的日常经验,我建议以下几点:

当应用程序变大时,您不希望所有 init 都集中在一个类中,因此我们有一个模块化结构

  • 一个小内核配置有一系列模块类。它的整个初始化序列受到严格控制,为任何异常做好准备(将它们转换为适当的消息,但记住对开发人员非常有用的堆栈跟踪),不对可用库进行假设等等...... CheckStyle 可以是专门为此代码配置。
  • 模块实现的接口(当然,抽象类也是可能的)通常有几个初始化方法。他们可能是:

    • getDependencies :返回这个依赖的模块列表。
    • 启动:当整个应用程序启动时。这只会在启动过程中调用一次,并且不能再次调用。
    • start :当模块准备好进行常规操作时
    • 停止:从开始反转
    • 关机:从启动反转。
  • 内核依次实例化每个模块。然后他在所有这些上调用一个 init 方法,然后根据需要调用另一个 init 方法,依此类推。每个 init 方法都可以:

    • 信号错误条件(使用级别,如 Log4J)。
    • 抛出的异常将被内核捕获,并转换为错误条件
    • 咨询另一个模块的状态(因为依赖是一般情况),并做出相应的反应。如果需要,可以声明式地建立依赖关系。
  • 内核通常会处理模块依赖关系

    • 他对模块进行排序,以便尊重依赖关系。
    • 如果模块的依赖项之一无法实现,他不会初始化模块。
    • 如果被要求停止一个模块,他将首先停止依赖它的模块。
  • 这种内核方法的一个很好的特点是可以很容易地聚合不同级别的错误(尽管致命可能会阻止它),并在最后报告所有错误,使用任何可用的方法(SWT 与否,Log4J 与否...)。因此,您不必一个接一个地发现问题,并且每次都必须重新开始,您可以一次完成(当然优先级很好)。


关于您的确切问题:

应用程序是否应该自行检查所需的依赖项?

是(见上)

如果是,是否应该向用户提供丢失的具体细节?或者只是一条消息,以及日志的详细信息?

正如上面所说的,用户在安装时更愿意处理这个问题。

开始时,我们为最终用户使用简单的消息,但允许开发人员访问完整的堆栈跟踪(我们有一个按钮,可以在剪贴板中复制应用程序环境、堆栈跟踪等)。

如果 log4J 库不可用怎么办?

没有它的日志(见更高)。

什么是最好的测试?验证文件是否存在(使用 file.exists(),在指定路径),或者加载一个类,比如 Class.forName("org.apache.log4j.Logger")?

我会加载一个类。但如果它失败了,我可能会检查磁盘上的文件是否存在以提供改进的消息,包括“如何修复”。

检查的正确顺序应该是什么?例如,如果我测试 SWT,我不知道记录器是否可用,当我尝试访问它时会发生错误。向后,如果我测试第一个记录器:a)库可能不可用 - 我无法记录错误;b) SWT 可能不可用 - 无法显示用户消息。

正如我上面所说的,我建议这些低级错误累积在一小部分代码(内核)中,您可以在其中使用任何可用的东西来显示它们。如果没有可用的东西,您可以简单地在没有 Log4J 的情况下登录控制台。

于 2009-10-04T06:40:56.380 回答