|
用UML给网上购物系统建模,基于最容易犯的网上毛病是一上来就画类图。我见过不少课程设计,购物开头就是系统一堆Customer、Order、基于Product的网上方框,属性列了七八行,购物方法写得更细,系统结果问起“用户下单时库存怎么锁定”,基于图里根本找不到对应关系。网上UML不是购物用来炫技的,它得能回答具体问题。系统 拿购物车来说。基于很多人把它当成一个孤立的网上类,挂上addItem()和removeItem()就算完事。购物实际跑一遍业务会发现,购物车和库存之间有个隐晦的交互:用户把商品加进购物车时,系统通常不会立刻扣减库存,但得记录“这个SKU被占用了多少”。这个约束在类图上经常被漏掉,导致后面画顺序图时,Inventory对象凭空冒出来一个reserve()消息,前后对不上。我的做法是先画活动图,把“浏览商品→加入购物车→结算→支付→发货”这条主流程的分支和泳道理清楚,再回头补类图。活动图里那个“库存检查”的判断节点,会逼着你想明白:检查动作发生在哪个对象上?是Cart还是Order?答案是Order,因为购物车阶段还没生成正式订单,库存不该被真正锁定。 用例图倒是可以最先画,但别搞成“用户→登录、用户→浏览、用户→下单”这种流水账。真正有用的是把参与者之间的泛化关系标出来。比如“注册用户”继承“游客”,游客能浏览和搜索,注册用户才能下单和查看历史订单。这个继承箭头一画,权限控制的代码结构基本就定了。还有支付环节,支付宝、微信、银行卡三个参与者如果都直接连到“支付”用例,图会乱成一团。抽一个“支付网关”作为抽象参与者,具体支付方式继承它,干净得多。 顺序图我习惯只画两条:一条正常下单,一条库存不足。正常那条里,User发出checkout(),Order对象先向Inventory发checkStock(),拿到true之后再创建OrderItem,最后调用PaymentGateway。库存不足那条更有意思——Order收到false之后,不该直接给用户弹错误就完事。实际系统里往往要触发一个“到货通知”的订阅,这个Alt片段里的消息流,比任何文字描述都直观。画完这两张图,后端接口的入参出参基本不用再猜了。 状态图适合盯住Order这一个对象。新建、待支付、已支付、已发货、已完成、已取消,六个状态之间的迁移条件写清楚。有个坑:待支付状态如果超时,是自动取消还是保留?状态图里加一个timeout事件,指向Cancelled,旁边注明“30分钟未支付”。这个细节在需求文档里经常被含糊带过,但状态图逼你给出确切答案。我见过一个项目,因为没定义超时后的库存释放逻辑,导致大量订单占着库存不放,最后靠定时任务扫表才补救回来。 组件图和部署图在课程设计里常被忽略,但网上购物系统恰恰需要。把“用户认证”“商品目录”“订单处理”“支付适配”拆成四个组件,标出它们之间的依赖接口。部署图上,Web服务器、应用服务器、数据库服务器分三块,负载均衡器画在Web前面。这样一摆,答辩时老师问“秒杀场景怎么扩展”,你指着应用服务器那层说“这里可以水平加节点,订单处理组件无状态”,比空谈架构强得多。 工具方面,StarUML和PlantUML我都用过。StarUML拖拽方便,但版本管理麻烦;PlantUML用文本描述,适合放进Git。我现在的习惯是:活动图和顺序图用PlantUML写,改起来快;类图用StarUML,因为要反复调整布局。别纠结工具,图能说清问题就行。最后提醒一句:画完所有图,拿一张A4纸把“用户下单”这个场景从头到尾手写一遍消息流,如果哪一步卡住了,回去改图。UML的价值不在图本身,在画图时被迫想清楚的那些边界。 |