Slime异步原理(单例设计模式)5

Slime异步原理(单例设计模式)4

你又提出了一个非常好的问题,这涉及到代码的组织结构和职责划分,是衡量代码设计优劣的重要方面。

submit_generate_tasks 函数放在 GenerateState 类下,而不是作为一个独立的全局函数,主要有以下几个原因:

1. 职责单一与高内聚(Single Responsibility & High Cohesion)

GenerateState 类的核心职责是管理所有与生成过程相关的状态 。这不仅包括像 tokenizersemaphore 这样的静态资源,也包括像 pendings(待处理任务集合)和 remaining_batch_size(剩余批次大小)这样的动态状态。

  • submit_generate_tasks 函数的核心作用是什么?
    • 它接收一批样本 (samples)。
    • 为这批样本创建 asyncio.Task
    • 将这些任务添加到 self.pendings 集合中进行跟踪。
    • 更新 self.remaining_batch_size 计数。

可以看到,这个函数的操作与 GenerateState 内部的状态变量 (pendings, remaining_batch_size) 紧密相关 。将函数和它操作的数据放在一起,是"高内聚"原则的体现。这使得 GenerateState 成为一个完整、独立的组件,负责管理从任务提交到状态跟踪的整个生命周期。

反例:如果不放在类里会怎么样?

假设我们把它作为一个全局函数:

python 复制代码
# 全局函数版本
def submit_generate_tasks_global(state: GenerateState, samples: list[list[Sample]]):
    for group in samples:
        state.pendings.add(
            asyncio.create_task(...)
        )
    state.remaining_batch_size += len(samples)

# 在其他地方调用
state = GenerateState(args)
samples = data_source(...)
submit_generate_tasks_global(state, samples)

这样做虽然功能上可行,但有几个缺点:

  • 职责不清晰GenerateState 变成了纯粹的数据容器,而操作这些数据的逻辑却散落在外部,破坏了类的封装性。
  • 增加了调用复杂度 :每次调用都需要同时传递 state 对象和 samples,而作为类方法,只需要传递 samples (self 是隐式传递的)。
  • 维护困难 :如果未来 GenerateState 内部状态管理的方式发生改变(比如 pendingsset 变成了 dict),你不仅要修改 GenerateState 类,还需要去查找并修改所有像 submit_generate_tasks_global 这样直接操作其内部状态的外部函数。

2. 封装与信息隐藏(Encapsulation & Information Hiding)

通过将 submit_generate_tasks 作为 GenerateState 的一个方法,外部调用者(比如 generate_rollout_async 函数)只需要知道"如何提交任务",而不需要关心"任务是如何被跟踪和管理的"。

  • 外部视角state.submit_generate_tasks(samples) ------ 这是一个清晰的指令,意为"状态管理器,请帮我处理这批任务"。
  • 内部实现 :这个方法内部具体是把任务加到一个 set 里,还是一个 list 里,还是一个更复杂的数据结构里,对于外部调用者来说是透明的。这种信息隐藏使得代码更容易维护和重构。

如果未来我们想增加更复杂的逻辑,比如在提交任务时进行优先级排序,或者记录任务的提交时间,我们只需要修改 submit_generate_tasks 这个方法内部的实现,而所有调用它的代码都无需改动

3. 代码可读性与面向对象思想

将相关的功能组织在同一个类中,使得代码结构更清晰,更符合人类的思维习惯。当我们阅读 GenerateState 类的代码时,我们可以一目了然地看到它包含了哪些状态 (__init__),以及可以对这些状态执行哪些操作(reset, submit_generate_tasks)。

这就像一个"任务管理器"对象,它有自己的属性(任务列表、剩余任务数),也有自己的行为(提交任务、重置状态)。这比将属性和行为分散在代码各处要更容易理解。

总结

submit_generate_tasks 放在 GenerateState 类下,是遵循良好软件设计原则的体现:

原则 在此处的体现
高内聚 函数和它紧密操作的数据(pendings, remaining_batch_size)被组织在一起。
低耦合 外部代码通过一个稳定的接口与状态管理器交互,而不需要了解其内部实现细节。
封装性 状态管理的具体逻辑被隐藏在类的方法内部,保护了内部状态的完整性。
职责单一 GenerateState 作为一个整体,负责"管理生成过程的状态"这一单一职责。

所以,这个设计决策让 GenerateState 不仅仅是一个被动的数据结构,而是一个主动的、有行为的状态管理器,从而使整个系统的代码更加健壮、清晰和易于维护。

相关推荐
七月丶5 小时前
别再手动凑 PR 了:这个 AI Skill 会按仓库习惯自动建分支、拆提交、提 PR
人工智能·设计模式·程序员
刀法如飞5 小时前
从程序员到架构师:6大编程范式全解析与实践对比
设计模式·系统架构·编程范式
九狼6 小时前
Flutter + Riverpod +MVI 架构下的现代状态管理
设计模式
静水流深_沧海一粟1 天前
04 | 别再写几十个参数的构造函数了——建造者模式
设计模式
StarkCoder1 天前
从UIKit到SwiftUI的迁移感悟:数据驱动的革命
设计模式
阿星AI工作室1 天前
给openclaw龙虾造了间像素办公室!实时看它写代码、摸鱼、修bug、写日报,太可爱了吧!
前端·人工智能·设计模式
_哆啦A梦2 天前
Vibe Coding 全栈专业名词清单|设计模式·基础篇(创建型+结构型核心名词)
前端·设计模式·vibecoding
阿闽ooo5 天前
中介者模式打造多人聊天室系统
c++·设计模式·中介者模式
小米4965 天前
js设计模式 --- 工厂模式
设计模式
逆境不可逃5 天前
【从零入门23种设计模式08】结构型之组合模式(含电商业务场景)
线性代数·算法·设计模式·职场和发展·矩阵·组合模式