You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
7.7 KiB
7.7 KiB
代码质量标准知识体系
编码规范标准
Qt Coding Style
// 类名使用帕斯卡命名法
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void onButtonClicked(); // 槽函数使用on前缀
private:
Ui::MainWindow *ui; // 成员变量使用驼峰命名
QTimer *m_timer; // 私有成员使用m_前缀
};
Google C++ Style Guide要点
- 命名约定:类名PascalCase,函数名camelCase,常量UPPER_CASE
- 文件组织:头文件包含顺序,前向声明的使用
- 代码格式:缩进、空格、换行的统一标准
- 注释规范:文档注释和行内注释的写法
现代C++最佳实践
// 使用auto进行类型推导
auto widget = std::make_unique<QWidget>();
// 使用范围for循环
for (const auto& item : container) {
// 处理item
}
// 使用初始化列表
class MyClass {
public:
MyClass(int value) : m_value{value} {} // 统一初始化语法
private:
int m_value;
};
代码质量度量
复杂度指标
- 圈复杂度:衡量代码逻辑复杂性,建议≤10
- 认知复杂度:衡量代码理解难度,建议≤15
- 嵌套深度:控制结构嵌套层数,建议≤4
- 函数长度:单个函数行数,建议≤50行
重复代码检测
// 避免代码重复,提取公共函数
void setupButton(QPushButton* button, const QString& text,
const QString& iconPath) {
button->setText(text);
button->setIcon(QIcon(iconPath));
button->setStyleSheet("QPushButton { padding: 8px; }");
}
耦合度分析
- 传入耦合(Ca):依赖此模块的其他模块数量
- 传出耦合(Ce):此模块依赖的其他模块数量
- 不稳定性(I):I = Ce / (Ca + Ce),值越小越稳定
- 抽象度(A):抽象类占总类数的比例
设计质量原则
SOLID原则
// 单一职责原则 (SRP)
class FileReader {
public:
QString readFile(const QString& filename);
};
class FileWriter {
public:
bool writeFile(const QString& filename, const QString& content);
};
// 开闭原则 (OCP)
class Shape {
public:
virtual double area() const = 0;
virtual ~Shape() = default;
};
class Rectangle : public Shape {
public:
Rectangle(double width, double height) : m_width(width), m_height(height) {}
double area() const override { return m_width * m_height; }
private:
double m_width, m_height;
};
// 里氏替换原则 (LSP)
// 子类对象应该能够替换父类对象而不影响程序正确性
// 接口隔离原则 (ISP)
class Readable {
public:
virtual QString read() = 0;
virtual ~Readable() = default;
};
class Writable {
public:
virtual bool write(const QString& data) = 0;
virtual ~Writable() = default;
};
// 依赖倒置原则 (DIP)
class DataProcessor {
public:
DataProcessor(std::unique_ptr<Readable> reader)
: m_reader(std::move(reader)) {}
void process() {
QString data = m_reader->read();
// 处理数据
}
private:
std::unique_ptr<Readable> m_reader;
};
DRY原则 (Don't Repeat Yourself)
// 避免重复代码,使用模板或函数
template<typename T>
void connectSignalSlot(T* sender, void(T::*signal)(),
QObject* receiver, void(QObject::*slot)()) {
QObject::connect(sender, signal, receiver, slot);
}
KISS原则 (Keep It Simple, Stupid)
// 简单直接的实现
bool isValidEmail(const QString& email) {
return email.contains('@') && email.contains('.');
}
// 而不是复杂的正则表达式(除非确实需要)
错误处理和异常安全
异常安全等级
// 基本保证:不会泄漏资源
class BasicSafety {
public:
void operation() {
auto resource = std::make_unique<Resource>();
// 即使抛出异常,resource也会自动释放
doSomething();
}
};
// 强异常安全:操作要么成功,要么保持原状
class StrongSafety {
public:
void operation() {
auto backup = m_data; // 备份当前状态
try {
modifyData();
} catch (...) {
m_data = backup; // 恢复原状
throw;
}
}
private:
Data m_data;
};
// 无异常保证:操作绝不抛出异常
class NoThrow {
public:
void operation() noexcept {
// 确保不会抛出异常的操作
}
};
Qt错误处理模式
// 使用返回值表示错误状态
enum class FileError {
Success,
FileNotFound,
PermissionDenied,
InvalidFormat
};
class FileManager {
public:
FileError loadFile(const QString& filename, QString& content) {
QFile file(filename);
if (!file.exists()) {
return FileError::FileNotFound;
}
if (!file.open(QIODevice::ReadOnly)) {
return FileError::PermissionDenied;
}
content = file.readAll();
return FileError::Success;
}
};
性能和内存管理
RAII (Resource Acquisition Is Initialization)
class DatabaseConnection {
public:
DatabaseConnection(const QString& connectionString) {
m_db = QSqlDatabase::addDatabase("QSQLITE");
m_db.setDatabaseName(connectionString);
if (!m_db.open()) {
throw std::runtime_error("Failed to open database");
}
}
~DatabaseConnection() {
if (m_db.isOpen()) {
m_db.close();
}
}
// 禁止拷贝
DatabaseConnection(const DatabaseConnection&) = delete;
DatabaseConnection& operator=(const DatabaseConnection&) = delete;
// 允许移动
DatabaseConnection(DatabaseConnection&&) = default;
DatabaseConnection& operator=(DatabaseConnection&&) = default;
private:
QSqlDatabase m_db;
};
智能指针使用指南
// unique_ptr:独占所有权
std::unique_ptr<QWidget> createWidget() {
return std::make_unique<QPushButton>("Click me");
}
// shared_ptr:共享所有权
std::shared_ptr<DataModel> getModel() {
static auto model = std::make_shared<DataModel>();
return model;
}
// weak_ptr:避免循环引用
class Parent {
public:
void addChild(std::shared_ptr<Child> child) {
m_children.push_back(child);
child->setParent(shared_from_this());
}
private:
std::vector<std::shared_ptr<Child>> m_children;
};
class Child {
public:
void setParent(std::shared_ptr<Parent> parent) {
m_parent = parent; // 使用weak_ptr避免循环引用
}
private:
std::weak_ptr<Parent> m_parent;
};
测试和质量保证
单元测试最佳实践
class TestCalculator : public QObject {
Q_OBJECT
private slots:
void testAddition_data();
void testAddition();
void testDivisionByZero();
private:
Calculator m_calculator;
};
void TestCalculator::testAddition_data() {
QTest::addColumn<int>("a");
QTest::addColumn<int>("b");
QTest::addColumn<int>("expected");
QTest::newRow("positive numbers") << 2 << 3 << 5;
QTest::newRow("negative numbers") << -2 << -3 << -5;
QTest::newRow("mixed numbers") << -2 << 3 << 1;
}
void TestCalculator::testAddition() {
QFETCH(int, a);
QFETCH(int, b);
QFETCH(int, expected);
QCOMPARE(m_calculator.add(a, b), expected);
}
代码审查检查清单
- 功能正确性:代码是否实现了预期功能
- 边界条件:是否处理了所有边界情况
- 错误处理:是否有适当的错误处理机制
- 性能考虑:是否存在性能瓶颈
- 内存安全:是否存在内存泄漏或悬空指针
- 线程安全:多线程环境下是否安全
- 可读性:代码是否清晰易懂
- 可维护性:代码是否便于后续维护