11

我在一家开发具有丰富 UI 的复杂医疗设备的小公司工作。我们目前处于设计的早期阶段。该应用程序面向 Windows(仅限桌面),最好只用 C++ 编写。

经过一些研究,我们倾向于选择 Qt 来开发 UI。它似乎满足了我们所有的需求,即可以开发出具有现代感和高响应性的 UI,开发速度相当快(熟悉之后),内存使用在某种程度上是合理的,免费用于商业用途(对我们来说是奖励)。

我的问题是:它对于医疗设备是否足够可靠?我们绝对不能接受考试中途发生的任何事故。我知道这首先当然取决于我们编写的代码的质量,但我仍然想知道是否有人遇到过任何与崩溃相关的神秘问题,这些问题特别难以解决。尤其是在使用 QML 这种脚本语言时,它自然会导致难以预测和解释的错误。

在生产中遇到此类问题的成本对我们来说将非常高,因此在我们选择任何特定的包之前,我们非常需要做出正确的决定。如果您知道在我们的特定上下文中可能出现的任何其他与 Qt 相关的问题(我承认不可能进行非常广泛的包测试),我也非常感谢您提及它。

4

4 回答 4

4

在我看来,如果你遵循他们的编码风格,Qt 就足够稳定了。我还会从 Digia 购买支持并使用该库的稳定版本。

事情归结为:

  • 评估使用 Qt(或任何其他 GUI 库)引入的风险
  • 针对这些风险采取防御措施(引入新的需求和涵盖风险的测试,例如将 GUI 作为一个单独的进程运行,通过 TCP 或其他方式与核心通信)
  • 评估应用程序崩溃的风险,并记录发生这种情况时要遵循的程序。

根据我对医疗设备认证的经验,设备的响亮碰撞比无声和错误的操作更可取。如有疑问,请询问跟进您案件的认证机构。

另外,请查看标准(例如 60601-1-4 或现在使用的任何标准)。

Qt 在医疗应用中的使用:http: //qt.nokia.com/qt-in-use/qt-in-medical/

于 2012-07-31T11:50:10.220 回答
3

我认为高可靠性工程的基本原则就足够了。有了这些,您就可以使用 Qt。现在,Ambroz Bizjak 提到了很多“麻烦”的场景。当您遵循基本规则时,它们是无关紧要的。

那么,这些规则是什么?他们不是很难。识别可能发生故障的位,并在故障不严重的时候执行这些操作。例如,Ambroz 有一个关于窗口删除的好观点。不要在考试中间这样做。将对象转储到延迟删除队列中,并确保它们不会干扰操作(即对象必须具有被动状态。例如,对于小部件,包括不可见)。同样,在开始检查之前创建您可能需要的所有对象(包括所有可能的对话窗口)。

您可以很好地将其总结为

  1. 可能失败的准备
  2. 可能不会失败的事情
  3. 可能失败的清理

由于已经提到的原因,我会避免使用 QML。上面的方案强调了为什么它如此成问题。您不能将所有可疑的 QML 步骤移至准备阶段。

于 2012-07-31T11:37:26.753 回答
2

我假设您不是在开发对安全至关重要的设备,因为您正在运行 Windows 并且 Windows 许可协议对此有一些话要说。所以你的问题真的是,“我们正在制造一种必须尽可能稳定的消费品,否则我们看起来会非常非常糟糕”

就个人而言,我可以建议使用 C#,因为它在 Windows 下具有出色的工具,并且使用它进行开发更加容易和安全(垃圾收集器是您的朋友,如果不是性能的话,也是稳定性的朋友),并且对单元测试更方便。对任何性能关键部分使用 C++ 或 C++/CLR,但没有理由使用这种复杂且具有潜在危险的语言来构建您的 GUI。

于 2012-07-31T09:31:43.200 回答
1

根据我对 Qt 的经验,当可靠性很重要时,这是一个糟糕的选择。例如,许多崩溃是由看似有效的代码引起的,但它在某些特定的上下文中做了一些 Qt 的某些部分没有预料到的事情。在这里,我列出了我在使用 Qt 时遇到的关于编写正确代码的一些问题:

  • 删除 QObjects(阅读:任何东西)是一个非常痛苦的过程。如果你从这个对象发出的信号中删除它(读取:一半的时间),你的程序可能会崩溃,因为发出信号的代码不会在你信号处理程序返回后检查对象是否仍然存在,并且可能继续使用它。

  • 如果您仔细观察,建议的解决方法是使用 QObject::deleteLater() ,这将使事件循环在某个时候删除对象,当它是安全的时。虽然这似乎可以接受,但请考虑在此期间对象仍然存在并且可以发出信号。这引入了您必须处理的不必要的中间状态,这引入错误;可能很少发生并且在非常特定的情况下发生(阅读:不是在您测试它时)。无论如何,这个页面讨论了 QObject 删除的一些问题。

  • Qt 中的其他类也有类似的删除相关问题。例如,QGraphicsScene::removeItem() 如果您在其 mousePressEvent 处理程序中从其场景中删除项目(而不是删除它),则可能会导致崩溃。这似乎没有记录在任何地方。

  • Qt 类充满了与核心功能集混合的便利功能,因此很难弄清楚该类的实际工作方式以及如何正确使用它。例如,QProcess 除了唯一需要的 stateChanged() 信号之外,还有 error()、finished() 和 started() 等信号,它们的语义和正确处理并不完全清楚。

  • 许多抽象接口设计得很糟糕,定义也很糟糕。例如,类 QIODevice 用于读取和写入以及阻塞和异步 I/O。一个类可以自由选择要实现它的哪个子集。这违反了抽象接口的整体理念,即实现接口的任何东西都以定义和一致的方式工作。

  • 没有真正好的和统一的方式来处理事件。Qt中有两种事件: QEvents,通过重新实现虚函数来安装回调,以及信号为什么?无论如何,这两种事件最终都只是调用函数(直接,在这里忘记排队信号)。这意味着各个模块只能通过调用彼此的函数进行通信。正如已经看到的,这是有问题的,因为当一个模块调用另一个模块时,另一个模块真的可以做任何事情,并且可能很难考虑每个回调站点的所有可能场景(正如我们所见,Qt 没有,而是崩溃)。

    这个问题可以通过在事件循环中添加一个特性来完全解决,这使得跨模块的通信和同步变得更加容易。我在这个问题中描述了这个设计。

总而言之,在追求最大可靠性时,您不希望在程序所基于的框架中出现此类设计问题,也不希望在几乎每一步都解决问题。即使你正确地解决了所有你能想到的问题,你怎么知道没有更多的问题?我认为您应该尝试在 Qt 中编写一些完全正确的代码(也就是说,阅读所有文档,并考虑每一步您在做什么以及框架将如何反应)。一段时间后,问问自己:你相信这个框架,还是觉得它在试图欺骗你?

于 2012-07-31T09:50:01.947 回答