输入关键词开始搜索

开发规范文档

智能家庭饮食管家 App - 开发规范文档

最后更新: 2026-05-20

一、文档修订记录

版本日期作者修改说明
v1.02026-05-20初始版本:Git 规范、C++/QML 代码规范、文档维护规范、CMake 规范、单人开发自律清单

第一部分:Git 规范

1.1 分支策略

本项目采用 简化 Git Flow 模型(单人适配版):

main                  ← 始终可编译、可运行

  ├── develop         ← 日常开发集成分支(主力分支)
  │     │
  │     ├── feature/xxx   ← 每个功能模块一条分支
  │     ├── fix/xxx       ← Bug 修复分支
  │     └── refactor/xxx  ← 重构分支

  └── release/vX.Y    ← 发布分支(阶段里程碑)
分支类型命名格式从哪分出合并到哪生命周期
main固定永久
develop固定mainmain (发版时)永久
feature/*feature/1.2-arch-skeletondevelopdevelop功能完成后删除
fix/*fix/fifo-underflowdevelopdevelop修复后删除
refactor/*refactor/repo-templatedevelopdevelop重构后删除
release/*release/v0.1-alphadevelopmain + develop发布后打 Tag 删除

单人简化规则:

  • 日常开发直接在 develop 上做,每完成一个子任务提交一次
  • 涉及较大重构(跨层修改 ≥3 个文件)时,切 feature/refactor/ 分支
  • 阶段里程碑达到后,从 develop 合入 main 并打 Tag

1.2 Commit Message 规范

采用 Conventional Commits 精简版:

<type>(<scope>): <subject>

[optional body — 一行一个要点]

[optional footer — 关联 issue / breaking change]

type 取值

type含义示例
feat新功能feat(core): 实现 TDEE 计算服务
fixBug 修复fix(repo): FIFO 扣减负数问题
refactor重构(无功能改动)refactor(data): Repository 模板化
docs文档变更docs: 新增开发规范文档 009
style格式调整(空格、缩进)style(qml): 统一 QML 缩进为 4 空格
test测试增改test(auth): 补充 Argon2id 单元测试
chore构建/工具/配置chore(cmake): 引入 QuickControls2 模块
perf性能优化perf(db): 索引优化查询耗时

scope 取值

scope对应层/模块对应目录
app入口、应用级src/app/
uiQML 视图与组件src/ui/qml/, src/ui/components/
coreService 层src/core/
dataRepository 层src/data/
network通信/同步src/network/
utils工具类src/utils/
cmakeCMake 构建CMakeLists.txt, cmake/
docs文档docs/
test测试tests/
resource资源文件resources/

规则

  • subject 强制中文(项目文档体系统一中文),不超过 50 字
  • body 选填,多行时每行一个要点,行宽 ≤72 字符
  • 一个 commit 只做一件事:禁止”修了 A 又加了 B 顺便改了 C”的混合提交

示例

feat(core): 实现 Mifflin-St Jeor BMR/TDEE 计算公式

- 支持男/女性别分支(男性公式 +5,女性公式 -161)
- 输入:身高(cm)、体重(kg)、年龄(岁)
- 返回:BMR(千卡)、TDEE(千卡,基于活动系数 1.2-1.9)
- TDEE 默认活动系数 1.55(中等活动量)
fix(data): 修复 updateWithVersion 乐观锁版本号误判

WHERE version = :expected AND id = :uuid 传入参数顺序错误,
导致 version 字段未被正确校验,并发更新时可能产生脏写。
chore(cmake): 新增 Quick Sql Network 模块,移除 Widget 源文件

BREAKING CHANGE: mainwindow.h/.cpp/.ui 已删除,UI 入口改为
src/ui/qml/main.qml。旧分支代码需同步此变更。

1.3 Tag 规范

采用 Semantic Versioning 2.0.0,格式 v<MAJOR>.<MINOR>.<PATCH>[-<pre-release>]

阶段Tag 示例说明
阶段里程碑v0.1-alphaM1:基础框架可运行
内部测试版v0.2-betaM5:菜单管理可用
正式候选v0.9-rc1M9:测试通过
正式发布v1.0.0M10:发布

Tag 分支来源: 仅从 main 分支打 Tag(在 release/* 合入后)。


1.4 .gitignore 维护

已存在的 .gitignore 规则覆盖了 Qt、编译产物、OS 文件、数据库文件、依赖目录。新增以下规则(如有需要直接在 .gitignore 末追加):

# IDE 临时文件(补充)
*.swp
*.swo
*~

# CMake 生成文件(补充)
CMakeCache.txt
CMakeFiles/
cmake_install.cmake
Makefile
*.cmake

# Qt Creator(补充)
*.autosave

# QML 编译缓存
*.qmlc
*.jsc
qmlcache/

# 打包产物
*.dmg
*.app
*.deb
*.rpm
*.apk

第二部分:代码规范

2.1 C++ 规范

命名

元素风格示例
类名PascalCaseInventoryRepository, AuthService
公开方法camelCasegetUserProfile(), calculateTDEE()
私有方法camelCase + 前缀 _p__validateToken(), p_executeSql()
成员变量camelCase + 尾缀 _dbConnection_, currentFamilyId_
常量kPascalCase 或 UPPER_SNAKE_CASEkDefaultPageSize / MAX_RETRY_COUNT
枚举值UPPER_SNAKE_CASEDietGoal::WEIGHT_LOSS
文件名snake_case(全小写下划线)base_repository.h, auth_service.cpp
命名空间snake_case(全小写)namespace smart_diet

头文件保护

// 使用 #pragma once(Qt 官方推荐,简洁且所有现代编译器支持)
#pragma once

// 不使用传统的 #ifndef / #define / #endif 三件套

Include 顺序

// 1. 本类对应的头文件
#include "auth_service.h"

// 2. Qt 库头文件(按模块字母序)
#include <QDateTime>
#include <QObject>
#include <QString>
#include <QtSql/QSqlDatabase>

// 3. 本项目内其他头文件(按目录层级)
#include "data/user_repository.h"
#include "utils/constants.h"

// 4. 标准库头文件
#include <memory>
#include <optional>

类结构模板

#pragma once

#include <QObject>

class AuthService : public QObject {
    Q_OBJECT

public:
    explicit AuthService(QObject *parent = nullptr);
    ~AuthService() override = default;

    // --- 公开接口 ---
    Q_INVOKABLE bool login(const QString &loginId, const QString &password);
    Q_INVOKABLE bool registerUser(const QVariantMap &profile);

signals:
    // --- 信号(遵循 动词-ed / 动词-过去式)---
    void loggedIn(const QString &userId);
    void errorOccurred(const QString &message, int errorCode);

private:
    // --- 私有方法 ---
    QString hashPassword(const QString &plainText) const;
    bool verifyPassword(const QString &plainText, const QString &hash) const;

    // --- 成员变量 ---
    class UserRepository *userRepo_ = nullptr;  // 依赖注入,不 new
};

其他约定

  • 禁止裸指针拥有所有权:Repository/Service 持有依赖时用 std::unique_ptr 或构造注入,不手动 new/delete
  • 优先 std::optional 而非返回哨兵值std::optional<User> getById(const QString& uuid) 优于返回空对象或 nullptr
  • C++17 特性可用if constexpr、结构化绑定、std::string_viewstd::optionalstd::variant
  • 禁止 using namespace std:头文件中绝对禁止,.cpp 中不鼓励

2.2 QML 规范

文件命名

元素风格示例
页面/视图PascalCase + Page 后缀HomePage.qml, LoginPage.qml
可复用组件PascalCaseNutritionRing.qml, BatchCard.qml
对话框/弹窗PascalCase + Dialog 后缀CookingDialog.qml
基础样式文件snake_casetheme_colors.js, font_sizes.js

QML 文件结构(从上到下)

// 1. import 语句(Qt 模块 → 第三方 → 项目内部)
import QtQuick
import QtQuick.Controls
import "../components" as C   // 项目组件

// 2. 根元素的 id 必须在最前
ApplicationWindow {
    id: root                   // 根节点 id 统一用 "root"

    // 3. 属性声明(property → 公开接口 → 内部状态)
    property int currentStep: 0
    readonly property bool isReady: currentStep > 0

    // 4. 信号声明
    signal stepCompleted(int stepIndex)

    // 5. 函数(公开 → 私有)
    function resetStep() { ... }

    // 6. 子元素(视觉树),嵌套缩进 4 空格
    Rectangle {
        id: header
        anchors { ... }
    }
}

命名约定

元素风格示例
idcamelCaseloginButton, calorieRing, headerNav
propertycamelCasecurrentMeal, isOffline
signalPascalCase 动词过去式loggedIn, menuConfirmed
functioncamelCase 动词refreshData(), navigateTo()

布局约定

  • 使用 anchors 优先于硬编码坐标,保证跨分辨率适配
  • 颜色统一引用自 Theme 单例(阶段 1.4 定义),禁止在 QML 中硬编码色值
  • 间距单位:小间距 8,中间距 16,大间距 24

严格禁止

  • ❌ 在 QML 中编写 SQL 语句
  • ❌ 在 QML 中调用网络 API(XMLHttpRequest / fetch
  • ❌ 在 QML 中包含 TDEE 计算、采购清单生成等业务逻辑
  • ❌ 使用 Qt.resolvedUrl() 进行跨模块硬路径引用

上述操作必须通过 C++ Service 层的 Q_INVOKABLE 方法或在 Connections 中监听信号完成。


2.3 目录与文件组织

src/
├── app/
│   └── main.cpp                      # 应用入口,仅此一个 .cpp

├── core/                             # Service 层
│   ├── base_service.h                # Service 抽象基类
│   ├── auth_service.h / .cpp         # 认证服务
│   ├── family_service.h / .cpp       # 家庭管理服务
│   ├── menu_service.h / .cpp         # 菜单服务
│   └── inventory_service.h / .cpp    # 库存服务

├── data/                             # Repository 层
│   ├── base_repository.h             # Repository 模板基类
│   ├── database_manager.h / .cpp     # 数据库连接管理(单例)
│   ├── user_repository.h / .cpp
│   ├── family_repository.h / .cpp
│   └── ...

├── network/                          # 网络通信层
│   ├── sync_manager.h / .cpp         # 同步队列与策略
│   ├── ws_client.h / .cpp            # WebSocket 客户端
│   └── http_client.h / .cpp          # HTTP REST 客户端

├── ui/
│   ├── qml/                          # 页面级 QML(每个页面一个文件)
│   │   ├── main.qml                  # QML 入口
│   │   ├── HomePage.qml
│   │   ├── LoginPage.qml
│   │   └── ...
│   ├── components/                   # 可复用 QML 组件
│   │   ├── NutritionRing.qml         # 营养环形图
│   │   ├── BatchCard.qml             # 批次卡片
│   │   └── ...
│   ├── styles/                       # 样式常量
│   │   ├── Theme.qml                 # 颜色、字体单例
│   │   └── Sizes.qml                 # 间距、圆角常量
│   └── views/                        # [留空] C++ ViewModel 宿主(如有需要)

├── utils/                            # 工具类
│   ├── constants.h                   # 全局常量、枚举
│   ├── uuid_generator.h / .cpp       # UUID 工具
│   └── time_utils.h / .cpp           # ISO 8601 转换工具

tests/
├── unit/                             # 单元测试(文件名 = 被测类 + _test)
│   ├── tdee_calculator_test.cpp
│   └── user_repository_test.cpp
└── integration/                      # 集成测试
    └── ws_sync_test.cpp

铁律:

  • 每个 .h 必须有且仅有一个对应 .cpp(除非是纯模板类)
  • 头文件放声明,.cpp 放实现。禁止在头文件中写函数体(简单的 getter/setter 除外)
  • 新模块必须在对应目录下,不得跨层放置

第三部分:文档维护规范

3.1 文档更新触发时机

触发条件应更新的文档说明
新增/修改 API005.接口设计文档.md同步更新接口定义、请求/响应示例
新增/修改表结构004.数据库设计文档.md同步更新 DDL、ER 图说明
架构层级调整001.概要设计文档.md同步更新分层图与职责描述
UI 页面新增/大改003.详细设计(原型设计).md保持原型与实装一致
新增安全机制007.安全设计文档.md记录新的安全措施
测试策略变化006.测试策略文档.md更新测试覆盖范围
开发计划调整008.项目开发计划.md更新阶段状态、工时、里程碑
每次工作结束docs/dev-log/YYYY年M月D日.md每日开发日志
任何规范变更009.开发规范文档.md(本文档)保持规范最新

3.2 文档修订记录规则

每个文档顶部的修订记录表必须更新:

  • 版本号:每次修改递增 minor(v1.0 → v1.1,实质性变更才跳 v2.0)
  • 日期:修改当天的日期
  • 修改说明:一句话说清改了什么,不要写”优化了部分内容”这种模糊描述

3.3 开发日志规范

日志文件路径:docs/dev-log/YYYY年M月D日.md

每日必写(结束工作前最后一步):

# 开发日志 - YYYY-MM-DD

## 今日完成
- [x] [任务名称 1] - [简要说明]
- [x] [任务名称 2] - [简要说明]

## 遇到的问题
1. [问题描述]
   → [解决方式 / 所需帮助]

## 明日计划
1. [任务名称] - [预估工时]
2. [任务名称] - [预估工时]

## 实际工时
__h / 计划 __h

## 备注
[可选:技术决策记录、踩坑备忘、灵感想法]

3.4 README 维护

  • 新增核心模块后,更新 readme.md 中「技术架构」或「项目结构」章节
  • 发布新版本后,更新 README 中的「最后更新」日期

第四部分:CMake 构建规范

4.1 目录级 CMakeLists.txt 模板

src/core/src/data/ 等目录出现 ≥2 个源文件时,应创建子目录 CMakeLists.txt

# src/core/CMakeLists.txt

# 收集本目录所有源文件
file(GLOB CORE_SOURCES
    "*.cpp"
    "*.h"
)

# 导出变量供父级 CMakeLists.txt 使用
set(CORE_SOURCES ${CORE_SOURCES} PARENT_SCOPE)

顶层 CMakeLists.txt 使用 add_subdirectory 引入:

add_subdirectory(src/core)
add_subdirectory(src/data)
# ...

set(PROJECT_SOURCES
    src/app/main.cpp
    ${CORE_SOURCES}
    ${DATA_SOURCES}
    ...
)

4.2 源文件添加规则

  • .cpp/.h 文件:自动通过 file(GLOB) 收集,无需手动在 CMakeLists.txt 中逐条添加
  • 新 QML 文件:必须同时添加到 resources.qrc 中,否则运行时无法加载
  • 新资源(图片/字体):放入 resources/ 对应子目录,并加入 resources.qrc

4.3 平台兼容要求

  • 不允许使用平台特定 API(#ifdef _WIN32 等)在业务层代码中出现
  • 如需平台差异,封装在 utils/ 下的独立工具类中
  • CMake 中 Qt5 兼容路径保留,但不新增 Qt5 特有逻辑

第五部分:单人开发自律规范

5.1 每日检查清单

每天开始工作前,回答三个问题:

  1. ☐ 今天做哪个阶段的任务?(对照 008.项目开发计划.md
  2. ☐ 是否依赖昨天未完成的工作?如果是,先收尾还是绕过去?
  3. ☐ 这个任务做完后,需要更新哪些文档?

每天结束工作前,执行以下动作:

  1. ☐ 写开发日志(docs/dev-log/
  2. ☐ 更新 008.项目开发计划.md 中的阶段进度表(实际工时、完成度)
  3. git add + git commit(即使不 push 也要本地提交)
  4. ☐ 如果今日有跨模块修改,运行一次编译确认无错误

5.2 代码提交前自检

每次 git commit 前必须逐条确认:

#检查项通过条件
1无注释掉的死代码删除,不注释。Git 历史可以恢复
2无调试打印移除所有 qDebug() / console.log() 调试输出
3Include 无冗余没有用了但忘删的头文件
4硬编码常量已提取色值、数字阈值、API URL 全部在 constants.hTheme.qml
5编译通过cmake --build 零 error,warnings ≤ 0(警告全部视为 error 处理)
6新功能无跨层调用UI 不直接调 Repository、Repository 不直接调网络
7文档已同步若修改了 API/DB/架构,对应设计文档已更新

5.3 阶段验收自检

每个阶段结束(里程碑 M1-M10),对照 008.项目开发计划.md 第七条验收标准逐条确认,并填写:

====================================
阶段 N 验收记录
日期:YYYY-MM-DD
====================================
验收项                             通过/不通过  备注
────────────────────────────────────────────────
✅ 代码可编译运行                   通过
✅ 分层架构符合设计                  通过
✅ 单元测试可运行                    通过
────────────────────────────────────────────────
遗留问题:
(无 / 列出)
────────────────────────────────────────────────
是否准出下一阶段:是 / 否
签字:___________  日期:___________

(签字行可选,但建议养成习惯)

5.4 “遇到困难”处理流程

当某个子任务实际耗时超过计划的 150% 时,强制执行:

  1. 暂停编码,在当天的开发日志中写明阻塞原因
  2. 判断原因类型:
    • 技术未知(没用过的新库/API)→ 先花 ≤2h 专项学习,再继续
    • 设计缺陷(前面的设计不支持此功能)→ 更新设计文档后再编码
    • 完美主义(反复调 UI 细节)→ 标记为 P2,先保功能完整
  3. 更新 008.项目开发计划.md 中的「调整记录」表

第六部分:其他约定

6.1 语言标准

场景语言
代码注释中文(简短提示可用英文,复杂逻辑必须中文)
Commit message中文 subject,body 中英均可
文档全部中文
代码符号(变量/函数/类)英文
UI 文案中文(通过 .ts 翻译文件管理)

6.2 版本号管理

CMakeLists.txt 中的 VERSION 与 Tag 同步更新。规则:

变更类型版本号变化示例
阶段里程碑MINOR +10.1 → 0.2
Bug 修复PATCH +10.1.0 → 0.1.1
正式发布直接跳 1.0.0

6.3 第三方库引入原则

  • 优先 Qt 内置模块:能用 Qt 自带的(QtSqlQtNetwork)绝不多引第三方
  • 必须引入第三方库时:记录在 docs/dev-log/ 当天的日志中,说明用途、版本、许可证
  • 第三方库放在 third_party/ 目录下,或通过 CMake FetchContent 引入

附录 A:快速查阅清单

我想知道…去看…
项目要做什么readme.md
产品需求细节002.产品需求文档PRD.md
UI 长什么样003.详细设计(原型设计).md
技术架构怎么搭的001.概要设计文档.md
数据库表结构004.数据库设计文档.md
API 怎么调005.接口设计文档.md
怎么测试006.测试策略文档.md
安全怎么做007.安全设计文档.md
现在做到哪了/下一步做什么008.项目开发计划.md
代码/提交/Git 怎么规范009.开发规范文档.md(本文档)
今天做了什么docs/dev-log/YYYY年M月D日.md