2个版本
0.1.1 | 2023年11月8日 |
---|---|
0.1.0 | 2023年11月8日 |
#2 在 #scoreboard
1MB
637 行
包含 (WOFF字体,400KB) NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2,(WOFF字体,135KB) FiraSans-Medium-8f9a781e4970d388.woff2,(WOFF字体,130KB) FiraSans-Regular-018c141bf0843ffd.woff2,(WOFF字体,82KB) SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2,(WOFF字体,77KB) SourceSerif4-Regular-46f98efaafac5295.ttf.woff2,(WOFF字体,45KB) SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2 和更多。
评分板
编码练习
开发一个新的实时世界杯评分库,显示所有正在进行的比赛及其比分
要求
- 必须是库实现
- 使用内存存储解决方案
- 使用TDD,注意面向对象设计、Clean Code和SOLID原则
- 实现基本API
- 开始比赛。假设初始比分“0-0”,应捕获两个参数:主队和客队
- 更新比分。应接收一对绝对比分:主队比分和客队比分
- 结束比赛。从评分板中移除正在进行的比赛
- 获取摘要。返回所有当前比赛,按总比分排序,总比分相同的按最近开始时间排序
假设
- 不期望特定编程语言。为了学习目的,此项目将使用Rust
- 未提及线程安全性。它被认为是“最好有的”功能
- 一支球队在给定时间内只能参加一场比赛。例如,如果目前正在举行洪都拉斯和哥斯达黎加之间的比赛,这两支球队都不能出现在新创建的比赛
- 在所有API调用中,“主队”始终位于“客队”之前。如果球队的顺序对于操作不正确,则返回错误
- 获取当前结果摘要将比其他所有API函数更频繁地使用。这将影响优化选择
进度
基本要求
要求 | 状态 | 注释 |
---|---|---|
1. 库 | 作为一个独立的Rust库crate开发 | |
2. 存储 | 使用标准的Vec 向量集合。有关更多评论,请参阅“可能的附加功能 -> 优化” |
|
3. TDD | 在一定程度上遵循TDD。大多数函数都很小,可以首先为第一个测试编写最终正确的版本,然后添加其他边界情况 | |
4. API | 公共ScoreBoard 结构和其方法 |
|
4.1. 开始 | ScoreBoard.start_game(home_team_name,away_team_name) |
|
4.2. 更新 | ScoreBoard.更新得分(home_team_name,主场得分,away_team_name,客场得分) |
|
4.3. 完成 | ScoreBoard.完成比赛(home_team_name,away_team_name) |
|
4.4. 总结 | ScoreBoard.获取总结() |
额外功能
功能 | 状态 | 注释 |
---|---|---|
队伍独特性 | start_game(team1, team2) 如果任一队伍正在比赛,则拒绝请求 |
|
线程安全 | Rust编译器提供线程安全,除非涉及到严重的黑客攻击。在此仓库中没有unsafe 代码 |
文档
该项目使用代码注释进行文档化
手动生成
运行此命令以生成文档并打开
cargodoc --open
在线
生成的文档可在GitHub Pages上找到,地址为daydreamest.github.io,或在crates.io
安装和使用
安装
编译
移动到"scoreboard"目录并运行
>cargo build--release
第一次执行时,Cargo将下载依赖项(例如日志crate)。之后,库将被编译成二进制文件
scoreboard/target/release/libscoreboard.rlib
使用
作为Rust源代码
将scoreboard.rs
文件复制到您的项目中,并在需要的位置使用use
导入模块
use scoreboard::*;
作为编译后的Rust库,使用rustc编译器
将编译后的libscoreboard.rlib
文件复制到您的项目中,并在编译选项中添加一个标志
rustcmain.rs --externscoreboard=libscoreboard.rlib
作为cargo库
在Cargo.toml
文件中添加以下行,位于[dependencies]
scoreboard_world_cup= "0.1.1"
测试
要运行测试,请移动到"scoreboard"目录并运行
>cargo test
可能的其他功能
API
- 队伍名称在内部作为UTF-8字符串保留,没有进行广泛的验证。这允许像"AAAA - jskdfhgidsf","USA - U.S.A."或其他任何两个不同的字符串名称的匹配。一个很好的改进是创建一个枚举或字典,保留所有可用名称的列表,并对其进行验证
update_score()
非常难以使用,并允许任意更改得分。在足球中,得分的改变以量(通常称为“进球”)出现,因此应该有一个方法add_goal(team_name)
,它将提到的队伍的得分加1
优化
- 使用时间戳来验证哪个比赛先开始。这可能是一种过度行为,但比实现内部计数器更干净、更简单,但代价是CPU效率较低
Vec
用作数据容器。还有其他集合可用,但即使是Rust指南也建议坚持使用可靠的向量。可以考虑其他选择来提高效率,但它们需要进行性能分析和库的真实世界使用- 每次添加、得分变化和删除数据后都会进行排序。排序可以移动到汇总显示方法中,这样在代码中“发生”的次数将只有一次,但这有一些缺点。
get_summary()
方法必须可变,并改变得分牌的状态,这不利于设计。- 作为替代,
get_summary()
可以复制数据并在返回之前本地排序,但这会增加不必要的内存使用。 get_summary()
预计会被调用得比所有其他 API 函数的总和还要频繁,因此它必须快速简单。对大量并发比赛添加排序可能会严重影响时间。- 当前
sort()
的实现对于部分排序的集合或具有排序元素段的集合表现极佳(来源)。因此,它对现在使用的函数的影响应该很小,因为它们的更改仅适用于单个比赛,而其余集合保持排序。
- 可以考虑
Vec
和push()
的替代方案,这些方案可能在某些情况下跳过排序。新创建的比赛具有最低的总得分和最新的时间戳,因此可能在start_game()
上的排序可以省略,但这需要更多的分析。
问题
- “match” 是 Rust 中的一个关键字,因此在整个代码中使用“game”一词表示“两个队伍之间的比赛”。