乐趣区

软件开发什么是过度设计

软件设计 (架构) 往往在项目开发中起到非常关键性的作用, 至少它是能够工作。良好的软件设计包含了:灵活性、可伸缩性、可行性、可复用性、安全性,通过该一系列的定义, 使我们影响到了软件功能的设计和特征。

(一)、什么是过度设计

过度设计一词在英文中称为“over design”,over 意思是太多,design 意思是设计、构思, 通过教科书上面的解释, 意味着你设计的或构思的太多了, 即为过度设计。

什么是过度设计?设计出来的系统比恰到好处要复杂或臃肿的多, 过度的封装、继承、接口或是大量的无用配置方法, 其实就是用户需要一把杀鸡的刀, 而你却设计出了杀牛刀或是电锯。

过度设计通常来自于开发者将问题过于复杂化或是前瞻性欠缺。

在我们日常所犯的错误中, 大部分是来自于前者, 至于后者的欠缺, 需要一定的项目经验和洞察力来支撑, 能够合理的预判和考虑需求会哪个方向发展。

在前者, 问题复杂化会引入大量额外的代价, 如成本上升,系统缺陷增大、提升维护成本、降低系统性能。而高性能和可维护性都是系统的隐性需求, 如果这些也没实现好, 那就可能属于设计错误。

但是从客观角度来看, 能够进行过度设计的,多半设计能力高于设计不足的, 过度的设计改回来的成本也比设计不足的改过去的成本低的多, 在此需要更多地去权衡“ 利与弊 ”

(二)、过度设计案例

以系统充值为例, 最初你设计的系统只需要一个支付宝功能, 你的数据库设计如下:

id primary key int  // 主键
user_id int// 充值用户
status  int     //- 1 充值失败,0 充值中,1 充值成功
order_no string // 第三方支付系统订单号
amount  decimal // 金额

但是没过多久, 你的系统需要接入另一个支付系统 - 微信, 需要区分用户是通过微信还是支付宝充值的, 于是你的数据库设计便成了以下模样

id primary key int  // 主键
user_id int// 充值用户
status  int     //- 1 充值失败,0 充值中,1 充值成功
order_no string // 第三方支付系统订单号
platform string // 第三方交易平台
amount  decimal // 金额

但是你想了下, 感觉可能以后需要接入银联支付, 需要记录是哪张银行卡支付的, 然后你又想了下, 既然已经接入了银联支付, 那顺便就再完善以下, 支持国际支付, 如美元充值, 港币充值, 然后需要记录上当地充值的汇率及当地支付时间, 最终你花了一天的时间, 将数据库改成了这样

id primary key int  // 主键
user_id int// 充值用户
status  int     //- 1 充值失败,0 充值中,1 充值成功
order_no string // 第三方支付系统订单号
platform string // 第三方交易平台
amount  decimal // 金额
currency string  // 货币:CNY USD HKD 
bank_id int // 银行卡 ID
rate   decimal // 充值汇率
local_pay_time  // 当地支付时间

完成基本设计后, 你花了 4 周的时间完成编码和测试, 最终交付了上去, 然而系统的初衷只是需要简单区分的是微信充值或支付宝充值, 而因过度设计带来的额外成本和缺陷是非常巨大的, 为此我们需要尽力让自己做的恰到好处并且避免过度设计。

(三、)如何避免过度设计?

避免过度设计的最佳方法就是“不要设计的太远”, 未了解实际未来, 就做出了各种预设和判断, 为系统增加了额外的负担。

正如 scrum(敏捷开发)所倡导的 Evolutionary Design(演进式设计), 将每一次的重构和迭代都映射和更新到最新的设计中来,从而最大限度的满足系统的功能性需求和非功能性需求。

当你手里握着一把锤子时, 不要把所有看到的, 都当成钉子。

退出移动版