REFACTORING_GUIDE.md 4.9 KB

软总线架构重构指南

概述

本文档说明如何将现有的"胖客户端"模式重构为"核心-外壳"(Core-Shell)模式。

架构变化

旧架构(胖客户端模式)

UI Widget -> SerialManager -> 直接信号连接

新架构(核心-外壳模式)

UI Widget -> SoftBusAPI -> SoftBusCore -> MessageDispatcher -> ProtocolAdapter

重构步骤

Step 1: 更新 main.cpp

在程序入口处初始化新的架构:

#include "api/SoftBusAPI.h"
#include "core/SoftBusCore.h"
#include "core/pal/serial/SerialProtocolAdapter.h"
#include "serial_manager/serial_manager.h"
#include "soft_bus_core/soft_bus_core.h"

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    // 初始化新的软总线API
    SoftBusAPI* api = SoftBusAPI::instance();
    if (!api->initialize()) {
        qCritical() << "Failed to initialize SoftBusAPI";
        return -1;
    }

    // 创建旧的SoftBusCore(用于数据库等兼容性)
    SoftBusCore* oldBusCore = new SoftBusCore();
    oldBusCore->initDB("soft_bus_db");

    // 创建SerialManager(保持向后兼容)
    SerialManager* serialManager = new SerialManager(oldBusCore);

    // 创建协议适配器并注册
    SerialProtocolAdapter* serialAdapter = new SerialProtocolAdapter();
    serialAdapter->setSerialManager(serialManager);
    SoftBusCore::instance()->registerProtocolAdapter(serialAdapter);

    // 创建主窗口
    MainWindow window;
    window.show();

    return app.exec();
}

Step 2: 重构 SerialDockPage

旧代码(直接持有Manager):

class SerialDockPage : public MDockManager {
private:
    SoftBusCore *m_busCore;
    SerialManager *m_serialManager;  // 直接持有
    SerialDataWidget *m_serialDataWidget;
    
    void createConnections() {
        connect(m_serialManager, &SerialManager::dataReceived, 
                m_serialDataWidget, &SerialDataWidget::onSerialDataReceived);
    }
};

新代码(通过API):

#include "api/SoftBusAPI.h"

class SerialDockPage : public MDockManager {
private:
    SoftBusAPI* m_api;  // 只持有API引用
    
    void createConnections() {
        // 订阅所有数据变化
        m_api->subscribe("*");
        
        // 连接API的数据变化信号
        connect(m_api, &SoftBusAPI::dataChanged,
                this, &SerialDockPage::onDataChanged);
    }
    
private slots:
    void onDataChanged(QString tagName, QVariant value, int quality) {
        // 根据tagName更新对应的UI组件
        if (tagName.startsWith("Serial.")) {
            m_serialDataWidget->updateValue(tagName, value, quality);
        }
    }
};

Step 3: 重构 SerialDataWidget

旧代码:

class SerialDataWidget : public QWidget {
    void setSerialManager(SerialManager *manager) {
        m_serialManager = manager;
    }
    
    void on_btn_send_clicked() {
        m_serialManager->writeData(portName, data);
    }
};

新代码:

#include "api/SoftBusAPI.h"

class SerialDataWidget : public QWidget {
    void on_btn_send_clicked() {
        // 使用语义化的API发送控制指令
        SoftBusAPI::instance()->sendCommand("Pump.Main.Control", 1);
    }
    
    // 移除setSerialManager方法,不再需要
};

Step 4: 数据映射配置

创建映射配置文件 config/tag_mapping.json

{
  "tags": [
    {
      "sourceId": "COM1:Dev1:40001",
      "tagName": "Tank.Level",
      "scale": 0.1,
      "offset": 0.0,
      "deadband": 1.0,
      "domain": "Process"
    },
    {
      "sourceId": "COM1:Dev1:40002",
      "tagName": "Pump.Outlet.Pressure",
      "scale": 1.0,
      "offset": 0.0,
      "deadband": 0.5,
      "domain": "Process"
    },
    {
      "sourceId": "COM1:Dev1:40010",
      "tagName": "Pump.Main.Control",
      "domain": "Control"
    }
  ]
}

在初始化时加载:

SoftBusCore* core = SoftBusCore::instance();
core->getDataMapper()->loadProfile("config/tag_mapping.json");

迁移检查清单

  • 更新 main.cpp 初始化新架构
  • 移除UI类中的Manager成员变量
  • 将直接信号连接改为API订阅
  • 将直接方法调用改为API调用
  • 创建数据映射配置文件
  • 更新CMakeLists.txt包含新文件
  • 测试数据流:串口 -> 适配器 -> 调度器 -> API -> UI
  • 测试控制指令:UI -> API -> 调度器 -> 适配器 -> 串口

注意事项

  1. 向后兼容:旧的SoftBusCore和SerialManager仍然保留,用于数据库等兼容性功能
  2. 逐步迁移:不要一次性重构所有代码,先重构一个模块验证流程
  3. 数据映射:确保所有物理地址都有对应的逻辑点名映射
  4. 信号槽:使用Qt::QueuedConnection确保线程安全

下一步扩展

  1. 实现CAN协议适配器(类似SerialProtocolAdapter)
  2. 实现共享内存传输(零拷贝)
  3. 实现分布式发现和通信
  4. 添加数据存储模块(PostgreSQL)