软件设计要素初探
概述
软件是一种特殊的作品。看不见摸不着,却似有幽灵般的力量驱动事物运行并展示变化。软件本质是数据采集与加工装置,其使命是处理数据。人通过软件与数据和生活交互。数据-模型,算法-流程,封装-集成,现实-连接。
软件设计将需求转化为可见的数据结构与领域对象、算法与流程,并采用恰当的全局/局部结构进行组织和集成,符合软件的预期质量指标。软件设计的核心是逻辑结构的设计。数据的结构、控制流的结构、部署的结构、结构的组合与嵌套。
软件设计要素主要包括:设计目标/原则/考量、领域建模、系统划分、应用模型、架构流图、存储设计、模式系统、技术设施、API设计。设计要素也涉及到全局错误处理、破解结构性难题、整体与兼容、设计取舍、设计与重构、设计与质量、设计与细节、维护与扩展、测量技术、设计实验。
本文主要对软件设计要素做一个全景式的了解,作为日常设计和开发工作的基本指引。
总体导引
设计目标
制定设计目标是非常重要的。团队的人力和资源通常是有限的,而要完成的事情和指标似乎无穷无尽,相互冲突。贪多嚼不烂。设计并不是无头无尾的纸上谈兵。
确定要达成的功能及相应的质量属性,哪些是真正所期望的,能够真正解决人们的麻烦,决定要往哪个方向使力,投入是否获得了令人欣喜的产出。 设计要考虑人性,人与人之间的沟通。 做正确的事情。
详见: “架构设计的目标与衡量”
设计原则
为了确保软件能够适应复杂多变的业务需求,且持续保持“柔性”, 需要确立和遵循一些设计原则。设计原则指导设计实践和编程实现。
详见: “一些软件设计原则”
设计考量
当拿到一个需求/重构/优化时,如何展开设计工作呢?设计方案需要考虑哪些因素呢?
详见: “设计方案考量的准则与细则”
设计要素
设计要素可以分为宏观层次的要素和局部层次的要素。宏观层次的要素影响软件的整体设计和变更;局部层次的要素只影响软件的某个组成部分。
宏观层次的要素主要包括:领域建模、系统划分、应用模型、架构流图、存储设计、技术设施、API设计;局部层次的要素主要包括:模式系统、设计实践的取舍权衡。
领域建模
领域建模是软件设计的初始点。 反复追溯事物的本质“是什么”,从不同视角去理解事物的性质,理解事物之间的关联,梳理事物与活动的流程与环节,抽象出实体与关联,规则与约束。
领域建模最核心的部分是:定义自身的定位,定义基础要素,定义完备的能力集合。
可参阅: “软件设计要素初探:领域建模的初步思考”
系统划分
将整个系统划分为若干正交的紧密关联的子系统,以及高内聚低耦合的小而美的模块与微服务,理清职责、交互与边界。划分的基本原则是“识别、分离和组合关注点”。每个子系统必定有其核心关注点和基础关注点,而基础关注点中交叠的部分,即是子系统交互定义的基础。
可参阅:“软件设计要素初探:组件化思想”
应用模型
应用模型涉及到数据处理的全局流程和交互方式。 我所接触过的,主要有“请求-响应模型”、“流处理模型”、“分布式模型”、“人机交互模型”。
可参阅:“软件设计要素初探:应用模型”
架构流图
架构流图是系统组件及组件交互的动态流动图,决定了处理数据和领域对象的全局控制结构。组件化是使用架构流图的前提。
可参阅:“软件设计要素初探:架构模式”
存储设计
存储设计是领域建模的设计细化,决定数据的结构以及领域对象的表达与存取,是软件详细设计的关键环节。存储设计通常要考虑读写操作的性能、容量、并发、事务、搜索。
可参阅: “软件设计要素初探:存储设计”
模式系统
模式系统,是对软件设计与开发中常见问题的设计方案和成例总结。在很多时候,模式简化了设计的考量,能够以更小的成本获得更好的方案。模式的组合,在技术层面构成了软件应用的骨架。
模式在不同层次上,可以分为:设计模式、业务模式、架构模式、分析模式。
-
设计模式是实现特定需求的接近代码层面的设计套路,通常用于梳理和表达对象之间较为复杂的依赖和交互关系,将错综复杂的容易膨胀的难以理解和扩展的条件判断逻辑解开成一系列对象的清晰可理解的易扩展的交互结构。 参阅文章:“设计模式之基础模式概览”
-
业务模式是对业务规则和流程的常见相似性、以及特定业务的数据处理能力的提炼**,是业务应用系统中的常见套路。可参阅: “软件设计要素初探:业务模式”
技术设施
技术设施是实现特定类软件应用的适用某种编程语言和平台的一整套技术机制。技术设施是软件系统的通用子域。
以下是我所接触过的Java系技术设施:
-
Java系技术栈基石是:Java + JVM ; JavaWeb技术栈基础是:Http + Servlet【必知必会】
-
简单JavaWeb应用后台:Struts + Spring + Hibernate + JSP + Velocity 【深情回顾】
-
Java服务工程后台:Spring + ibatis + Mysql + Cache + Message + Restful(or Dubbo) + [ Git ] + ZK【工程套路】
-
海量业务数据管理:Cluster + ES + Hbase + Storm 【大数据技能拓展】
-
测试工程:Python + Groovy + CI + CodeReview 【质量控制】
-
运维:Python + Shell + Ngnix + Docker(or VM) 【DevOp能力】
-
前端技术栈基础: Html+Javascript+CSS+Ajax + Reactor; 基础库:jQuery + Bootstrap + Highchart 。由于我已不再写前端,对前端蓬勃发展的技术体系不甚了解,这里不再多述了。
技术选型即是根据项目实情选择或简单或复杂的技术栈。技术选型通常更多考虑实现目标的非功能质量属性。性能、初期成本和发布时间、团队技术组成、产品复杂度、可定制性、可扩展性、可维护性是常常要考虑的重要因素。
技术选型也可适当引进正在起步发展的技术。起步发展的技术虽然不够成熟,对线上服务的稳定造成潜在的威胁,却可抓住机遇领先一步,提升生产效率。可先在内部应用或探索性项目中试点,然后逐步推广到线上应用。因噎废食是不可取的。Anyway, 再先进的技术栈都会很快过时,什么才是真正值得掌握的呢?
API设计
API 是软件应用向外部提供自身服务的一种形态和公开接口。就像一个人的着装打扮、举止言行、形象状态,是其内在的某种体现。优雅的API是清晰简洁的,就像少女的肌肤一样柔滑。
怎样合适地公开服务,是需要精思熟虑的。“通用订单搜索的API设计得失录” 和 “重新设计导出API” 梳理了我在做API设计实践的一些心得与反省。
实际权衡
软件设计的实际过程中,还需要权衡更多因素,才能做出最终设计决策。
“软件设计要素初探:软件设计的一些子主题” 讨论了一些设计的实际问题: 错误处理、结构性难题、整体与兼容、设计取舍、设计与重构、设计与质量、设计与细节、维护与扩展、测量技术。
要素组合
实现好设计
好设计
好的设计自然、清晰而容易理解;容易扩展和修改而影响局部化;丰富而不复杂不单调。可以将好的设计与好的绘画或建筑进行对比。好的绘画和建筑,有的简洁而内涵深意,有的丰富而不失清丽。好的设计不矫揉造作,亦不过度追求,满足必需而添加适当的色彩。
设计实验
物理学家为了探索和发现自然规律会设计物理实验,思想家为了论证某个问题会设计思想实验,工程师为了验证实现的可靠性会设计工程实验,而设计者为了提升设计能力和验证设计的可行性,也需要大量的设计实验。针对每个设计知识点,设计一些实验,或者在项目实战中使用和体会。重要的是从实验中快速积累大量经验。
可做的设计实验有:
-
代码层次:在业余项目中研习设计模式, 在正式项目中使用和体会设计模式; 重构代码,更加自然而容易理解和扩展; 识别和分离关注点,组件化逻辑;抽取和积累常用业务模式的实现。
-
设计层次:绘制设计图增进整体理解;识别和解除设计束缚;提炼关注点,定义合适接口; 多视角设计判断活动;从细节中发现设计。
-
存储层次: 关系型存储设计;大数据存储设计; 学习底层存储结构的原理与实现。
-
领域层次: 抽象事物、活动与关联;在破解结构难题中创建新的技术机制实现。
-
测量层次: 测量软件的响应时间、吞吐量和稳定性,观察占用资源。
-
经验层次: 学习优秀源代码和系统;积累设计模式、业务模式与架构模式。
-
质量层次: 为设计制定质量指标,并使设计方案符合质量指标要求。
小结
无论是领域模型、系统组件、架构模式、存储设计还是业务模式、设计模式,都是一种结构抽象。结构模式或大或小,都是软件结构的构件。软件设计,即是发现和运用结构模式,解决现实中的各种业务问题。
综合而言,软件设计主要是由两部分组成:相对稳定而可演进的领域模型,若干结构模式所组合而成的可重构优化的应用控制结构。