Qt工程化项目架构设计实战 - 第1节

一、为什么我们需要工程化架构?

说实话,我刚开始做Qt开发那会儿,根本不懂什么叫架构。

一个mainwindow.cpp能写两三千行,所有逻辑全塞在一起。信号槽满天飞,今天改个按钮,明天崩三个窗口。嗯,这种日子,我相信不少朋友都经历过。

后来我带团队了,发现一个残酷的现实:代码写得好不好,三个月后见分晓。三个月后你自己都看不懂自己写的代码,那这项目基本就废了。

工程化架构的核心目的就三个:

  • 可维护性 —— 改一个功能,不会炸掉三个不相关的模块
  • 可扩展性 —— 加新功能时,不用重写旧代码
  • 可测试性 —— 能单独测某个模块,不用启动整个应用

说白了,架构就是给代码画边界。每个模块管好自己的事,别越界。我在项目中遇到过最典型的反面教材:一个类既处理UI事件,又直接操作数据库,还负责网络通信。这种代码,改起来就像拆炸弹——剪错一根线就全炸了。

二、常见架构模式:MVC / MVP / MVVM

这三种模式,说白了都是在做同一件事:把界面和业务逻辑拆开。但拆法不一样,适用场景也不同。

2.1 MVC —— 最经典,但容易踩坑

MVC分为三部分:

  • Model(模型):数据与业务逻辑
  • View(视图):界面展示
  • Controller(控制器):接收用户输入,更新Model和View

在Qt里,很多人把QWidget既当View又当Controller,结果又回到了大泥球。我个人习惯是:View只负责显示,Controller单独写成一个类。

我的经验:Qt自带的Model/View框架(QAbstractItemModel、QTableView等)其实就是MVC的一种实现。但很多人只用了View,没用好Model,导致数据逻辑散落在各处。

2.2 MVP —— 更适合复杂UI交互

MVP把Controller换成了Presenter。区别在哪?

  • View:只负责被动渲染,不包含任何业务逻辑
  • Presenter:负责处理用户操作,调用Model,更新View
  • Model:数据层,与MVC相同

我曾经在一个医疗设备项目里用过MVP。界面交互极其复杂,一个界面有几十个参数输入。如果用MVC,Controller会膨胀到无法维护。换成MVP后,每个界面对应一个Presenter,逻辑清晰多了。

注意:MVP的缺点是类数量翻倍。每个View都要配一个Presenter。小项目用起来反而累赘。

2.3 MVVM —— Qt的现代选择

MVVM是MVP的进化版。核心思想是数据绑定——View直接绑定到ViewModel的属性,ViewModel变化时View自动更新。

Qt里实现MVVM,主要靠:

  • Q_PROPERTY:定义可绑定的属性
  • 信号与槽:属性变化时通知View
  • QDataWidgetMapper:自动将Model数据映射到控件

我个人现在做新项目,基本都倾向MVVM。原因很简单:写UI代码时不用想着业务逻辑,写业务逻辑时不用管UI长什么样。这种分离感,真的很爽。

三、三种模式对比

模式 核心思想 适用场景 Qt中的实现难度
MVC Model-View-Controller 简单应用、快速原型 低
MVP View-Presenter-Model 复杂交互、需要单元测试 中
MVVM View-ViewModel-Model 数据驱动、大型项目 中高

四、Qt项目目录结构最佳实践

聊完模式,咱们落地到实际工程。一个Qt项目该怎么组织目录?我见过太多人把所有文件扔在一个文件夹里,找文件全靠搜索。嗯,这种习惯得改。

4.1 推荐目录结构

MyProject/
├── CMakeLists.txt          # 顶层构建文件
├── src/                    # 源代码
│   ├── app/                # 应用入口
│   │   └── main.cpp
│   ├── core/               # 核心业务逻辑
│   │   ├── models/         # 数据模型
│   │   ├── services/       # 业务服务
│   │   └── utils/          # 工具类
│   ├── ui/                 # 界面层
│   │   ├── views/          # 视图(窗口、控件)
│   │   ├── viewmodels/     # ViewModel(MVVM用)
│   │   └── resources/      # 资源文件(qrc、图片等)
│   └── tests/              # 单元测试
│       ├── test_models/
│       └── test_services/
├── third_party/            # 第三方库
├── docs/                   # 文档
└── scripts/                # 构建脚本

关键原则:

  • 按功能分层,而不是按文件类型。别把所有的.h放一个文件夹,.cpp放另一个
  • 每个模块一个子目录,模块内部再按职责细分
  • 测试代码与源码分离,但保持相同的目录结构

4.2 命名规范

我习惯的命名方式:

  • 类名:大驼峰,如 UserManager
  • 文件名:与类名一致,如 UserManager.h
  • 命名空间:按模块划分,如 core::models::User
  • 信号与槽:信号用 xxxChanged,槽用 onXxx

避坑指南:我曾经在一个项目里看到有人把信号命名为 signal1、signal2。三个月后,没人知道这些信号是干什么的。命名一定要自解释,别偷懒。

五、本章知识体系总览

下面这张图,是我自己总结的Qt工程化架构的核心脉络。你可以把它当作一张地图,后续章节都会围绕这些点展开。

Qt工程化架构核心知识体系 为什么需要工程化架构? 可维护性 可扩展性 可测试性 常见架构模式 MVC Model-View-Controller MVP Model-View-Presenter MVVM Model-View-ViewModel 目录结构最佳实践 按功能分层 模块化组织 命名规范 测试分离

这张图把本章的核心内容串起来了。从上到下,先搞清楚为什么要搞架构,再选用什么模式,最后落地到目录怎么组织。后续章节会逐一深入每个细节。

一句话总结:架构不是银弹,但没有架构,项目就是定时炸弹。选对模式,搭好目录,你的Qt项目才能活过三个月。

可可精品资料库