如何在 C++ 中模块化构建应用程序

Posted

技术标签:

【中文标题】如何在 C++ 中模块化构建应用程序【英文标题】:How do you build an application in c++ modularly 【发布时间】:2011-05-05 10:30:42 【问题描述】:

这是一个关于如何构建 c++ 应用程序的问题,而不是关于 c++ 本身的问题

我正在构建一个设想为图形应用程序的应用程序,但实现的细节需要大量抽象功能来促进接口,例如从文件、Web 资源等读取对象列表。我已经想出了如何毫不费力地实现这个功能,但我没有很好的方法来测试它。具体来说,我已经开始实现图形环境,但还没有准备好使用较低级别的功能。

我还构建了很多我想让底层做的事情,但它还没有经过测试。所有这些代码都驻留在一个文件夹中,并存储在具有定期提交的版本控制系统中。

到目前为止,我对用 C++ 编写任何功能性的东西还比较陌生,但我已经用 php 编写了很多不同类型的程序。

如果这是一个 PHP 项目,测试任何功能似乎都很简单:

    我只是从交互实现它开始 将其编码成一个小文件 编写一些使用该功能的代码 将其构建为函数 将该函数导入我更大的代码体中。

这似乎是用 C++ 做同样事情的一种非常尴尬的方式。我是否把它全部倒退了,你如何在你的编译程序中解决小的孤立问题并将它们导入你的项目中;是否有您认为有用的工作流程。

【问题讨论】:

【参考方案1】:

一般来说,您的问题的答案是使用类和单元测试。在互联网上搜索敏捷/极限编程。

想法是这样的:

    完成所有敏捷故事的内容(我会让您自己阅读) 您将设计分解为类 编写单元测试,为您的类定义“规范” 编写空占位符函数。 查看单元测试失败。 编写代码直到单元测试成功。 返回到第 3 步,然后重复其他课程。

如果您以这种方式编写代码,您将创建可重用且健壮的代码。

老实说,我个人并不相信真正的 TDD(测试驱动开发)——我觉得在编写代码之后编写单元测试会更好(我感觉到来自用户尖叫的即将到来的厄运火焰”敏捷或死亡!”)。

编辑:如果您的问题更多地涉及多个类的实际构建的谎言,那很容易。一般来说,你的每个类都应该封装在 2 个文件中(源代码和头文件)。只需将这些文件(以及您要使用的所有其他类的文件)包含在新项目中。 #include "xxx.h" 在您需要使用类的适当位置,编写使用这些类的代码并构建。就是这样。

【讨论】:

从下面回答您的评论:如果您已经编写过代码(听起来您没有使用 Agile/XP 方法——那很好)。然后我会创建一个界面来使用它(老实说你应该已经这样做了)。创建一个可用的 .h 文件(许多人将应该在 .h 中的东西放在 .c 中,反之亦然)。然后在需要时将这些文件导入新项目。 澄清:所以——我正在使用类,我正在使用 QT,并且我已经构建了很多代码——我是否应该只使用我编写的代码,复制它进一个新文件夹,写一个简单的界面,然后编译/测试?这是最好的选择吗?【参考方案2】:

我想这将是任何 OO 项目的一般策略。

首先确定主要组成部分,并确保您对所有内容的责任有非常透彻的了解。

写出每个组件的接口,并(逻辑上)检查它是否适合您的问题。

实现每个模块。

就测试而言,制作测试模块(存根):例如制作一个类,该类将向 GUI 发送输入,模仿实际组件发送的输入。由于您对界面有一个清晰的概念,因此该结果是如何产生的将是无关紧要的。

对系统中的每个组件重复此过程,然后将它们放在一起。

希望对你有帮助

【讨论】:

【参考方案3】:

我目前处于类似情况,我已经实现了一些零碎的功能(通过某些 API 进行文件 I/O、工作的主要部分等)。所以也许我的一些经验会有所帮助:

如果您已经有一些代码,绘制一张您所拥有的图表可能会有所帮助。笔和纸,甚至更好的 UML 可以在这里提供帮助(顺便说一句,可以导入现有类的一个很好的 UML 工具是 Umbrello)。有时我会在最后一次提交后进行这种“设计检查”,它帮助我发现了一些微妙的问题,尤其是在设计阶段,我每天都在重构课程; 如果您为组件编写了代码,我认为您可以轻松地为每个组件制定一些要求,然后您可以根据这些要求创建一些测试(例如,使用“UnitCPPLite”)。目前,我在主文件中有测试,其中包含一些样板代码,这些代码在应用程序中执行任何其他操作之前触发测试执行(尽管这仍然不是最佳的); 最后,我将在 ComtriS 的建议中添加“包含防护”的想法(如果您尚未使用它们),以防止多次包含头文件。所以,在实践中,我通常会得到这样的结果:

src/CFoo.h:

// class 'CFoo': header file
#ifndef CFOO_H
#define CFOO_H

#include <only_what_you_need_in_declaration_interface>

class CFoo 
    private:
        // class data
    public:
        // constructors, destructors, getters, setters, etc.
        void doWork();
    ;
#endif /* CFOO_H */

src/CFoo.cpp:

// class 'CFoo': implementation file
#include "CFoo.h"
#include <what_you_need_in_addition_for_internal_workings_of_methods>

// code for other methods...

void CFoo::doWork() 
    // work

希望对你有帮助。

【讨论】:

以上是关于如何在 C++ 中模块化构建应用程序的主要内容,如果未能解决你的问题,请参考以下文章

如何快速读懂大型C++程序代码

如何在 C++ 中使用管道构建聊天程序

混合 C 和 C++ 的线程同步

如何在 C++ 中构建与运行时版本无关的 DLL?

如何在 C++ 程序将使用的 Python 脚本中导入 cpython 模块?

我如何使用 Web 应用程序作为 C++ 构建的应用程序的接口?