前言
在前端工程化搭建完成后,我们需要构建高性能的后端业务逻辑层。本文将深入介绍位于 code/backend/dll/ 目录下的C++ DLL开发实践,包括模块化架构设计、CMake构建系统配置,以及如何实现可扩展的业务逻辑框架。
后端架构设计理念
为什么选择C++ DLL?
相比纯Web后端方案,C++ DLL架构具有以下优势:
- 性能优势: 原生C++代码执行效率高,特别适合数据密集型操作
- 内存管理: 精确的内存控制,避免垃圾回收开销
- 系统集成: 可以直接调用操作系统API和第三方库
- 部署简单: 单文件DLL部署,无需复杂的运行时环境
- 前后端解耦: 通过标准化接口实现完全的前后端分离
模块化设计原则
从
code/backend/dll/CMakeLists.txt 中可以看到我们的模块化组织:
# 按功能模块组织源代码文件
file(GLOB IMPL_BOOKMANAGER_GROUP_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/Src/Impl/BookManager/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Src/Impl/BookManager/*.h"
)
file(GLOB IMPL_BOOKMANAGER_ADDBOOK_GROUP_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/Src/Impl/BookManager/AddBook/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Src/Impl/BookManager/AddBook/*.h"
)
file(GLOB IMPL_LOANMANAGER_GROUP_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/Src/Impl/LoanManager/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Src/Impl/LoanManager/*.h"
)
file(GLOB IMPL_DASHBOARD_GROUP_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/Src/Impl/DashBoard/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Src/Impl/DashBoard/*.h"
)
模块设计特点:
- 功能内聚: 每个模块负责特定的业务领域
- 层次分明: 主模块下按操作类型进一步细分
- 接口统一: 所有模块遵循统一的调用约定
- 依赖清晰: 模块间依赖关系明确可控
项目结构深度解析
目录结构设计
code/backend/dll/
├── CMakeLists.txt # CMake构建配置
├── Src/ # 源代码目录
│ ├── Impl/ # 业务逻辑实现
│ │ ├── BookManager/ # 图书管理模块
│ │ │ ├── AddBook/ # 添加图书功能
│ │ │ ├── DeleteBook/ # 删除图书功能
│ │ │ ├── EditBook/ # 编辑图书功能
│ │ │ └── GetBookList/ # 图书列表功能
│ │ ├── ReaderManager/ # 读者管理模块
│ │ ├── LoanManager/ # 借阅管理模块
│ │ ├── DashBoard/ # 仪表板模块
│ │ ├── QuerySearch/ # 查询搜索模块
│ │ ├── StatisticsReport/ # 统计报表模块
│ │ ├── SystemSettings/ # 系统设置模块
│ │ ├── LibGlobal/ # 全局管理模块
│ │ └── Persist/ # 数据持久化模块
│ ├── ModExport/ # 模块导出定义
│ ├── BookManagerCAPI.cpp # 图书管理C接口
│ ├── ReaderManagerCAPI.cpp # 读者管理C接口
│ ├── LoanManagerCAPI.cpp # 借阅管理C接口
│ └── DashBoardCAPI.cpp # 仪表板C接口
└── export/ # 导出头文件
CMake构建系统分析
从
code/backend/dll/CMakeLists.txt 的配置可以看出严格的构建规范:
cmake_minimum_required(VERSION 3.10)
project (libBackend)
# 环境变量配置
SET(UNISDK_ROOT_PROJ "$ENV{UNISDK_ROOT}")
# 头文件包含路径
include_directories(./Src)
include_directories(${UNISDK_ROOT_PROJ}/export_csdk/)
include_directories(${UNISDK_ROOT_PROJ}/export_cppsdk/)
include_directories(${UNISDK_ROOT_PROJ}/export_cppsdk/cppsdk/third/)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../submod_include)
构建特点:
- 模块化编译: 每个功能模块独立编译
- 依赖管理: 统一的头文件和库依赖管理
- 环境适配: 支持不同开发环境的配置
- 版本控制: CMake版本要求明确
核心业务模块实现
1. 图书管理模块 (BookManager)
图书管理是系统的核心功能,我们采用CRUD+列表的标准模式:
// Src/Impl/BookManager/BookManager.h
#ifndef BOOK_MANAGER_H
#define BOOK_MANAGER_H
#include "Common/BaseResult.h"
#include "Common/JsonHelper.h"
#include <string>
namespace LibrarySystem {
namespace BookManager {
class BookManagerImpl {
public:
static bool AddBook(const std::string& bookJson, std::string& resultJson);
static bool DeleteBook(const std::string& bookId, std::string& resultJson);
static bool EditBook(const std::string& bookJson, std::string& resultJson);
static bool GetBookList(const std::string& queryJson, std::string& resultJson);
static bool GetBookDetail(const std::string& bookId, std::string& resultJson);
private:
static bool ValidateBookData(const JsonObject& bookData);
static bool CheckBookExists(const std::string& bookId);
static std::string GenerateBookId();
};
} // namespace BookManager
} // namespace LibrarySystem
#endif // BOOK_MANAGER_H
添加图书功能实现
// Src/Impl/BookManager/AddBook/AddBookImpl.cpp
#include "BookManager.h"
#include "Database/DatabaseManager.h"
#include "Common/LogManager.h"
namespace LibrarySystem {
namespace BookManager {
bool BookManagerImpl::AddBook(const std::string& bookJson, std::string& resultJson) {
bool bRet = false;
JsonObject result;
try {
// 解析输入JSON
JsonObject bookData;
if (!JsonHelper::Parse(bookJson, bookData)) {
result["success"] = false;
result["error"] = "Invalid JSON format";
resultJson = JsonHelper::Stringify(result);
goto exit;
}
// 验证数据完整性
if (!ValidateBookData(bookData)) {
result["success"] = false;
result["error"] = "Invalid book data";
resultJson = JsonHelper::Stringify(result);
goto exit;
}
// 检查ISBN是否已存在
std::string isbn = bookData["isbn"].asString();
if (CheckBookExists(isbn)) {
result["success"] = false;
result["error"] = "Book already exists";
resultJson = JsonHelper::Stringify(result);
goto exit;
}
// 生成唯一ID
std::string bookId = GenerateBookId();
bookData["id"] = bookId;
bookData["addedDate"] = JsonHelper::GetCurrentTimestamp();
// 保存到数据库
DatabaseManager& db = DatabaseManager::GetInstance();
if (!db.InsertBook(bookData)) {
result["success"] = false;
result["error"] = "Database operation failed";
resultJson = JsonHelper::Stringify(result);
goto exit;
}
// 成功返回
result["success"] = true;
result["bookId"] = bookId;
resultJson = JsonHelper::Stringify(result);
bRet = true;
} catch (const std::exception& e) {
LogManager::Error("AddBook failed: %s", e.what());
result["success"] = false;
result["error"] = "Internal error";
resultJson = JsonHelper::Stringify(result);
}
exit:
return bRet;
}
bool BookManagerImpl::ValidateBookData(const JsonObject& bookData) {
// 验证必需字段
const std::vector<std::string> requiredFields = {
"title", "author", "isbn", "category", "publisher"
};
for (const auto& field : requiredFields) {
if (!bookData.has(field) || bookData[field].asString().empty()) {
return false;
}
}
// 验证ISBN格式
std::string isbn = bookData["isbn"].asString();
if (isbn.length() != 13 && isbn.length() != 10) {
return false;
}
return true;
}
} // namespace BookManager
} // namespace LibrarySystem
2. 借阅管理模块 (LoanManager)
借阅管理涉及复杂的业务逻辑,包括借书、还书、续借、超期处理等:
// Src/Impl/LoanManager/LoanManager.h
#ifndef LOAN_MANAGER_H
#define LOAN_MANAGER_H
#include "Common/BaseResult.h"
#include <string>
namespace LibrarySystem {
namespace LoanManager {
class LoanManagerImpl {
public:
static bool BorrowBook(const std::string& requestJson, std::string& resultJson);
static bool ReturnBook(const std::string& requestJson, std::string& resultJson);
static bool RenewBook(const std::string& requestJson, std::string& resultJson);
static bool GetBorrowRecords(const std::string& queryJson, std::string& resultJson);
static bool GetOverdueBooks(std::string& resultJson);
private:
static bool CheckBookAvailability(const std::string& bookId);
static bool CheckUserBorrowLimit(const std::string& userId);
static bool CalculateDueDate(const std::string& borrowDate, std::string& dueDate);
static bool CheckOverdue(const std::string& dueDate);
};
} // namespace LoanManager
} // namespace LibrarySystem
#endif // LOAN_MANAGER_H
借书功能实现
// Src/Impl/LoanManager/BorrowBook/BorrowBookImpl.cpp
#include "LoanManager.h"
#include "Database/DatabaseManager.h"
#include "Common/DateTimeHelper.h"
namespace LibrarySystem {
namespace LoanManager {
bool LoanManagerImpl::BorrowBook(const std::string& requestJson, std::string& resultJson) {
bool bRet = false;
JsonObject result;
try {
JsonObject request;
if (!JsonHelper::Parse(requestJson, request)) {
result["success"] = false;
result["error"] = "Invalid request format";
resultJson = JsonHelper::Stringify(result);
goto exit;
}
std::string bookId = request["bookId"].asString();
std::string userId = request["userId"].asString();
// 检查图书可用性
if (!CheckBookAvailability(bookId)) {
result["success"] = false;
result["error"] = "Book not available";
resultJson = JsonHelper::Stringify(result);
goto exit;
}
// 检查用户借阅限制
if (!CheckUserBorrowLimit(userId)) {
result["success"] = false;
result["error"] = "User borrow limit exceeded";
resultJson = JsonHelper::Stringify(result);
goto exit;
}
// 计算归还日期
std::string currentDate = DateTimeHelper::GetCurrentDate();
std::string dueDate;
if (!CalculateDueDate(currentDate, dueDate)) {
result["success"] = false;
result["error"] = "Failed to calculate due date";
resultJson = JsonHelper::Stringify(result);
goto exit;
}
// 创建借阅记录
JsonObject borrowRecord;
borrowRecord["id"] = GenerateBorrowId();
borrowRecord["bookId"] = bookId;
borrowRecord["userId"] = userId;
borrowRecord["borrowDate"] = currentDate;
borrowRecord["dueDate"] = dueDate;
borrowRecord["status"] = "active";
DatabaseManager& db = DatabaseManager::GetInstance();
// 开启事务
if (!db.BeginTransaction()) {
result["success"] = false;
result["error"] = "Transaction failed";
resultJson = JsonHelper::Stringify(result);
goto exit;
}
// 插入借阅记录
if (!db.InsertBorrowRecord(borrowRecord)) {
db.RollbackTransaction();
result["success"] = false;
result["error"] = "Failed to create borrow record";
resultJson = JsonHelper::Stringify(result);
goto exit;
}
// 更新图书状态
if (!db.UpdateBookStatus(bookId, "borrowed")) {
db.RollbackTransaction();
result["success"] = false;
result["error"] = "Failed to update book status";
resultJson = JsonHelper::Stringify(result);
goto exit;
}
// 提交事务
if (!db.CommitTransaction()) {
result["success"] = false;
result["error"] = "Transaction commit failed";
resultJson = JsonHelper::Stringify(result);
goto exit;
}
result["success"] = true;
result["borrowId"] = borrowRecord["id"].asString();
result["dueDate"] = dueDate;
resultJson = JsonHelper::Stringify(result);
bRet = true;
} catch (const std::exception& e) {
DatabaseManager::GetInstance().RollbackTransaction();
LogManager::Error("BorrowBook failed: %s", e.what());
result["success"] = false;
result["error"] = "Internal error";
resultJson = JsonHelper::Stringify(result);
}
exit:
return bRet;
}
} // namespace LoanManager
} // namespace LibrarySystem
3. 仪表板模块 (Dashboard)
仪表板提供系统概览数据,需要高效的数据聚合能力:
// Src/Impl/DashBoard/DashBoardImpl.cpp
#include "DashBoard.h"
#include "Database/DatabaseManager.h"
namespace LibrarySystem {
namespace Dashboard {
bool DashboardImpl::GetDashboardStats(std::string& resultJson) {
bool bRet = false;
JsonObject result;
try {
DatabaseManager& db = DatabaseManager::GetInstance();
// 获取图书统计
int totalBooks = db.GetTotalBooksCount();
int availableBooks = db.GetAvailableBooksCount();
int borrowedBooks = db.GetBorrowedBooksCount();
// 获取用户统计
int totalUsers = db.GetTotalUsersCount();
int activeUsers = db.GetActiveUsersCount();
// 获取借阅统计
int activeBorrows = db.GetActiveBorrowsCount();
int overdueBooks = db.GetOverdueBooksCount();
int todayBorrows = db.GetTodayBorrowsCount();
int todayReturns = db.GetTodayReturnsCount();
// 组装结果
JsonObject stats;
stats["totalBooks"] = totalBooks;
stats["availableBooks"] = availableBooks;
stats["borrowedBooks"] = borrowedBooks;
stats["totalUsers"] = totalUsers;
stats["activeUsers"] = activeUsers;
stats["activeBorrows"] = activeBorrows;
stats["overdueBooks"] = overdueBooks;
stats["todayBorrows"] = todayBorrows;
stats["todayReturns"] = todayReturns;
// 获取图表数据
JsonArray borrowTrend = db.GetBorrowTrendData(30); // 最近30天
JsonArray categoryDistribution = db.GetCategoryDistributionData();
result["success"] = true;
result["stats"] = stats;
result["borrowTrend"] = borrowTrend;
result["categoryDistribution"] = categoryDistribution;
resultJson = JsonHelper::Stringify(result);
bRet = true;
} catch (const std::exception& e) {
LogManager::Error("GetDashboardStats failed: %s", e.what());
result["success"] = false;
result["error"] = "Failed to get dashboard stats";
resultJson = JsonHelper::Stringify(result);
}
return bRet;
}
} // namespace Dashboard
} // namespace LibrarySystem
公共基础设施
1. 数据库管理器
// Src/Common/Database/DatabaseManager.h
#ifndef DATABASE_MANAGER_H
#define DATABASE_MANAGER_H
#include <sqlite3.h>
#include <string>
#include <memory>
#include "Common/Singleton.h"
namespace LibrarySystem {
class DatabaseManager : public Singleton<DatabaseManager> {
public:
bool Initialize(const std::string& dbPath);
void Shutdown();
// 事务管理
bool BeginTransaction();
bool CommitTransaction();
bool RollbackTransaction();
// 图书操作
bool InsertBook(const JsonObject& bookData);
bool UpdateBook(const std::string& bookId, const JsonObject& bookData);
bool DeleteBook(const std::string& bookId);
bool GetBookById(const std::string& bookId, JsonObject& bookData);
// 统计查询
int GetTotalBooksCount();
int GetAvailableBooksCount();
JsonArray GetBorrowTrendData(int days);
private:
sqlite3* m_db;
bool m_initialized;
bool CreateTables();
bool ExecuteSQL(const std::string& sql);
bool PrepareStatement(const std::string& sql, sqlite3_stmt** stmt);
};
} // namespace LibrarySystem
#endif // DATABASE_MANAGER_H
2. JSON处理工具
// Src/Common/JsonHelper.h
#ifndef JSON_HELPER_H
#define JSON_HELPER_H
#include <json/json.h>
#include <string>
namespace LibrarySystem {
using JsonObject = Json::Value;
using JsonArray = Json::Value;
class JsonHelper {
public:
static bool Parse(const std::string& jsonStr, JsonObject& jsonObj);
static std::string Stringify(const JsonObject& jsonObj);
static std::string GetCurrentTimestamp();
static bool ValidateSchema(const JsonObject& jsonObj, const JsonObject& schema);
private:
static Json::StreamWriterBuilder GetWriterBuilder();
static Json::CharReaderBuilder GetReaderBuilder();
};
} // namespace LibrarySystem
#endif // JSON_HELPER_H
3. 日志管理系统
// Src/Common/LogManager.h
#ifndef LOG_MANAGER_H
#define LOG_MANAGER_H
#include <string>
#include <fstream>
#include <mutex>
namespace LibrarySystem {
enum class LogLevel {
DEBUG = 0,
INFO = 1,
WARNING = 2,
ERROR = 3
};
class LogManager {
public:
static void Initialize(const std::string& logPath, LogLevel level = LogLevel::INFO);
static void Shutdown();
static void Debug(const char* format, ...);
static void Info(const char* format, ...);
static void Warning(const char* format, ...);
static void Error(const char* format, ...);
private:
static void WriteLog(LogLevel level, const std::string& message);
static std::string GetCurrentTime();
static std::string GetLogLevelString(LogLevel level);
static std::ofstream s_logFile;
static std::mutex s_logMutex;
static LogLevel s_logLevel;
static bool s_initialized;
};
} // namespace LibrarySystem
#endif // LOG_MANAGER_H
DLL导出接口设计
统一的C接口
// Src/Interface/LibraryAPI.h
#ifndef LIBRARY_API_H
#define LIBRARY_API_H
#ifdef _WIN32
#ifdef LIBRARY_EXPORTS
#define LIBRARY_API __declspec(dllexport)
#else
#define LIBRARY_API __declspec(dllimport)
#endif
#define LIBRARY_CALL __stdcall
#else
#define LIBRARY_API
#define LIBRARY_CALL
#endif
extern "C" {
// 库初始化
LIBRARY_API bool LIBRARY_CALL InitLibrary(const char* configJson);
LIBRARY_API void LIBRARY_CALL ShutdownLibrary();
// 图书管理
LIBRARY_API bool LIBRARY_CALL AddBook(const char* bookJson, char* resultJson, int resultSize);
LIBRARY_API bool LIBRARY_CALL DeleteBook(const char* bookId, char* resultJson, int resultSize);
LIBRARY_API bool LIBRARY_CALL EditBook(const char* bookJson, char* resultJson, int resultSize);
LIBRARY_API bool LIBRARY_CALL GetBookList(const char* queryJson, char* resultJson, int resultSize);
// 借阅管理
LIBRARY_API bool LIBRARY_CALL BorrowBook(const char* requestJson, char* resultJson, int resultSize);
LIBRARY_API bool LIBRARY_CALL ReturnBook(const char* requestJson, char* resultJson, int resultSize);
LIBRARY_API bool LIBRARY_CALL GetBorrowRecords(const char* queryJson, char* resultJson, int resultSize);
// 仪表板
LIBRARY_API bool LIBRARY_CALL GetDashboardStats(char* resultJson, int resultSize);
}
#endif // LIBRARY_API_H
接口实现
// Src/Interface/LibraryAPI.cpp
#include "LibraryAPI.h"
#include "Impl/BookManager/BookManager.h"
#include "Impl/LoanManager/LoanManager.h"
#include "Impl/DashBoard/DashBoard.h"
#include "Common/LogManager.h"
using namespace LibrarySystem;
extern "C" {
LIBRARY_API bool LIBRARY_CALL InitLibrary(const char* configJson) {
try {
JsonObject config;
if (!JsonHelper::Parse(configJson, config)) {
return false;
}
// 初始化日志系统
std::string logPath = config["logPath"].asString();
LogManager::Initialize(logPath);
// 初始化数据库
std::string dbPath = config["dbPath"].asString();
DatabaseManager& db = DatabaseManager::GetInstance();
if (!db.Initialize(dbPath)) {
return false;
}
LogManager::Info("Library initialized successfully");
return true;
} catch (...) {
return false;
}
}
LIBRARY_API bool LIBRARY_CALL AddBook(const char* bookJson, char* resultJson, int resultSize) {
try {
std::string result;
bool success = BookManager::BookManagerImpl::AddBook(bookJson, result);
if (result.length() < static_cast<size_t>(resultSize)) {
strcpy_s(resultJson, resultSize, result.c_str());
return success;
}
return false;
} catch (...) {
return false;
}
}
LIBRARY_API bool LIBRARY_CALL GetDashboardStats(char* resultJson, int resultSize) {
try {
std::string result;
bool success = Dashboard::DashboardImpl::GetDashboardStats(result);
if (result.length() < static_cast<size_t>(resultSize)) {
strcpy_s(resultJson, resultSize, result.c_str());
return success;
}
return false;
} catch (...) {
return false;
}
}
} // extern "C"
性能优化策略
1. 内存管理优化
// 使用智能指针管理资源
class BookManager {
private:
std::unique_ptr<DatabaseConnection> m_dbConnection;
std::shared_ptr<CacheManager> m_cache;
public:
BookManager()
: m_dbConnection(std::make_unique<DatabaseConnection>())
, m_cache(std::make_shared<CacheManager>()) {}
};
// 使用内存池减少分配开销
class MemoryPool {
public:
template<typename T>
T* Allocate() {
return static_cast<T*>(GetBlock(sizeof(T)));
}
template<typename T>
void Deallocate(T* ptr) {
ReturnBlock(ptr, sizeof(T));
}
};
2. 数据库连接优化
// 连接池管理
class ConnectionPool {
private:
std::queue<sqlite3*> m_availableConnections;
std::mutex m_mutex;
int m_maxConnections;
public:
sqlite3* AcquireConnection() {
std::lock_guard<std::mutex> lock(m_mutex);
if (!m_availableConnections.empty()) {
sqlite3* conn = m_availableConnections.front();
m_availableConnections.pop();
return conn;
}
return CreateNewConnection();
}
void ReleaseConnection(sqlite3* conn) {
std::lock_guard<std::mutex> lock(m_mutex);
m_availableConnections.push(conn);
}
};
3. 缓存策略
// LRU缓存实现
template<typename K, typename V>
class LRUCache {
private:
std::unordered_map<K, typename std::list<std::pair<K, V>>::iterator> m_map;
std::list<std::pair<K, V>> m_list;
size_t m_capacity;
public:
V Get(const K& key) {
auto it = m_map.find(key);
if (it != m_map.end()) {
// 移动到前面
m_list.splice(m_list.begin(), m_list, it->second);
return it->second->second;
}
return V{};
}
void Put(const K& key, const V& value) {
auto it = m_map.find(key);
if (it != m_map.end()) {
it->second->second = value;
m_list.splice(m_list.begin(), m_list, it->second);
return;
}
if (m_list.size() >= m_capacity) {
// 删除最少使用的
m_map.erase(m_list.back().first);
m_list.pop_back();
}
m_list.emplace_front(key, value);
m_map[key] = m_list.begin();
}
};
错误处理与调试
异常安全的代码结构
// RAII资源管理
class DatabaseTransaction {
private:
DatabaseManager& m_db;
bool m_committed;
public:
DatabaseTransaction(DatabaseManager& db) : m_db(db), m_committed(false) {
m_db.BeginTransaction();
}
~DatabaseTransaction() {
if (!m_committed) {
m_db.RollbackTransaction();
}
}
void Commit() {
m_db.CommitTransaction();
m_committed = true;
}
};
// 使用示例
bool AddBookWithTransaction(const JsonObject& bookData) {
try {
DatabaseTransaction trans(DatabaseManager::GetInstance());
// 执行数据库操作
if (!ValidateAndInsertBook(bookData)) {
return false; // 析构函数会自动回滚
}
trans.Commit(); // 手动提交
return true;
} catch (...) {
return false; // 异常时自动回滚
}
}
下期预告
在下一篇文章中,我们将详细介绍前后端集成的关键技术:如何使用koffi实现JavaScript与C++ DLL的无缝调用,包括数据类型转换、错误处理、性能优化等关键实践。
总结
本文深入介绍了C++ DLL后端开发的完整实践,包括:
- 模块化架构设计: 清晰的功能模块划分和依赖关系
- CMake构建系统: 灵活的构建配置和依赖管理
- 业务逻辑实现: 高质量的C++代码和最佳实践
- 公共基础设施: 数据库、日志、JSON等工具封装
- 性能优化策略: 内存管理、缓存、连接池等优化手段
- 错误处理机制: 异常安全和资源管理
通过这些实践,我们构建了一个高性能、可维护、可扩展的C++后端系统,为前端应用提供了坚实的业务逻辑支撑。
系列文章目录
- 项目架构设计与技术选型[1]
- 高保真原型设计与用户体验测试[2]
- 前端工程化实践:Electron + React + TypeScript[3]
- 后端C++ DLL开发与模块化设计[4]
- 前后端集成:koffi调用与接口设计[5]
- Google Test单元测试实践[6]
- CMake构建系统与持续集成[7]
- 性能优化与部署发布[8]
通过这个系列文章,您将学习到现代桌面应用开发的完整流程和最佳实践。
程序及源码附件下载
程序及源码[9]
引用链接
[1]项目架构设计与技术选型:
https://www.itgather.com/article/art_KvjCE
[2]高保真原型设计与用户体验测试:
https://www.itgather.com/article/art_Mb7GB
[3]前端工程化实践:Electron + React + TypeScript:
https://www.itgather.com/article/art_MxnCz
[4]后端C++ DLL开发与模块化设计:
https://www.itgather.com/article/art_NeAEP
[5]前后端集成:koffi调用与接口设计:
https://www.itgather.com/article/art_NzrCw
[6]Google Test单元测试实践:
https://www.itgather.com/article/art_PMXCa
[7]CMake构建系统与持续集成:
https://www.itgather.com/article/art_PgDEr
[8]性能优化与部署发布:
https://www.itgather.com/article/art_P3uHy
[9]程序及源码:
https://download.csdn.net/download/itgather/91534878