114
社区成员
发帖
与我相关
我的任务
分享| 这个作业属于哪个课程 | 软件工程实践W班 |
|---|---|
| 这个作业要求在哪里 | 作业要求链接 |
| 这个作业的目标 | 回顾本学期软件工程实践课的学习与项目开发全过程,反思需求到发布各阶段的收获,总结个人技术成长,并结合项目思考软件开发模式的选择 |
| 其他参考文献 | 《构建之法》 |
1| 软件工程实践——个人技术博客
2| 概述:
卫生评估用于宿舍卫生检查的“前后对比”:用户在小程序上传打扫前/后的两张图片,后端 Spring Boot 接收后转发给评估服务,再将返回的清洁度分数与指标解析为结构化结果或可读报告供前端展示。该技术适用于需要减少人工检查主观性、提高检查效率的场景,难点集中在跨端图片上传协议、评估结果的可解释性、以及外部评估服务的可配置与稳定联调。
写这篇技术复盘时,我刻意把重点放在“工程链路”而不是“算法玄学”上:我们真正踩坑的往往不是模型/特征怎么提,而是图片到底有没有传上来、Python 服务到底能不能连上、返回字段能不能稳定渲染、出了问题能不能快速定位
这学期的软件工程实践课,我第一次在一个相对完整的团队项目里体验了“需求—设计—实现—测试—发布”的闭环。
说明:本博客中的项目事实引用自仓库代码(例如后端
pom.xml/application.yml、数据库db.sql、后端Controller代码、小程序app.json/页面代码等)。
以下是我们的项目轮廓:
guichao/guichao),页面包含登录、清洁(AI 卫生检查)、群聊、设备、奖励、个人中心等(app.json 的 pages 列表可直接看到)。TeamPractice_GuiChao/TeamPractice_GuiChao),端口为 8081(application.yml 与 Dockerfile 一致)。spring-boot-starter-webSa-Tokenspring-boot-starter-websocketsys_user、user_sign_intask、dormitory_task、schedule、user_schedulereward_pointschat_messagedevice、device_light、device_air_conditioner这一段对我很重要:它让我在写文档/做联调时始终能对齐“系统边界”,避免在讨论中把一堆概念说得很大、但落不到实现。
如果要总结我在这门课里最大的变化,我会用三个关键词:
过去写个人项目时,我经常把“跑通”当作完成;但在团队项目里,“跑通”只是开始,后面还有:
这些能力不是靠看书获得的,而是一次次联调失败、一次次需求返工、一次次线上环境差异带来的“被迫成长”。
更具体地说,我的成长不是“我又学了一个框架”,而是出现了几个明显的思维转变:
我一开始对“需求文档”的理解偏向“功能列表”:有什么页面、有什么按钮、有什么接口。但很快我们在推进中遇到典型现象:
我在需求文档与联调中逐步形成了“可验证需求”的写法:
cleanliness_score/assessment_result/change_area_ratio)或一段可读报告。EvaluationController 在图片为空时直接抛 IllegalArgumentException,这类行为应该在需求里作为“错误反馈方式”体现。Sa-Token(pom.xml 可见依赖),业务接口需要明确“是否要求登录”。群聊历史消息接口在代码中就做了 StpUtil.isLogin() 校验。我在写需求说明书时还加了一条“对我最有用但很容易被忽视”的内容:
这让团队后期验收不再是“大家看着差不多”,而是能按步骤复现。
localhost:5000/evaluate 的 Python 服务)时,需求里要不要写“不可用时的降级策略/超时策略/监控指标”?写多少算合适?以前我很容易把“优雅”当作好设计,比如模式多、抽象多;但团队项目里“好设计”的第一要义是:
我们后端的包结构天然在表达模块边界:
user:注册登录、验证码、用户信息、积分等(UserController)schedule:清洁任务、排班、用户日程(TaskController 等)household:设备管理(DeviceController,以及 DeviceLight/DeviceAirConditioner 等实体)websoket:宿舍群聊(历史消息、上传图片/语音,MinIO 存储)cv:卫生评估(图片前后对比,调用 Python 服务)config/common:Sa-Token、MinIO、WebSocket、统一异常等通用能力对我来说,这种“模块化”本身就是团队协作的设计:你只要知道模块目录,就能快速找到接口入口、DTO/Entity、Service/Mapper。
同时,一些“工程化设计”也在代码里体现:
Dockerfile 固定 Java 17 环境,暴露 8081;db.sql 能一键初始化核心表。BadRequestException)使接口错误更可预期。我对“好设计”的理解也在项目里被迫具体化。比如:
ChatMessageController 中有明确逻辑)。这看起来是一个很小的 if 判断,但背后其实是“用后端约束保证系统不被错误调用拖垮”。device + device_light/device_air_conditioner),这其实是在为未来设备类型扩展留接口,而不是把所有字段堆在一张超级大表里。这一阶段我踩过一个典型坑:
/api/analyze 与 /api/eval/upload)。我在这一阶段学到的关键能力,是把“变化”当成常态:
如果设计一开始就把这些变化当作“不存在”,后面每次改动都会变成痛苦的重构。
从 pom.xml 与 application.yml 能看到我们实现阶段落地了很多工程化能力:
sa-token-spring-boot3-starter)我在实现阶段最大的收获不是写了多少代码,而是学会了把“系统风险点”提前显式化:
在这个过程中我也形成了一个固定习惯:
这个习惯直接影响了我后续做异常处理与日志优化的效率。
我对测试的理解在这学期变得更工程化:
发布阶段让我意识到:只要团队要交付,下面这些“非功能”就必须被当作必需品:
Dockerfile、端口(8081)、JAR 打包产物db.sqlapplication.yml(数据源、对象存储、邮件短信等)否则项目很容易陷入“在我电脑上可以”的尴尬。
这一阶段我最大的收获,是第一次把“交付”当作一个系统工程:
Dockerfile 让部署环境可控(Java 17、端口暴露、JAR 入口)。db.sql 让数据库初始化可复现(表结构清晰、字段含义明确)。我在群聊方向关注的不是“发消息”这一件事,而是整个使用闭环:
ChatMessageController 提供 /messages/history,并做了登录校验。/messages/uploadImage、/messages/uploadAudio 统一上传到 MinIO,再返回 URL。这类功能的工程点在于:
如果把群聊功能拆成“对用户可感知的能力”,我会这么描述:
这几个点看起来都很“功能”,但它们背后其实分别对应:分页、权限隔离、对象存储与 URL 访问策略。
我在这个方向的工程思维是:
目前仓库中可直接引用的实现是 cv 模块:
pages/main/clean/clean.js 上传前后照片ImageAnalysisController/EvaluationController 转发图片到 Python 服务 localhost:5000/evaluate 并解析结果EvaluationReportGenerator 将细分指标转换为可读报告我在卫生评估方向最深的体会是:
因此我倾向于把“解释层”当作算法系统的一部分:即使算法在 Python 端实现,我们也至少能在后端把返回结果组织成可读报告,并给出改进建议。
而你提到的“旧扣分逻辑修正、新评分算法、A/B 测试环境、参数配置化、数学模型”等更深内容,我需要进一步定位到对应代码/配置/文档后,才能在博客中逐段引用(见本文末尾“待补材料”)。
从数据库 db.sql 可以看到设备表按“基础表 + 类型扩展表”建模:
device:通用字段(device_id、type、dormitory、status、power、is_online 等)device_light:灯光扩展(brightness、color_temperature、mode 等)device_air_conditioner:空调扩展(temperature、fan_speed、mode 等)这种建模天然支持“抽象层 + 插件化扩展”的思路:新增设备类型时,不需要把所有设备逻辑都塞进一个巨大表/巨大类里。
对我而言,“抽象层”不是为了炫技,而是为了避免两种团队协作灾难:
我们采用的是轻量级任务驱动的迭代开发模式,不完全遵循 Scrum,但每个模块基本按以下闭环推进:
我个人的经验结论是:对于课程项目,轻量级迭代是最合适的;但必须配套:
如果让我回到项目一开始重新选一次模式,我仍然会选“轻量级任务驱动迭代”,但我会更早引入两件事:
评分口径:我是否能在项目中稳定做出对应成果,而不是是否“听懂”。