很多团队把软件设计等同于画架构图、套设计模式。其实设计只回答一个问题:当需求变化时,你要改多少地方?好的设计让变化局部化,坏的设计让一个小需求牵动十个文件。
边界是职责变化的方向。订单服务不该知道微信支付如何签名,只该知道支付成功或失败。把第三方细节挡在接口后面。
interface Payment {
boolean pay(String orderId, int cents);
}
class OrderService {
private final Payment payment;
OrderService(Payment payment) { this.payment = payment; }
void submit(String orderId, int cents) {
if (!payment.pay(orderId, cents)) throw new IllegalStateException("支付失败");
}
}这里没有工厂、没有单例,但依赖倒置已经发生:OrderService 依赖抽象,不依赖微信。换支付宝,订单逻辑不动。
传统三层架构里,上层依赖下层。软件设计更关心:谁依赖谁。业务策略不应依赖数据库驱动,而应依赖一个 Repository 接口。实现可以换 MySQL、Redis、内存,业务不变。
依赖方向对了,替换成本就低。依赖方向错了,抽象越多越乱。
不要为“以后可能”加抽象。两个实现才考虑接口,三处重复再提取。YAGNI 不是懒,是省下维护成本。设计模式是工具箱,不是任务清单。
真正难的不是写出复杂结构,而是在需求还不清楚时,忍住不写复杂结构。
每个边界都能单独测试。OrderService 不需要启动微信,传一个假 Payment 就能测。测试难,往往说明边界错了。
可测试性不是测试团队的事,是设计质量的外显。
没有唯一正确答案,只有当前约束下更合适的结构。先写能跑的,再改到好改的。每次修改都让下一次修改更容易,这就是好设计。
软件设计不是让代码看起来高级,而是让变化来临时,你还能从容改。把变化关在接口后面,把简单留给日常。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。