Genluo’s Blog

👋 欢迎来到我的个人博客!

  • 这个博客会分享我的个人经历、技术文章和有趣的见解

Spec Coding 调研

什么是spec coding Spec coding 是一种通过 AI 生成代码和方案的开发方式,它通过先定义"做什么",再决定"怎么做"的方式,帮助开发者聚焦在业务逻辑和架构设计上,而将重复性的编码工作交给 AI 完成。 对比 vibe coding 不同 从研发周期上看,拆解为不同的阶段或者角色,每个阶段都有对应的输入和输出要求 每个角色阶段之间没有状态,不进行上下文持久化和传递 每个阶段都有对应的规范文档,并按照特定的名称持久化在特定的工程目录中 每个阶段记录过程,人工都可以被动或主动进行澄清 文档不是静态的,需要动态变化,不断对齐现实,保持和现实的一致性 优点 通过文档建立持久化的知识库,每个独立任务保持无状态,避免上下文混乱和信息丢失。 文档代表事实真相,与代码保持一致性。文档不是静态的,而是动态变化,不断对齐现实,确保文档和实际代码的同步。 开发者可以专注于"做什么"(业务逻辑和架构设计),而将重复性的编码工作交给 AI 完成,提高开发效率。 通过明确的规范定义,AI 能够准确理解开发意图,生成高质量、可预测的代码,大大减少开发时间和沟通成本。 从研发周期上拆解为不同的阶段或角色(constitution → specify → plan → tasks → implement),每个阶段都有对应的输入和输出要求,流程清晰可控。 每个阶段都记录过程,人工可以被动或主动进行澄清和调整,保持对开发过程的控制。 总结:让 AI 辅助开发变得更加可控、可靠和高效,彻底解决了 AI 编程助手"不可控"的痛点。 spec-kit https://github.com/github/spec-kit spec-kit 介绍 spec-kit 是由 GitHub 开发的规范驱动开发(Spec-Driven Development, SDD)工具,旨在帮助开发团队专注于产品场景而非重复编码,从而构建高质量的软件。它通过先定义"做什么",再决定"怎么做"的方式,让 AI 更好地理解和执行开发任务。 spec-kit 工作流程 graph TD Start([开始项目]) --> Constitution[1. Constitution<br/>定义项目宪法] Constitution --> |核心原则<br/>技术约束<br/>协作规则| Specify[2. Specify<br/>创建项目规范] Specify --> |功能描述<br/>用户场景<br/>业务规则| Clarify{3. Clarify<br/>需要澄清?} Clarify --> |是| ClarifyProcess[澄清模糊点<br/>解决不确定性] ClarifyProcess --> Plan Clarify --> |否| Plan[4. Plan<br/>制定技术方案] Plan --> |架构设计<br/>技术选型<br/>数据模型| Tasks[5. Tasks<br/>任务分解] Tasks --> |可执行任务列表| Analyze{6. Analyze<br/>需要分析?} Analyze --> |是| AnalyzeProcess[一致性分析<br/>验证完整性] AnalyzeProcess --> Implement Analyze --> |否| Implement[7. Implement<br/>任务实施] Implement --> SelectTask[选择任务] SelectTask --> Understand[理解需求] Understand --> WriteCode[编写代码] WriteCode --> WriteTest[编写测试] WriteTest --> CodeReview[代码审查] CodeReview --> Acceptance[验收确认] Acceptance --> MoreTasks{还有任务?} MoreTasks --> |是| SelectTask MoreTasks --> |否| End([项目完成]) style Constitution fill:#e1f5ff style Specify fill:#e1f5ff style Clarify fill:#fff4e1 style Plan fill:#e1f5ff style Tasks fill:#e1f5ff style Analyze fill:#fff4e1 style Implement fill:#e8f5e9 style Start fill:#f3e5f5 style End fill:#f3e5f5 classDef optional fill:#fff4e1,stroke:#ff9800,stroke-width:2px,stroke-dasharray: 5 5 class Clarify,ClarifyProcess,Analyze,AnalyzeProcess optional spec-kit 的开发流程分为五个主要阶段: ...

October 30, 2025 · 5 min · 1053 words

Agent 技术调研

Agent 内容 整个 Agent 相关技术拆为两个大的部分进行介绍,一个是对应的工作流,一个是对应的 Agent 开发相关技术 工作流介绍 顺序执行型:ReAct、Plan & Execute、流水式、提示链 协作优化型:自协商、评估优化、多智能体协作、分层规划 动态编排型:动态编排、自演化、混合模式、路由、并行化、协调者-工作者 顺序执行型 1. ReAct 通过推理(Reasoning)和行动(Acting)交替循环的方式,让Agent在思考和执行工具之间迭代,直到完成任务。 stateDiagram-v2 [*] --> 接收任务 接收任务 --> 推理思考 推理思考 --> 判断是否需要行动 判断是否需要行动 --> 执行工具: 需要行动 判断是否需要行动 --> 生成答案: 无需行动 执行工具 --> 观察结果 观察结果 --> 推理思考 生成答案 --> [*] 2. Plan & Execute 先制定完整的执行计划,然后按照计划逐步执行各个步骤,适合复杂任务的分解与执行。 stateDiagram-v2 [*] --> 接收任务 接收任务 --> 规划阶段 规划阶段 --> 生成执行计划 生成执行计划 --> 执行步骤1 执行步骤1 --> 执行步骤2 执行步骤2 --> 执行步骤N 执行步骤N --> 检查完成状态 检查完成状态 --> 返回结果: 已完成 检查完成状态 --> 重新规划: 需调整 重新规划 --> 生成执行计划 返回结果 --> [*] 3. 流水式 将任务按固定顺序分配到多个专门的Agent,每个Agent处理特定环节后传递给下一个,形成处理流水线。 ...

October 28, 2025 · 7 min · 1370 words

领域驱动设计

契机 最近因为一些契机看了下互动小游戏的服务端,深入了解了下现在互动游戏服务端的架构,同时也尝试在这个架构的基础上使用 AI 进行一些游戏业务功能开发,其中印象最深的服务端的一个称之为基座的架构设计,这个基座架构深度使用 DDD 领域设计思想进行抽象实现,在游戏业务非常灵活,复用性非常高,所以想看下在NodeJS 中针对 DDD领域驱动设计是否有一定的实践。下面主要分为两个部分,一个是为什么是DDD?另一个 NodeJS中一些实践 DDD 什么是领域驱动设计(domain driving design) 领域驱动设计是一种软件设计方法,用于表示和组织特定领域中的知识和业务逻辑。它主要通过创建抽象的模型对象来模拟现实世界的实体及其关系,帮助开发人员理解和实现复杂系统的业务逻辑。在领域驱动设计中,通常会包含以下几个关键概念: 实体(Entity):具有唯一标识的对象,通常表示业务中的一个独立的概念或对象。例如,在一个订单系统中,订单和客户可以被视为实体。 值对象(Value Object):没有唯一标识的对象,通常用于描述某个实体的属性或细节。它们是不可变的,两个值对象如果具有相同的属性值,则认为是相等的。例如,一个地址可以作为一个值对象。 聚合(Aggregate):一组相关的对象(实体和值对象)的集合,它们被视为一个单元进行数据修改。聚合有一个根实体(Aggregate Root),通过根实体来管理聚合的生命周期。 领域服务(Domain Service):封装领域逻辑的操作,这些操作不属于任何一个实体或值对象。它们通常用于表示跨越多个实体或值对象的业务逻辑。 仓储(Repository):提供访问持久化存储中对象的方法,通常用于获取和保存聚合根。 什么是聚合根 指的是一个聚合中具有唯一标识的核心实体,该实体负责控制整个聚合的生命周期和一致性。 控制访问:聚合根是聚合内的唯一入口点,外部对象只能通过聚合根来访问或操作聚合中的其它对象。这有助于保持聚合内部的完整性和一致性。 管理生命周期:聚合根负责管理聚合内所有对象的生命周期,包括创建、更新和删除操作。通过聚合根,可以确保对聚合中数据的任何修改都是合法和一致的。 一致性边界:聚合定义了一个一致性边界,其中的所有对象在事务中应该保持一致。因此,聚合根通过确保在其范围内的操作都是一致的,来维持这种边界。 唯一性:每个聚合都有一个唯一的聚合根。通常,聚合根具有唯一标识符,用来标识和访问该聚合。 持久化管理:通过仓储(Repository)模式,聚合根通常是持久化操作(如保存和检索)的主要对象。这意味着仓储通常只直接处理聚合根,而不是聚合内的其它对象。 领域驱动设计优缺点 领域驱动设计(Domain-Driven Design, DDD)是一种软件设计方法,旨在通过紧密结合业务需求和技术实现来构建复杂软件系统。以下是领域驱动设计的一些优缺点: 优点 更好地理解业务: DDD强调与领域专家的密切合作,使开发团队对业务需求有更深入的理解。这有助于创建更符合业务需求的系统。 清晰的模型: 通过使用统一语言和领域模型,所有团队成员(包括技术人员和非技术人员)都可以在同一语境下沟通,从而减少误解。 灵活性和可维护性: DDD鼓励模块化设计,如界限上下文(Bounded Context)和聚合(Aggregate),这些设计有助于简化系统的维护和扩展。 关注核心领域: 通过识别和聚焦于核心领域,DDD帮助团队将资源集中在对业务最重要的部分,从而提高竞争力。 支持复杂系统开发: DDD为处理复杂领域逻辑提供了有力的方法和工具,可以有效地管理复杂性。 缺点 学习曲线陡峭: 对许多开发人员和组织来说,DDD的概念和技术术语可能较为陌生,初始学习和实施成本较高。 时间和资源投入大: 由于需要深度的领域分析和持续的团队协作,DDD可能比传统方法花费更多时间和资源。 不适合所有项目: 对于简单或小型项目,DDD可能过于复杂和冗余,投入的成本和收益不成比例。 需求稳定性要求高: DDD更适合于需求相对稳定且对业务逻辑要求高的项目。对于需求频繁变化的项目,可能需要经常重构。 对团队协作要求高: 成功实施DDD需要团队成员之间良好的沟通和协作,这对团队的组织文化和沟通能力提出了较高要求。 为什么需要领域模型 在传统的软件开发中,我们常常遇到以下问题: 1. 贫血模型的困境 传统的开发方式往往采用"贫血模型"(Anemic Domain Model),即: 数据对象只包含字段和简单的 getter/setter,没有任何业务逻辑 所有业务逻辑集中在 Service 层,形成庞大的服务类 数据和行为分离,导致代码难以理解和维护 2. 业务逻辑散乱 缺乏统一的业务规则管理:同样的业务逻辑可能在多个地方重复实现 难以保证一致性:订单创建、修改、取消等操作中的业务规则可能不一致 维护成本高:修改一个业务规则需要在多个地方查找和修改 3. 技术与业务脱节 代码难以反映业务意图:开发人员看到的是表、字段、SQL,而不是订单、支付、发货等业务概念 与领域专家沟通困难:技术术语和业务术语无法对应,容易产生理解偏差 需求变更代价大:业务调整时,需要从底层数据结构开始重新设计 领域模型如何解决这些问题 领域模型通过以下方式解决上述问题: ...

September 1, 2025 · 15 min · 3020 words

Clangformat

# .clang-format BasedOnStyle: LLVM # 可选:LLVM, Google, Chromium, Mozilla, WebKit IndentWidth: 4 TabWidth: 4 UseTab: Never # 可选:Always, Never, ForIndentation ColumnLimit: 100 # 每行最大字符数,设为 0 表示不限制 BreakBeforeBraces: Allman # 可选:Attach, Linux, Stroustrup, Allman, WebKit AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false AllowShortFunctionsOnASingleLine: Inline SpaceAfterCStyleCast: true SpacesInParentheses: false SpaceBeforeParens: ControlStatements # 控制语句前加空格,如 `if (...)` PointerAlignment: Left # 可选:Left, Right, Middle SortIncludes: true IncludeBlocks: Regroup # 对齐参数 AlignAfterOpenBracket: Align AlignConsecutiveAssignments: true AlignConsecutiveDeclarations: true AlignOperands: true # 命名空间格式 NamespaceIndentation: All # 可选:None, Inner, All # 结构体/类格式 AccessModifierOffset: -4 # public/private/protected 的缩进 # 注释格式 IndentWrappedFunctionNames: true

August 28, 2025 · 1 min · 89 words

Readerwriterqueue 源代码阅读

ReaderWriterQueue 是一个高性能的 C++无锁队列实现,专为单生产者-单消费者(SPSC)场景设计。 无锁设计:完全无锁实现,enqueue 和 dequeue 操作都是 O(1)时间复杂度 高性能:在 x86 架构上,内存屏障编译为无操作指令,性能极佳 C++11 兼容:支持移动语义,减少不必要的拷贝 泛型模板:使用模版支持任意类型的元素,类似 std::queue 内存高效:预分配连续内存块,提供 try_enqueue 保证不分配内存 阻塞版本:提供 BlockingReaderWriterQueue 支持 wait_dequeue 操作 适用于需要在两个线程间高效传递数据的场景,如生产者-消费者模式、异步任务处理等。仅需包含头文件即可使用,无需额外依赖 核心问题 1. 整体思路 代码中主要包含两个部分,一个是队列链表,这个链表中存储很多的 block,每个 block 内部实现又是一个链表,这个链表,有读写两个指针,可以存放多个线程共享的元素 2. 内存中结构 存储的数据分为两部分,一部分是 Block 中属性数据+内存对其 auto size = sizeof(Block) + std::alignment_of<Block>::value - 1; 另一部分则是需要存储的具体数据: size += sizeof(T) * capacity + std::alignment_of<T>::value - 1; 针对申请的内容,实际分配内存进行指针对齐 auto newBlockRaw = static_cast<char *>(std::malloc(size)); auto newBlockAligned = align_for<Block>(newBlockRaw); auto newBlockData = align_for<T>(newBlockAligned + sizeof(Block)); template <typename U> static AE_FORCEINLINE char *align_for(char *ptr) AE_NO_TSAN { const std::size_t alignment = std::alignment_of<U>::value; return ptr + (alignment - (reinterpret_cast<std::uintptr_t>(ptr) % alignment)) % alignment; } 为什么这个过程中需要内存对其,可以看下下面的问题部分,这样对齐之后可以保证: ...

August 11, 2025 · 4 min · 816 words

Vscode+clangd

基本配置 一般来说,vscode 中开发 c++ 项目使用的都是微软提供的插件,但是这个插件不是很好用,推荐使用 clangd ,相比于微软的插件来说,错误的提示更好点,同时速度要快很多 基础配置 如果使用 cmake 进行开发,可以添加编译参数 -DCMAKE_EXPORT_COMPILE_COMMANDS=ON 来生成 clangd 需要的 compile_commands.json 来索引整个项目的源文件 通过 cmake 进行配置生成,包含 bear 工具介绍 generates a compilation database for clang tooling. 如果使用的是其他的构建系统,没有使用 cmake 可以使用这个工具,生成对应的 compile_commands.json bear -- make 重启服务之后,可以正常进行跳转

August 8, 2025 · 1 min · 37 words

如何写出高质量的 Prompt

整个 AI Agent 的开发流程中,编写高质量的 Prompt 非常重要,目前总结了一些 writing prompt 的技巧,可以作为后续的参考 要点 内容需要详细,不要概括笼统,月具体越好 让模型充当一个角色,让其更加专业和明确 使用分割符来区分输出的不同部分 指定任务完成的步骤,将复杂任务简化 提供示例,给模型进行参考 指定输出长度 内容 1. 确定角色定义 明确定义 AI 的身份和专业背景,这决定了 AI 的回答风格和专业程度。 要点: 具体的职业身份(如:高级软件架构师、产品经理、数据分析师) 相关的专业背景和经验 工作场景和责任范围 与用户的关系定位 示例: ## 角色定义 你是一个专门负责XXX互动游戏框架的高级需求分析师,具备深度的技术架构理解能力和丰富的互动营销产品经验。 2. 确定核心目标 清晰描述希望 AI 完成的主要任务和期望达到的效果。 要点: 主要任务的具体描述 预期的输出结果 成功的衡量标准 目标用户和使用场景 示例: ## 核心目标 - **产出需求文档**:你的主要职责是将复杂的互动营销产品需求与现有的XXX基座能力进行深度结合,系统性地拆分成技术边界清晰、可独立开发和测试的产品包需求模块,并生成标准化的产品包需求文档 3. 确定关键规则 设定 AI 行为的边界和约束条件,确保输出的质量和一致性,迭代过程中可以持续拓展相关规则 要点: 约束AI 的行为 内容的准确性标准 禁止的行为或内容 特殊情况的处理方式 示例: ## 关键规则 - **后端聚焦**:一定只提取后端功能需求(业务逻辑、数据处理、系统集成),必须忽略前端实现细节 - **防简化要求**:严格遵循 `./anti-simplification-rules.md` 中的防简化规则,绝对禁止简化、概述、总结原始需求内容 4. 确定执行流程 定义 AI 处理任务的具体步骤和逻辑顺序。 ...

July 28, 2025 · 2 min · 260 words

Augment 试用

最近试用了下 augment 进行一些需求开发,感觉相比 cursor 还是解决了一些问题,挺好的进行分享下 上下文机制 如何进行跨仓库开发,以前使用 cursor 是通过同时打开两个仓库进行的,但是在 augment 中,可以通过上下文机制进行。 通过这种方式可以给新的仓库添加对应的索引,然后在当前仓库的开发中进行使用 工具 另外一个比较好的点是 augment 提供了一些工具配置,可以一键进行安装使用 任务规划 提供了任务规划,可以让用户手动指定相关任务列表,并且后续能够将本次编辑的任务导出进行保存,后续可以二次进行使用 同理,针对起他通用的agent 任务,augment 也会进行任务拆分,然后逐个实现,只不过这里提供了一个窗口,可以让用户指定任务列表,这针对于用户想要自己创建固定的任务流程是非常有用的 图表展示 不知道为什么,感觉 augment 针对 mermaid 的图标进行了展示优化,看起来比较舒服,如果能够再加一个全屏展示会更好 提示词优化 可以先编写简短或不完整的提示,然后使用提示增强从代码库中添加相关的参考、结构和约定,以便在发送提示之前对其进行改进。这个非常好用

July 17, 2025 · 1 min · 29 words

StateMachine

状态机概述 状态机是一种计算模型,用于描述系统在不同状态之间的转换逻辑。它由状态(States)、事件(Events)和转换(Transitions)组成。状态机在任一时刻只能处于一个特定状态,通过触发事件使其从一个状态转换到另一个状态。 核心概念 状态(State):系统可能处于的一种情况或模式。 事件(Event):触发状态转换的信号或动作。 转换(Transition):定义从一个状态到另一个状态的规则。 回调(Callback):状态转换时执行的逻辑。 应用场景 状态机在以下场景中特别有用: 游戏开发:管理游戏角色的不同状态(站立、行走、攻击、受伤等)。 UI 交互:控制界面元素在不同状态下的行为(正常、悬停、激活、禁用)。 工作流管理:追踪业务流程的不同阶段(创建、审核、发布)。 协议实现:网络协议的状态管理(连接中、已连接、断开连接)。 动画控制:管理动画序列和转换。 基本用法 // 定义状态和事件类型 type State = 'idle' | 'running' | 'paused' | 'stopped'; type Event = 'START' | 'PAUSE' | 'RESUME' | 'STOP'; // 创建状态机实例 const sm = new StateMachine<State, Event>('idle', [ t('idle', 'START', 'running'), t('running', 'PAUSE', 'paused'), t('paused', 'RESUME', 'running'), t('running', 'STOP', 'stopped'), ]); // 触发状态转换 await sm.dispatch('START'); // idle -> running console.log(sm.getState()); // 'running' 高级特性 全局事件(ANY_STATE) 使用 ANY_STATE 符号定义可从任意状态触发的转换: // RESET 事件可从任何状态回到 idle 状态 sm.addTransitions([ t(ANY_STATE, 'RESET', 'idle', resetCallback) ]); 状态查询和预测 // 检查当前状态是否可以接收特定事件 if (sm.can('PAUSE')) { // 可以执行暂停操作 } // 获取事件触发后的下一个状态 const nextState = sm.getNextState('STOP'); // 'stopped' // 检查当前是否为终止状态(没有可用的出站转换) if (sm.isFinal()) { // 到达终止状态 } 子状态机 子状态机是一种嵌套状态机机制,允许在一个主状态内部有自己的状态转换逻辑。这对于构建复杂的分层状态行为非常有用 ...

July 8, 2025 · 3 min · 528 words