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.
Software_Architecture/.promptx/resource/domain/qt-code-optimizer/knowledge/code-quality-standards.know...

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);
}

代码审查检查清单

  • 功能正确性:代码是否实现了预期功能
  • 边界条件:是否处理了所有边界情况
  • 错误处理:是否有适当的错误处理机制
  • 性能考虑:是否存在性能瓶颈
  • 内存安全:是否存在内存泄漏或悬空指针
  • 线程安全:多线程环境下是否安全
  • 可读性:代码是否清晰易懂
  • 可维护性:代码是否便于后续维护