结对编程项目总结
https://z.gitee.cn/zgca/repos/yolo12318/Elevator
2. 时间预估
| PSP 阶段 | 阶段说明 | 预估耗时(分钟) |
|---|---|---|
| Planning | 计划 | 10 |
| · Estimate | · 估计本次任务所需时间 | 10 |
| Development | 开发 | 290 |
| · Analysis | · 需求分析(包括学习新技术) | 30 |
| · Design Spec | · 生成设计文档 | 20 |
| · Design Review | · 设计复审 | 15 |
| · Coding Standard | · 代码规范 | 5 |
| · Design | · 具体设计 | 40 |
| · Coding | · 具体编码 | 120 |
| · Code Review | · 代码复审 | 30 |
| · Test | · 测试(自我测试,修改代码,提交修改) | 30 |
| 总计 | 300 |
3.接口说明
3.1. Information Hiding(信息隐藏)
应用实例
API Client 封装
# elevator_saga/client/api_client.py
class ElevatorAPIClient:
def __init__(self, base_url: str):
self._cached_state: Optional[SimulationState] = None # 隐藏缓存实现
self._cached_tick: int = -1
self._tick_processed: bool = False
关键设计:
-
将HTTP通信细节隐藏在
_send_get_request和_send_post_request私有方法中 -
缓存机制完全封装,外部只调用
get_state(),无需关心是否使用缓存 -
用户无需了解底层序列化/反序列化过程
优势:客户端代码不依赖具体的HTTP库或通信协议,便于后续升级(如改用WebSocket)
3.2. Interface Design
抽象基类定义标准接口
# elevator_saga/client/base_controller.py
class ElevatorController(ABC):
关键设计:
-
使用ABC定义所有调度算法必须实现的事件回调接口
-
统一的数据模型(
models.py)确保客户端和服务器类型一致 -
清晰的生命周期方法:
on_init()→on_start()→ 事件循环 →on_stop()
优势:算法开发者只需继承ElevatorController并实现抽象方法,无需关心底层事件循环和状态同步
3.3. Loose Coupling
Proxy模式解耦
# elevator_saga/client/proxy_models.py
class ProxyElevator:
def __init__(self, elevator_id: int, api_client: ElevatorAPIClient):
self.id = elevator_id
self._api_client = api_client # 通过API通信,不直接访问状态
def go_to_floor(self, floor: int, immediate: bool = False):
return self._api_client.go_to_floor(self.id, floor, immediate)
关键设计:
-
客户端算法通过Proxy对象操作电梯,不直接修改状态
-
所有状态变更通过API请求完成,服务器统一管理真实状态
-
事件驱动架构:控制器响应事件而非轮询状态
优势:
-
客户端与服务器完全解耦,可独立部署和测试
-
支持多客户端同时连接同一模拟器
-
算法代码不依赖具体的模拟器实现
4.结对编程中的实践总结
| 原则 | 具体实践 | 协作方式 |
|---|---|---|
| Information Hiding | 一人负责API Client封装,一人负责调度算法 | 通过清晰的公共接口协作,内部实现独立开发 |
| Interface Design | 共同设计抽象基类和数据模型 | 先确定接口契约,再分工实现客户端/服务器 |
| Loose Coupling | 通过HTTP API分离前后端 | 并行开发,使用Mock数据独立测试 |
核心收益:
-
降低模块间依赖,便于分工协作
-
提高代码可测试性和可维护性
-
支持算法快速迭代而不影响模拟器核心
4. 重要模块接口的设计与实现
核心接口:ElevatorController抽象基类
通过ABC模式定义事件驱动接口,子类只需实现8个关键回调(on_passenger_call、on_elevator_stopped等),框架自动处理事件循环和状态同步,实现算法与底层解耦。
算法关键点:SmartElevatorScheduler
核心策略:LOOK算法+BUS模式混合调度
-
优先级决策:车内乘客目的地 > 同方向等待请求 > 反方向请求 > 空载巡游
-
方向一致性:电梯保持当前方向直到无同向请求才掉头,减少抖动
-
永不空闲:借鉴BUS模式,确保电梯始终移动,避免idle状态造成的响应延迟
独到之处:
-
双层目的地维护:通过
in_elevator_destinations字典追踪车内所有目的地的计数(支持多人同目的地),避免过早清空导致提前停靠 -
Tick快照机制:每tick刷新等待队列快照(
waiting_up/down),避免事件处理过程中集合失真
性能表现:
-
优势场景:上下班高峰、单向流量密集场景(如up_peak),因LOOK算法顺路接人效率高
-
劣势场景:完全随机的跨楼层流量,因优先服务同方向可能延迟反向请求,不如完全公平调度
5. 需求变化与代码重构
重构实例
当增加"多场景自动切换"需求时,通过在SmartElevatorScheduler中覆盖父类_run_event_driven_simulation方法,添加auto_next_scenario标志位控制场景结束后的行为(自动切换/等待手动),无需修改基类代码。
回归测试
使用框架内置的11个流量场景文件(traffic/*.json)作为测试集,每次修改后依次运行所有场景,对比核心指标(平均等待时间、P95等待时间、完成率)确保无退化,通过Git提交前手动验证保证稳定性。
Pull Request流程
采用功能分支开发模式,本地测试通过后提交PR,由另一人Code Review检查代码规范和逻辑漏洞后合并到main分支,共完成5次主要PR(架构设计、算法实现、GUI开发、性能优化、文档完善)。
遇到的问题:合并时出现过api_client.py缓存逻辑冲突,通过当面讨论确定保留基于_tick_processed标志的版本,舍弃基于时间戳的方案。
6. 代码规范与质量保障
规范共识
采用PEP 8规范 + Google Python风格(docstring格式),通过配置pyrightconfig.json启用严格类型检查,要求所有公共接口必须添加类型注解和文档字符串。
异常处理
-
网络异常:API Client的所有HTTP请求使用try-except捕获
urllib.error.URLError,转换为RuntimeError并带上下文信息 -
状态不一致:
_update_wrappers方法检测电梯/楼层数量变化时抛出ValueError,防止状态错位 -
连接失败:GUI中使用
try-except包裹get_state(),无连接时显示友好错误提示而非崩溃
7. 界面模块设计(MVC模式)
GUI实现:Streamlit框架
界面模块:gui_app.py包含3个关键函数
-
render_elevator_visual:电梯井道ASCII可视化 -
render_floor_info:楼层等待队列表格 -
render_metrics:性能指标卡片
MVC架构体现:
-
Model:
SimulationState及相关数据模型(models.py) -
View:Streamlit渲染函数(
render_*系列) -
Controller:
ElevatorGUI类协调调度器和UI交互
模块对接:
-
GUI通过
ElevatorAPIClient获取状态(Model层),不直接访问调度器内部 -
控制操作(启动/停止/切换场景)通过
ElevatorGUI封装,调用API Client方法 -
调度器运行在独立线程,通过线程安全的API通信避免状态竞争
功能截图:界面显示实时电梯位置、方向、载客数、楼层等待队列和性能指标(平均等待时间、P95等待时间、完成率),支持启动/停止调度、切换场景、自动刷新等交互。
8. 结对过程描述
结对编程采用Driver-Navigator模式,一人编码(Driver)时另一人实时审查代码逻辑和规范(Navigator),每30分钟交换角色。关键设计决策(如接口定义、算法优先级)通过白板讨论达成共识后再动手实现。主要协作场景包括:架构设计时共同绘制类图、算法调试时结对排查事件处理逻辑、性能优化时分析不同场景的瓶颈。

9. 结对编程方式与评价
合作方式
采用Driver-Navigator轮换模式,结合Ping-Pong模式(一人写测试用例,另一人实现代码使其通过),核心模块设计采用面对面讨论确定接口后分工实现。
结对编程优缺点
优点:
-
实时代码审查减少低级错误(如类型错误、边界条件遗漏)
-
知识共享加速技能提升(学习对方擅长的领域)
-
设计决策质量高(双人讨论避免主观盲区)
缺点:
-
时间成本高(简单任务两人协作效率不如单人)
-
节奏不匹配时易产生摩擦(编码速度差异)
-
远程结对受限于工具和网络延迟
伙伴评价
优点:
-
逻辑思维严谨,能快速发现算法边界条件漏洞
-
代码风格规范,注释和文档意识强
-
学习能力强,对新框架(如Streamlit)上手快
缺点:过于追求完美主义,有时在次要细节(如变量命名)上过度纠结影响进度
三明治改进法
正面反馈:"你对代码质量的高标准让整个项目非常规范,这是我特别欣赏的。" 建设性意见:"不过在时间紧张时,我们可以先实现核心功能,把命名优化等放到重构阶段,这样能更快验证思路。" 正面结束:"你的这种严谨态度其实也帮我养成了更好的编码习惯,我们可以商量一个优先级标准来平衡完美和效率。"
10. 实际时间消耗
| PSP 阶段 | 阶段说明 | 实际耗时(分钟) |
|---|---|---|
| Planning | 计划 | 30 |
| · Estimate | · 估计本次任务所需时间 | 30 |
| Development | 开发 | 360 |
| · Analysis | · 需求分析(包括学习新技术) | 60 |
| · Design Spec | · 生成设计文档 | 20 |
| · Design Review | · 设计复审 | 20 |
| · Coding Standard | · 代码规范 | 10 |
| · Design | · 具体设计 | 40 |
| · Coding | · 具体编码 | 120 |
| · Code Review | · 代码复审 | 30 |
| · Test | · 测试(自我测试,修改代码,提交修改) | 60 |
| 总计 | 390 |

浙公网安备 33010602011771号