目录

SQLite

什么是 SQLite

为什么要用 SQLite

SQLite3 C/C++ API 介绍

SQLite3 C/C++ API 使用

GTest

GTest 是什么

GTest 使用

TEST 宏

断言

事件机制

全局事件

TestSuite 事件


SQLite

什么是 SQLite

        SQLite 是一个进程内的轻量级数据库,它实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其他数据库不一样,我们不需要在系统中配置。像其他数据库,SQLite 引擎不是一个独立的进程,可以按应用程序需求进行静态或动态连接,SQLite 直接访问其存储文件。

为什么要用 SQLite

  • 不需要一个单独的服务器进程或操作的系统(无服务器的)。
  • SQLite 不需要配置。
  • 一个完整的 SQLite 数据库是存储在一个单一的跨平台的磁盘文件。
  • SQLite 是非常小的,是轻量级的,完全配置时小于 400KiB,省略可选功能配置时小于250KiB。
  • SQLite 是自给自足的,这意味着不需要任何外部的依赖。
  • SQLite 事务是完全兼容 ACID 的,允许从多个进程或线程安全访问。
  • SQLite 支持 SQL92(SQL2)标准的大多数查询语言的功能。
  • SQLite 使用 ANSI-C 编写的,并提供了简单和易于使用的 API。
  • SQLite 可在 UNIX(Linux, Mac OS-X, Android, iOS)和 Windows(Win32, WinCE, WinRT)中运行。

SQLite3 C/C++ API 介绍

        C/C++ API 是 SQLite3 数据库的一个客户端, 提供一种用 C/C++操作数据库的方法。下面我们介绍一下常见的几个接口:

sqlite3 操作流程:
0. 查看当前数据库在编译阶段是否启动了线程安全
         int sqlite3_threadsafe(); 0-未启用; 1-启用
         需要注意的是 sqlite3 是有三种安全等级的:

  1. 非线程安全模式
  2. 线程安全模式(不同的连接在不同的线程/进程间是安全的,即一个句柄不能用于多线程间)
  3.  串行化模式(可以在不同的线程/进程间使用同一个句柄)

1. 创建/打开数据库文件,并返回操作句柄
         int sqlite3_open(const char *filename, sqlite3 **ppDb) 成功返回SQLITE_OK
 //若在编译阶段启动了线程安全,则在程序运行阶段可以通过参数选择线程安全等级
         int sqlite3_open_v2(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs );

flag: 

  1.  SQLITE_OPEN_READWRITE -- 以可读可写方式打开数据库文件
  2.  SQLITE_OPEN_CREATE -- 不存在数据库文件则创建
  3.  SQLITE_OPEN_NOMUTEX--多线程模式,只要不同的线程使用不同的连接即可保证线程安全
  4.  SQLITE_OPEN_FULLMUTEX--串行化模式

 返回:SQLITE_OK 表示成功
2. 执行语句
         int sqlite3_exec(sqlite3*, char *sql, int (*callback)(void*,int,char**,char**),  void* arg, char **err)   返回:SQLITE_OK 表示成功

  1. sqlite3*:数据库文件句柄。
  2. char *sql:sql语句。
  3. int (*callback)(void*,int,char**,char**):对执行结果的回调函数。
  4. void* arg:给回调函数的第一个参数,常用于保存处理结果。
  5. char **err:错误信息。

        int (*callback)(void*,int,char**,char**)

  1.  void* : 是设置的在回调时传入的 arg 参数。
  2.  int:一行中数据的列数。
  3.  char**:存储一行数据的字符指针数组。
  4.  char**:每一列的字段名称。

         对于每一行结果都会执行这个回调函数,这个回调函数有个 int 返回值,成功处理的情况下必须返回 0,返回非 0会触发 ABORT 退出程序
3. 销毁句柄
         int sqlite3_close(sqlite3* db); 成功返回 SQLITE_OK
         int sqlite3_close_v2(sqlite3*); 推荐使用--无论如何都会返回SQLITE_OK
        获取错误信息
         const char *sqlite3_errmsg(sqlite3* db);

SQLite3 C/C++ API 使用

        下面我们将这几个接口封装成一个类,快速上手这几个接口

// 封装一个sqlitehelper类
#pragma once#include <sqlite3.h>
#include <iostream>
#include <string>class SqliteHelper
{
public:typedef int (*sqliteCallback)(void*, int, char**, char**);SqliteHelper(const std::string &dbfile):_dbfile(dbfile), _handler(nullptr) {}bool open(int safe_level = SQLITE_OPEN_FULLMUTEX){int ret = sqlite3_open_v2(_dbfile.c_str(), &_handler, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | safe_level, nullptr);if (ret != SQLITE_OK){std::cerr << "打开/创建数据库失败: " << sqlite3_errmsg(_handler) << std::endl;return false;}return true;}bool exec(const std::string &sql, sqliteCallback callback, void *arg){int ret = sqlite3_exec(_handler, sql.c_str(), callback, arg, nullptr);if (ret != SQLITE_OK){std::cerr << sql << std::endl;std::cerr << "执行语句失败: " << sqlite3_errmsg(_handler) << std::endl;return false;}return true;}void close(){if(_handler)sqlite3_close_v2(_handler);}
private:std::string _dbfile;sqlite3 *_handler;
};

测试程序:

#include "sqlite.hpp"
#include <cassert>
#include <vector>int select_stu_callback(void *arg, int col_count, char **result, char **fields_name)
{std::vector<std::string> *names = (std::vector<std::string>*)arg;names->push_back(result[0]);return 0;
}int main()
{SqliteHelper helper("./test.db");// 创建/打开库文件assert(helper.open());// 创建表const char *ct = "create table if not exists student(sn int primary key, name varchar(32), age int);";assert(helper.exec(ct, nullptr, nullptr));// 新增数据const char *insert_sql = "insert into student values(1, '小明', 18), (2, '小刚', 19), (3, '小红', 18);";assert(helper.exec(insert_sql, nullptr, nullptr));const char *select_sql = "select name from student;";std::vector<std::string> names;assert(helper.exec(select_sql, select_stu_callback, &names));for (auto &name : names){std::cout << name << std::endl;}// 关闭数据库helper.close();return 0;
}

GTest

GTest 是什么

        GTest 是一个跨平台的 C++单元测试框架,由 google 公司发布。gtest 是为了在不同平台上为编写 C++单元测试而生成的。它提供了丰富的断言、致命和非致命判断、参数化等等。

GTest 使用

TEST 宏

TEST(test_case_name, test_name)
TEST_F(test_fixture,test_name)
  • TEST:主要用来创建一个简单测试, 它定义了一个测试函数, 在这个函数中可以使用任何 C++代码并且使用框架提供的断言进行检查。
  • TEST_F:主要用来进行多样测试,适用于多个测试场景如果需要相同的数据配置的情况, 即相同的数据测不同的行为。

断言

GTest 中的断言的宏可以分为两类:

  1. ASSERT_系列:如果当前点检测失败则退出当前函数。
  2. EXPECT_系列:如果当前点检测失败则继续往下执行。

下面是经常使用的断言介绍:

// bool 值检查
ASSERT_TRUE(参数),期待结果是 true
ASSERT_FALSE(参数),期待结果是 false
//数值型数据检查
ASSERT_EQ(参数 1,参数 2),传入的是需要比较的两个数 equal
ASSERT_NE(参数 1,参数 2),not equal,不等于才返回 true
ASSERT_LT(参数 1,参数 2),less than,小于才返回 true
ASSERT_GT(参数 1,参数 2),greater than,大于才返回 true
ASSERT_LE(参数 1,参数 2),less equal,小于等于才返回 true
ASSERT_GE(参数 1,参数 2),greater equal,大于等于才返回 true

下面我们做一个测试:

#include <iostream>
#include <gtest/gtest.h>// 断言宏的使用 ASSERT_ 断言失败则退出   EXPECT_断言失败继续运行   必须在单元测试宏函数中使用TEST(test, great_than)
{int age = 20;ASSERT_GT(age, 18);printf("OK\n");
}int main(int argc, char *argv[])
{testing::InitGoogleTest(&argc, argv);return RUN_ALL_TESTS();    
}

运行结果:

[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from test
[ RUN      ] test.great_than
OK
[       OK ] test.great_than (0 ms)
[----------] 1 test from test (0 ms total)[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.

事件机制

        GTest 中的事件机制是指在测试前和测试后提供给用户自行添加操作的机制,而且该机制也可以让同一测试套件下的测试用例共享数据。GTest 框架中事件的结构层次:

  1.  测试程序:一个测试程序只有一个 main 函数,也可以说是一个可执行程序是一个测试程序。该级别的事件机制是在程序的开始和结束执行。
  2. 测试套件:代表一个测试用例的集合体,该级别的事件机制是在整体的测试案例开始和结束执行。
  3. 测试用例:该级别的事件机制是在每个测试用例开始和结束都执行。

        事件机制的最大好处就是能够为我们各个测试用例提前准备好测试环境,并在测试完毕后用于销毁环境,这样有个好处就是如果我们有一端代码需要进行多种不同方法的测试,则可以通过测试机制在每个测试用例进行之前初始化测试环境和数据,并在测试完毕后清理测试造成的影响。

 GTest 提供了三种常见的的事件:

全局事件

        针对整个测试程序。实现全局的事件机制,需要创建一个自己的类,然后继承 testing::Environment 类,然后分别实现成员函数 SetUp 和 TearDown,同时在 main 函数内进行调用 testing::AddGlobalTestEnvironment(new MyEnvironment);函数添加全局的事件机制。

#include <iostream>
#include <gtest/gtest.h>
#include <unordered_map>
#include <string>class MyEnvironment : public testing::Environment
{
public:virtual void SetUp() override{std::cout << "单元测试环境初始化" << std::endl;}virtual void TearDown() override{std::cout << "单元测试环境清理" << std::endl;}
};TEST(MyEnvironment, test1)
{std::cout << "单元测试1" << std::endl;
}TEST(MyEnvironment, test2)
{std::cout << "单元测试2" << std::endl;
}std::unordered_map<std::string, std::string> mymap;
class MyMapTest : public testing::Environment
{
public:virtual void SetUp() override{std::cout << "单元测试环境初始化" << std::endl;mymap.insert(std::make_pair("hello", "你好"));mymap.insert(std::make_pair("bye", "再见"));}virtual void TearDown() override{std::cout << "单元测试环境清理" << std::endl;mymap.clear();}
};TEST(MyMapTest, test1)
{ASSERT_EQ(mymap.size(), 2);mymap.erase("hello");
}TEST(MyMapTest, test2)
{ASSERT_EQ(mymap.size(), 2);
}int main(int argc, char *argv[])
{testing::AddGlobalTestEnvironment(new MyEnvironment);testing::AddGlobalTestEnvironment(new MyMapTest);testing::InitGoogleTest(&argc, argv);return RUN_ALL_TESTS();
}

运行结果:

[==========] Running 4 tests from 2 test suites.
[----------] Global test environment set-up.
单元测试环境初始化
单元测试环境初始化
[----------] 2 tests from MyEnvironment
[ RUN      ] MyEnvironment.test1
单元测试1
[       OK ] MyEnvironment.test1 (0 ms)
[ RUN      ] MyEnvironment.test2
单元测试2
[       OK ] MyEnvironment.test2 (0 ms)
[----------] 2 tests from MyEnvironment (0 ms total)[----------] 2 tests from MyMapTest
[ RUN      ] MyMapTest.test1
[       OK ] MyMapTest.test1 (0 ms)
[ RUN      ] MyMapTest.test2
global.cc:58: Failure
Expected equality of these values:mymap.size()Which is: 12
[  FAILED  ] MyMapTest.test2 (0 ms)
[----------] 2 tests from MyMapTest (0 ms total)[----------] Global test environment tear-down
单元测试环境清理
单元测试环境清理
[==========] 4 tests from 2 test suites ran. (0 ms total)
[  PASSED  ] 3 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] MyMapTest.test21 FAILED TEST
TestSuite 事件

        针对一个个测试套件。测试套件的事件机制我们同样需要去创建一个类,继承自testing::Test,实现两个静态函数 SetUpTestCase 和TearDownTestCase,测试套件的事件机制不需要像全局事件机制一样在 main 注册,而是需要将我们平时使用的 TEST 宏改为 TEST_F 宏。

  •  SetUpTestCase() 函数是在测试套件第一个测试用例开始前执行。
  • TearDownTestCase() 函数是在测试套件最后一个测试用例结束后执行。
  • 需要注意 TEST_F 的第一个参数是我们创建的类名,也就是当前测试套件的名称,这样在 TEST_F 宏的测试套件中就可以访问类中的成员了。
#include <iostream>
#include <gtest/gtest.h>
#include <unordered_map>
#include <string>class MyTest : public testing::Test
{
public:static void SetUpTestCase(){std::cout << "所有单元测试前初始化环境\n";}static void TearDownTestCase(){std::cout << "所有单元测试完毕后清理环境\n";}std::unordered_map<std::string, std::string> _mymap;
};TEST_F(MyTest, insert_test)
{_mymap.insert(std::make_pair("good", "好"));
}TEST_F(MyTest, size_test)
{ASSERT_EQ(_mymap.size(), 1);
}int main(int argc, char *argv[])
{testing::InitGoogleTest(&argc, argv);return RUN_ALL_TESTS();
}

 运行结果:

[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from MyTest
所有单元测试前初始化环境
[ RUN      ] MyTest.insert_test
[       OK ] MyTest.insert_test (0 ms)
[ RUN      ] MyTest.size_test
suit.cc:40: Failure
Expected equality of these values:_mymap.size()Which is: 01
[  FAILED  ] MyTest.size_test (0 ms)
所有单元测试完毕后清理环境
[----------] 2 tests from MyTest (0 ms total)[----------] Global test environment tear-down
[==========] 2 tests from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] MyTest.size_test1 FAILED TEST

        能够看到在上例中,有一个好处,就是将数据与测试结合到同一个测试环境类中了,这样与外界的耦合度更低,代码也更清晰。
        但是同样的,我们发现在两个测试用例中第二个测试用例失败了,这是为什么呢?这就涉及到了 TestCase 事件的机制。
        • TestCase 事件: 针对一个个测试用例。测试用例的事件机制的创建和测试套件的基本一样,不同地方在于测试用例实现的两个函数分别是 SetUp 和 TearDown, 这两个函数也不是静态函数

        ○ SetUp()函数是在一个测试用例的开始前执行

        ○ TearDown()函数是在一个测试用例的结束后执行
        也就是说,在 TestSuite/TestCase 事件中,每个测试用例,虽然它们同用同一个事件环境类,可以访问其中的资源,但是本质上每个测试用例的环境都是独立的,这样我们就不用担心不同的测试用例之间会有数据上的影响了,保证所有的测试用例都使用相同的测试环境进行测试。

 

#include <iostream>
#include <gtest/gtest.h>
#include <unordered_map>
#include <string>class MyTest : public testing::Test
{
public:static void SetUpTestCase(){std::cout << "所有单元测试前初始化环境\n";}static void TearDownTestCase(){std::cout << "所有单元测试完毕后清理环境\n";}void SetUp() override{_mymap.insert(std::make_pair("hello", "你好"));_mymap.insert(std::make_pair("bye", "再见"));}void TearDown() override{_mymap.clear();}std::unordered_map<std::string, std::string> _mymap;
};TEST_F(MyTest, insert_test)
{_mymap.insert(std::make_pair("good", "好"));
}TEST_F(MyTest, size_test)
{ASSERT_EQ(_mymap.size(), 2);
}int main(int argc, char *argv[])
{testing::InitGoogleTest(&argc, argv);return RUN_ALL_TESTS();
}

运行结果:

[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from MyTest
所有单元测试前初始化环境
[ RUN      ] MyTest.insert_test
[       OK ] MyTest.insert_test (0 ms)
[ RUN      ] MyTest.size_test
[       OK ] MyTest.size_test (0 ms)
所有单元测试完毕后清理环境
[----------] 2 tests from MyTest (0 ms total)[----------] Global test environment tear-down
[==========] 2 tests from 1 test suite ran. (0 ms total)
[  PASSED  ] 2 tests.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/914783.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/914783.shtml
英文地址,请注明出处:http://en.pswp.cn/news/914783.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Web3.0 学习方案

Web3.0 学习方案 一、学习方案 &#xff08;一&#xff09;入门阶段 1. 了解 Web3.0 基础概念 学习内容&#xff1a; Web3.0 的起源、愿景、与 Web2.0 的区别区块链的基本概念&#xff1a;分布式账本、哈希、公钥/私钥、共识机制&#xff08;PoW、PoS、DPoS、PBFT 等&#xff0…

springboot3.5.3依赖学习

springboot3.5.3依赖学习 ​ Spring Boot BOM&#xff08;spring-boot-dependencies&#xff09;是 Spring 官方维护的超级依赖清单&#xff0c;覆盖了 Spring 生态中几乎所有核心库、常用工具库及第三方依赖。其作用是统一管理这些依赖的版本&#xff0c;确保它们相互兼容。以…

制作一款打飞机游戏80:道具碰撞

目前我们仍然无法拾取这些物品&#xff0c;它们只是简单地掉落在地上。因此&#xff0c;我们需要对这些功能进行增强。目标‌弹射物品‌&#xff1a;当物品生成时&#xff0c;我们希望它们能以一定的力量弹出&#xff0c;而不是无力地掉落。‌添加不同类型的物品‌&#xff1a;…

Python编程基础(六)| 用户输入和while循环

引言 很久没有写 Python 了&#xff0c;有一点生疏。这是学习《Python 编程&#xff1a;从入门到实践&#xff08;第3版&#xff09;》的课后练习记录&#xff0c;主要目的是快速回顾基础知识。 练习1&#xff1a;汽车租赁 编写一个程序&#xff0c;询问用户要租什么样的汽车&a…

【华为机试】HJ52 计算字符串的编辑距离

文章目录HJ52 计算字符串的编辑距离描述输入描述输出描述示例1HJ52 计算字符串的编辑距离描述输入描述输出描述示例1解题思路算法分析动态规划状态转移状态转移方程算法流程图DP表格示例三种操作详解代码实现思路时间复杂度分析关键优化技巧实际应用场景算法扩展面试考点完整题…

15.手动实现BatchNorm(BN)

15.1 BatchNorm操作手动实现 import torch from torch import nndef batch_norm(X,gamma,beta,moving_mean,moving_var,eps,momentum):if not torch.is_grad_enabled():#这个是推理模式X_hat(X-moving_mean)/torch.sqrt(moving_vareps)else:assert len(X.shape) in (2,4)if le…

【项目实践】SMBMS(Javaweb版)汇总版

文章目录前期准备工作数据库、数据表创建web项目创建项目文件目录配置Tomcat&#xff0c;导入依赖建立实体类编写基础公共方法类导入基础资源登录功能登录页面持久层dao层的用户登录及接口实现dao层接口实现所需的方法业务层sevice层的接口的实现接口实现相关的业务逻辑编写ser…

隐藏源IP的核心方案与高防实践

一、源IP暴露的风险 直接DDoS攻击&#xff1a;2025年Q2全球DDoS攻击峰值达3.8Tbps&#xff08;来源&#xff1a;Cloudflare报告&#xff09;漏洞利用&#xff1a;暴露的SSH端口平均每天遭受12,000暴力破解尝试数据泄露&#xff1a;直接连接数据库风险提升300% 二、4种有效隐藏方…

深度学习图像分类数据集—五种电器识别分类

该数据集为图像分类数据集&#xff0c;适用于ResNet、VGG等卷积神经网络&#xff0c;SENet、CBAM等注意力机制相关算法&#xff0c;Vision Transformer等Transformer相关算法。 数据集信息介绍&#xff1a;五种电器识别分类&#xff1a;[notebook, phone, powerbank, tablet, w…

Windows11家庭版配置frigate 嵌入自研算法(基于Yolov8)-【2】

使用 YOLOv8 的 results.xyxy 结构&#xff0c;下面是一个完整的 MQTT 推送脚本&#xff0c;用于把识别到的目标&#xff08;比如突涌水、水渍、障碍物等&#xff09;发送到 Frigate 的 MQTT 接口。✅ 前提假设 YOLOv8 推理代码已经运行并生成 results.xyxy。每一行是 [x1, y1,…

安装llama-factory报错 error: subprocess-exited-with-error

报错信息如下 Using cached https://mirrors.aliyun.com/pypi/packages/17/89/940a509ee7e9449f0c877fa984b37b7cc485546035cc67bbc353f2ac20f3/av-15.0.0.tar.gz (3.8 MB)Preparing metadata (pyproject.toml) ... errorerror: subprocess-exited-with-error Preparing metad…

QT 多线程 管理串口

记录一下自己使用多线程进行串口管理和数据读取的过程。如果有问题的话可以发消息给我。背景在使用QT制作一个串口数据读取处理的小软件的时候&#xff0c;发现了存在界面卡顿的情况&#xff0c;感觉性能太低&#xff0c;于是考虑把串口数据的读取和处理都放到子线程的缓冲区中…

在虚拟环境中复现论文(环境配置)

前提&#xff1a;已经下载condawinR&#xff0c;输入cmd进入命令行conda create -n PPT python3.8.3 pytorch1.7.0conda create -n PPT(虚拟环境名) python3.8.3(包名) pytorch1.7.0(包名)安装完毕&#xff0c;激活虚拟环境&#xff1a;conda activate PPT根据论文readme要求安…

Flutter Web 的发展历程:Dart、Flutter 与 WasmGC

Flutter Web 应该是 Flutter 开发者里最不“受宠”的平台了&#xff0c;但是其实 Flutter 和 Dart 团队对于 Web 的投入一直没有减少&#xff0c;这也和 Flutter 还有 Dart 的"出生"有关系&#xff0c;今天就借着 Dart 团队的 mer Ağacan 和 Martin Kustermann 在油…

c#方法关键字,ref、out、int

在 C# 中&#xff0c;ref、out 和 in 是用于方法参数传递的关键字&#xff0c;它们控制参数如何在方法和调用者之间传递数据。以下是对这三个关键字的详细分析&#xff1a;1. ref 关键字&#xff08;引用传递&#xff09;作用允许方法修改调用者的变量&#xff1a;通过引用传递…

设计模式—初识设计模式

1.设计模式经典面试题分析几个常见的设计模式对应的面试题。1.1原型设计模式1.使用UML类图画出原型模式核心角色&#xff08;意思就是使用会考察使用UML画出设计模式中关键角色和关系图等&#xff09;2.原型设计模式的深拷贝和浅拷贝是什么&#xff0c;写出深拷贝的两种方式的源…

深度学习-参数初始化、损失函数

A、参数初始化参数初始化对模型的训练速度、收敛性以及最终的性能产生重要影响。它可以尽量避免梯度消失和梯度爆炸的情况。一、固定值初始化在神经网络训练开始时&#xff0c;将权重或偏置初始化为常数。但这种方法在实际操作中并不常见。1.1全零初始化将所有的权重参数初始化…

格密码--Ring-SIS和Ring-LWE

1. 多项式环&#xff08;Polynomial Rings&#xff09; 设 f∈Z[x]f \in \mathbb{Z}[x]f∈Z[x] 是首一多项式&#xff08;最高次项系数为1&#xff09; 则环 RZ[x]/(f)R \mathbb{Z}[x]/(f)RZ[x]/(f) 元素为&#xff1a;所有次数 <deg⁡(f)< \deg(f)<deg(f) 的多项式…

前端工作需要和哪些人打交道?

前端工作中需要协作的角色及协作要点 前端工作中需要协作的角色及协作要点 前端开发处于产品实现的 “中间环节”,既要将设计方案转化为可交互的界面,又要与后端对接数据,还需配合团队推进项目进度。日常工作中,需要频繁对接的角色包括以下几类,每类协作都有其核心目标和…

万字长文解析 OneCode3.0 AI创新设计

一、研究概述与背景 1.1 研究背景与意义 在 AI 技术重塑软件开发的浪潮中&#xff0c;低代码平台正经历从 “可视化编程” 到 “意图驱动开发” 的根本性转变。这种变革不仅提升了开发效率&#xff0c;更重新定义了人与系统的交互方式。作为国内领先的低代码平台&#xff0c;On…