软件设计是什么:
一百个程序员,就有一百种理解。若按照这些方式去了解“软件设计”,软件设计的知识不仅散乱,且像陷入沼泽:
软件设计应关注长期变化,能应对需求规模的膨胀。然而这些在不断变化的东西可能还没你的软件生命周期长,又怎能支撑长久的变化?那软件设计到底是什么?
软件开发是解决由需求带来的各种问题,解决结果是可运行的交付物。如在线购物的需求,使用电商平台方案解决。软件设计就是在需求和解决方案之间架设的一个桥梁。
区别于解决简单的问题,软件开发往往是一项长期工作,是个多人运动。这就需要建立起统一的结构,以便所有人都能有共同理解。就像建筑中的图纸,懂建筑的人看了后,就会产生一个统一认知。
而在软件开发过程中,这种统一结构就是模型,软件设计就是要构建一套模型。 模型包括:
写代码中常用的服务(Service)、调度器(Scheduler)等概念就是一个个模型。模型是一个软件的骨架,也是一个软件之所以是这个软件的核心。一个电商平台,它不用关系型DB,还可用NoSQL,但若无产品信息,没有订单,它就肯定不是电商平台。
模型粒度可大可小。若把模型理解为一个个类,就是小模型。也可把整个系统当作一个整体,就是大模型。“高内聚、低耦合”就是对模型的要求。 这种模型有效隐藏细节,理解更容易,可继续扩展。如程序设计语言,就是提供编程模型,让我们写程序不用再面对各种硬件差异,还能够在此基础上继续提供新功能。各种框架和技术,也是提供了一个个模型,它们大幅降低了开发门槛。
所以整个计算机世界就是在这样一个又一个模型的叠加中,一点点构建。模型是分层的,就像乐高,由一个个小块构建出一个个大部件,再用这些部件组成成品。 与一些人理解的Controller、Service分层有差异。这才是在计算机行业中普遍存在的分层。网络模型就是典型分层模型。按TCP/IP分层,网络层要构建在网络接口层上,应用层要依赖传输层。 即便是在一个软件内部,模型也可分层。可以先从最核心的模型开始构建,有了这个核心模型后,可通过组合这些基础的模型,构建出上一层模型。
如交易系统设计。分析主要交易动作后,提出一个交易原语概念,包括资产冻结、解冻、出金、入金等动作。然后,把原先的交易动作变成了原语的组合。如下单是资产冻结,成交是不同账户的出金和入金,撤单则是资产解冻:
由:
这就是模型的分层。所以,模型是一个软件核心;模型粒度可大可小;好模型“高内聚、低耦合”;模型可分层,由底层的模型提供接口,构建出上层的模型。
仅是把软件设计理解成构建模型还不够。模型设计也不能任意妄为,需要有一定约束,即软件设计要构建的另一部分:规范。
限定什么样的需求应该以怎样方式完成。如:
每个项目都有自己的规范,但问题也常驻。如
规范是维系软件长期的演化。没有显式规范,项目维系只能依靠团队个人发挥,新人往往创造不同寻常新写法,项目朝着失控发展。某项目,多种不同的做法并存:
没有统一规范,每个项目上的新人都会骂街前人代码。然后,新人自己另起炉灶,又加了新东西。其实前任们的混乱一般也就是这么开始的。存在一个显式、统一的规范,项目就能按一个统一方向行进。即使后续设计要演化、规范要调整,统一规范也比散兵游勇代码更可控。
有次网关OOM。这个网关日常内存消耗达150G,一次流量暴增它就扛不住。后来经过优化,把内存消耗降到8G。单看数字,20倍优化,nb啊,具体咋整? 最核心内容就是构建防腐层,将请求过来的JSON转换成普通内存对象。而原来做法是把JSON解析器解析出来的对象到处用,因为这些对象上附加很多额外信息,导致占用大量内存。
只是因为旧的规范不符合软件设计原则而导致的错误:外部请求的对象需要在防腐层转换为内部对象。
模型的一个规范:我接触防腐层的概念是从DDD的限界上下文开始。Eric用细胞膜的概念来解释“限界”的概念,细胞膜只让细胞需要的物质进入细胞,代码之间业务也存在这样一个界限,同一个对象的业务含义在不同的上下文中不一样。网上买书为例:
防腐层是在限界上下文之间映射(说白了就是交互)的方式,体现在代码上就是一个对象的转换,这个转换的意义在于隔离变化,防止因为对象在一个上下文中的变化扩散到其他的上下文中。
规范也是团队文化中很重要的一部分,以持续集成为例子,它的执行严格依赖于团队的开发纪律文化,以为了所谓赶进度而单元测试覆盖很低或者直接不写;采用分支策略方开发,一星期都合并不了主干,类似的人到处倒是,也就因为这一点,很多团队都在持续集成这个环节上掉队了。所以开发规范真的很重要,时刻谨记:混乱始于没有规范。
二者相辅相成。一个项目最初建立起的模型,往往要符合一定规范,而规范的制定也有赖于模型。 就像讨论户型,可按照各种方式组合不同空间(模型),却不会把厨房与卫生间放在一起(规范)。
软件设计既包含构建出一套模型,也包括制定出相应的规范。
软件设计应该包括:
模型与规范,二者相辅相成,一个项目最初建立起的模型,往往是要符合一定规范的,而规范的制定也有赖于模型。
软件设计,应该包括模型和规范。