工程设计论——如何写好工程代码

简介:设计是在对需求的认知不完整的情况下,对被设计对象进行求解的一个过程。这就迫使我们需要一边认识被设计对象,一边进行求解。为了并行化地进行这一过程,也为了使得对被设计对象地认识有初步的研究工具和基础,我们总结出了一套利用分拆提供弱约束,并基于这种分拆,来并行进行不同组件之间的设计的流程。

作者 | 任增
来源 | 阿里技术公众号

一 内容概述

  1. 从抽象的工程设计论角度阐述了如何写好一份代码。阐述了设计模式和设计原则的底层原理。
  2. 解释了设计模式与设计原则适用的场景及局限性。工程设计论是在有限设计能力下对被设计对象进行的认知和进行逆运算的过程。在不符合这一条件的领域,不应当死扣设计模式与设计原则。在软件领域,一个显而易见的例子就是不要在极度追求性能的代码中死扣设计模式与设计原则。
  3. 解释了设计原则中的单一职责原则为何难以掌握和运用。
  4. 面向接口设计是软件系统设计的最终形态,对开发流程中先写单例再开发的原因做了解释。

二 理论基础

  1. 哲学基础:罗素《哲学问题》。
  2. 数学基础:矩阵理论,工程控制论。
  3. 工程基础:一定工程设计经验,如代码开发等。
  4. 设计科学基础:谢友柏老师的《设计科学与设计竞争力》,Nam Suh的《公理设计》。

三 什么是设计——设计和计算与认知之间的联系

一门科学的建立,应当首先明确本学科的局限性,确定本学科最基本的问题与框架。明确的基本框架应能够迅速得到一门学科的基础结论与研究方法;明确的基本问题可以用于检验上述的结论与方法。指出自然界中每一杯水中都有金元素并不能对金矿的发现起到什么促进作用。设计科学的现在的发展应该做减法而不是做加法。对于设计所具备的特征,有很多描述。这些描述最基本的共同点是设计是需要达到一定的目标的(即需求)。其他特征并不是设计最基本的特征。例如最优化设计中就没有需求变更,logo设计中就没有系统故障。

如果认同需求是设计的共同点,那么搞清楚需求是什么则是重要的。 大部分人都认为,在我们的实际工作中,需求是不明确的,不完整的。那我们不妨用辩证的思维来考虑这个问题的反面,什么是明确的,完整的需求?一份完整的需求,对于所有人而言都是清晰的,不会产生什么不一样的理解。那么对于什么样的产品能够满足相应的需求,也应该是清晰的。用集合论的话来说,一个集合被其外延所完全确定。换句话说,如果需求能够被一个确定的验收方式来定义,比如说单元测试,那么这份需求可以说是明确和完整的。

我们还需要更进一步地探讨什么是验收。以单元测试为例,我们用单元测试来输出一个True或是输出一个False;如果认为单元测试本身是一个函数,那验收就是要求被设计对象在该函数下的相必须为True。那么,如果我们的需求足够简单,会发生什么情况?比如说我们的需求是找到一个x,使其满足x+1=0,我们一般称这种问题为求解,或者是逆运算。可以看到,当我们对需求及其实现方式的认识完全清晰的时候,需求将退化成为一个函数,设计将退化成为逆运算的过程。

设计的过程中,我们对于需求及实现方式的认识是不全面的,这是其与逆运算不同的核心点(而不是需求不明确或者是需求会发生变更)。例如化工产品的合成路线设计,例如高效排序算法的设计,都不存在需求本身不明确的问题。认知的不全面迫使我们需要在设计的过程中,一边对需求及其实现方式进行认知,获取更多的知识,一边进行求逆运算,找到能够满足需求的实现方式。

四 工程设计的过程

在进行工程设计的过程中,对于认知和计算的交替流程,我们总结了一套行之有效的经验,即对需求的拆分和组合。

我们刚刚已经说过,需求本质上是要求一个对象,在某个函数下的像具备某些特征,这本质上是一种约束。而“被设计对象由A,B两个组件构成,A具备123特征,B具备456特征”,这和需求的描述方式没有什么不同,本质上也是一种约束。也就是说,分拆本身也是对被设计对象的一种约束,只不过满足分拆约束的对象并不一定满足需求的约束。因此我们不妨把分拆的约束当作一种对被设计对象的弱约束。

因而工程设计可以被总结成为如下的流程:

  1. 根据对需求的相关研究,给出实现方式的弱约束,我们一般采用对系统拆分的方式来进行弱约束。在软件领域,最常见的弱约束就是对组件划分的约束,各个部件之间的依赖关系,接口的定义,数据交互方式之间的约束。(认知过程,我们一般称之为需求拆解与架构设计)
  2. 利用第一步的弱约束,来对需求中的强约束的实现方式进行具体的分析和求解。(逆运算过程,我们一般称之为编码)

我们刚刚已经说明了,分拆本质上也是一种约束。第二步中的求解结果,仍旧有可能是一种对子系统需求,此时就需要我们继续进行更加细化的设计。

引入弱约束这个概念,是因为在我们对被设计对象一无所知的情况下,研究如何实现相应的需求是相对困难的。那么我们不妨假设被设计对象具备某些性质(这种假设往往也强依赖于个人经验),并将这些假设性质(比如说接口)作为研究如何实现的一种工具和框架。

例如在代码设计中,拆分为A,B两个模块并进行并行设计时,如果在A模块的实现流程完全不知道B模块的信息,那么将会对A模块的设计产生巨大的阻碍(比如前端完全不知道后端的数据格式)。但是,B模块的具体实现方式还未确定,此时A模块也不可能对B模块的信息由完整的了解,且并不是每一个B模块的信息对于其他模块都是有用的(比如后端选用的数据库格式,后端部署的位置,后端的实现方式)。所以我们需要折中的对B模块进行约束(比如规定接口),使得A模块能够获得必要的相关信息。了解过认知论的同学也应该知道,这种接口本身就是一种对B模块的认知(参照罗素的感觉材料或是我在前序文章中所述的“关系”)。我认为这是依赖注入的底层逻辑,也是面向接口设计将成为软件设计的最终形态的底层依据。

在这个例子中,工程设计与科学研究后进行计算的最大区别即在于,第二步中的具体实现过程是并行的。各个组件的实现的并行在软件工程中是常见的(前后端分别编码,最后进行调试即是如此)。我们当然可以在完全研究清楚J(X)的性质下,再去进行设计。限制我们不去这么做的条件,并非是这样得到的产品效果一定不好,而是设计需要投入的工期与人力有限制。完全设计好前端之后,再去进行后端设计,当然是可以的,但是这种串行化的工作模式,显而易见的会对工期造成负面影响。

为了使得这种拆分方式可行,独立职责的原则就需要被引进以保证最后的组装工作顺利完成。在上一步中,我们的工作是并行的,意味着我们并不知道f(X),g(X),m(X)所需要取得的值是多少。如果我们最终研究得到

那我们显然是找不到相应的解的。这就需要我们保证f({X}),g({X}),m({X})之间的相互独立。我们对拆分地独立性及其负面影响进行进一步地探讨:

这一规则对应于软件领域中的单一职责原则,有人评论这一原则是较为难以运用和掌握的(“单一职责原则是最简单但又最难运用的原则”)。事实确实如此,接下来我们将对这一点进行探讨。

我们换一种看起来正确的模棱两可的表述更方便我们发现问题在哪。这个陈述是:独立的功能应当由独立的类来实现。那么,问题出现了。我们怎么去判断两个功能之间相互独立?熟悉哲学,并对哲学中对“Free”的讨论有接触的人会很快反应过来,“Free”这个词必然是建立于某种映射之上,单独说A与B“Free”没有任何意义。家庭教育和学校教育是否独立?道德教育和智力教育是否独立?从不同的角度会有不一样的答案。从时间上,家庭教育和学校教育相互独立;从评分标准上,道德教育和智力教育也相互独立。如果把教育也作为一种设计,我们是应该把教育划分成为家庭教育和学校教育,还是划分成为道德教育和智力教育?划分的依据究竟应该是什么?

显而易见的事情是,我们所能够接受的判断功能之间的相互独立的依据,应该是从其实现方式上相互独立。那么上面那句话,就可以改写成为:实现上独立的功能应当被独立地实现。这有点像一句政治正确的废话,其具体的运用强依赖于设计人员对于相关领域的事前经验与判断。不具备相关领域的经验,进行功能划分必然会出现一些搞笑的结果。这就是单一职责原则是最简单,也最困难的原则的原因。

五 总结与局限

设计是在对需求的认知不完整的情况下,对被设计对象进行求解的一个过程。这就迫使我们需要一边认识被设计对象,一边进行求解。为了并行化地进行这一过程,也为了使得对被设计对象地认识有初步的研究工具和基础,我们总结出了一套利用分拆提供弱约束,并基于这种分拆,来并行进行不同组件之间的设计的流程。由于分拆只能提供关于被设计对象的较弱认识,因此依赖倒置和面向接口设计是必须的。为了使得并行化的设计最终可以被组装,单一职责原则(独立原则)是必须的。

可以看到,整个设计理论是必须基于对需求的认知不完整,且需要低成本(首要的是时间成本)地完成设计这一条件。对于设计周期比较长,认知较为充分的领域,设计理论并不适用。完全只用设计模式来衡量设计的好坏,也是不可取的。这方面的反例有很多,LeetCode上面的题目,恐怕没有哪一个符合了设计模式,比如说找链表倒数第k个节点中的双指针就是一个典型。对于人体而言,也并不遵循什么单一职责原则,甚至可以说耦合地不像,人在饥饿的时候,可以分解蛋白质来供能;我们在飞机设计过程中,有考虑过在液压油泄露时,拿燃油来充当液压油么?一些经典设计也并不遵循设计理论与原则,例如活塞环既能够防止漏气,又能够降低摩擦磨损,这显然也不是符合独立公理的。

只有对设计科学的底层逻辑有着深入的研究,才能使得这门科学发挥其真正的作用。虽然本文尽可能地对这个领域进行了一些减法地操作,略去了一些不核心的要素,但是无论在理论上,还是例子上,都没有能够提供一个真正能够被验证成为正确或是错误的想法或是命题。本文甚至连错误都算不上,这无论如何都是让人不满意的。

六 附——利用分拆来设计系统的一个例子

很多设计领域的文章提出的例子,都是一些已有的设计;或是拿着根本没有市场的需求来设计一款产品。这种先射箭后画靶的行为并不能促进科学的发展。因此找一个大家都熟知的领域,提出解决起来较为有难度,但是需求明确的问题来作为探讨的例子。很幸运的是,我的确解决了我自己提出的问题。

在机械领域,平面杆件机构的设计是最基本的问题。例如对下图中这种四杆机构,我们经常会进行摆角的设计等工作。那么,我们能不用匀速的电机和平面杆件,使得平面杆件上的某一点有着指定的轨迹?例如用平面杆件画一只兔子?

对于这个问题,我们梳理我们已经知道的知识,来给出一些弱约束:

那么,我们再由拆分给出另外的弱约束,以解决这一问题:

在这样一个弱约束下,我们的问题就变为了:

如何通过一些圆周运动,及建立在其上的加法体系,拟合任意一个周期运动。

  1. 如何找到一个连接组,使得其具备上述条件。
  2. 问题一的答案由傅里叶变换给出:

问题二可以由如下杆组完成,转动副2始终为转动副1,3的中点:

最终的设计,我用了16个主动件,及16个连接组,共计80个杆件,得到的结果已经在上图中展示了。

诚实而言,我认为这个例子在说明弱约束和强约束,以及拆分对于工程设计的必要性方面,仍旧难以摆脱先射箭后画靶的嫌疑。但是至少,我不认为我设计的机构,就是本问题的最优解;我想本问题用以说明工程设计并不能得到最好的设计这一点,还是足够的。

原文链接

本文为阿里云原创内容,未经允许不得转载。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/511402.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

阿里云能耗宝即将发布,助力中小企业绿色升级,参与碳中和万亿市场

阿里云能耗宝新品发布会由阿里云-企业云服务-能耗云团队主办,将于2022年2月23号举行,本期发布会将为企业呈现“双碳”背景下的一站式服务。通过阿里云能耗宝,企业如何更加高效便捷地核算碳排放量、制定节能降碳方案、规划碳中和路径。 2020年…

关于网络安全,企业领导者应该了解的3件事

作者:Veeam 企业战略副总裁 Dave Russell 随着全球疫情期间世界各地数百万人转向远程工作,网络安全再次成为关注的焦点。勒索软件是一种通过网络传播的恶意软件,它通过感染计算机并限制对关键用户数据的访问来获取赎金。每起勒索软件攻击事件…

鸿蒙关键技术研究,鸿蒙内核源码分析(静态链接篇) | 完整小项目看透静态链接过程 | 百篇博客分析HarmonyOS源码 | v54.02...

百篇博客系列篇.本篇为:下图是一个可执行文件编译,链接的过程.本篇将通过一个完整的小工程来阐述ELF编译,链接过程,并分析.o和bin文件中各区,符号表之间的关系.从一个崭新的视角去看中间过程,阅读之前建议先看准备工作先得有个小工程,麻雀虽小,但五脏俱全,标准的文件夹和Makefi…

敏捷研发项目,我们该如何度量?

简介:作为项目负责人,我们如何及时获悉当前项目的最新进展和问题,了解项目的整体状况?作为项目管理人员,我们如何跟进和推进项目的正常进行?如何借助云效效能洞察平台 Insight,帮助项目管理者及…

iofsstat:帮你轻松定位 IO 突高,前因后果一目了然 | 龙蜥技术

简介:磁盘被打满到底是真实的业务需求量上来了呢?还是有什么野进程在占用 IO? iofsstat 帮你精准定位。 编者按:sysAK(system analyse kit),是龙蜥社区系统运维 SIG 下面的一个开源项目&#x…

补招开发岗需要80天?软件开发人员短缺的几个“真相”

作者 | Jani Bagheri 供稿 | Mendix 许多企业已经意识到对遗留系统进行现代化改造、提高运营效率并通过创新的解决方案吸引客户的重要性,意味着企业需要招聘更多的软件开发人员。技术创新需要专业的软件开发人才与开发工具,没有软件开发人员就不会有新技…

html视频标签不显示,HTML视频标签无法正确显示视频

这里是我的JS:function video() {navigator.device.capture.captureVideo(onSuccess, onFail,{limit: 1,duration: constants.MAX_DURATION_OF_VIDEO});function onSuccess(mediaFiles) {console.log("MEDIA FILE");console.log(mediaFiles);var i, path,…

晋中计算机专业对口大学,山西晋中计算机专业好就业吗?,计算机专业

【山西大众技工学校】将学生的日常管理、学习成绩、操行考核融为一体,结合校园全封闭管理形成一套完整的学生管理办法,做到每个环节都有标准与要求,每个过程都有管理和考核。山西晋中计算机专业好就业吗?另一种称为“编译”&#…

实战 Kubectl 创建 Deployment 部署应用

作者 | 洲的学习笔记来源 | CSDN博客本篇文章主要是实战 Kubectl 创建 Deployment 部署应用。通过本期文章:我们将学习创建在 Kubernetes 集群上运行应用程序的 Deployment 所需的最常见的 Kubectl 命令。用 Kubectl 创建 Deployment当运行 Kubernetes 集群&#xf…

性能提升一倍,云原生网关支持 TLS 硬件加速

简介:业界在优化 HTTPS 的性能上也做了诸多探索,传统的软件优化方案有 Session 复用、OCSP Stapling、False Start、dynamic record size、TLS1.3、HSTS 等, 但软件层面如何优化也无法满足流量日益增长的速度,加上 CPU 摩尔定律已入暮年&…

Linux 中如何检查开放的端口

作者 | 刘光录来源 | TIAP无论你的服务器是用的Linux还是桌面系统,了解系统开放的端口,和正在使用的端口,在各种情况下都会有所帮助。比如,如果你的服务器中正在运行着 Apache或者Nginx,那么其端口应该为80或者443&…

微服务应用实现无损上下线实践

简介:本文是阿里云微服务引擎MSE在应用发布时提供的无损上下线和服务预热能力最佳实践介绍。 本文是阿里云微服务引擎MSE在应用发布时提供的无损上下线和服务预热能力最佳实践介绍。假设应用的架构由Zuul网关以及后端的微服务应用实例(Spring Cloud&…

计算机策划知识竞赛有创意的主题,【社团活动】首届创意·科技文化节--第八届计算机趣味知识竞赛决赛...

就21世纪而言,计算机莫过于是至今最成功的创新,作为计算机科学系的学子们担当着社会的前行者,从语言不和的英文代码,到逻辑化的函数循环,甚至有人开玩笑高呼着“c从入门到放弃”。谁又忍心让大家始终学习在枯燥中呢&am…

3月2日,阿里云开源 PolarDB 企业级架构即将发布

简介:2022年3月2日,开源 PolarDB 企业级架构将迎来重磅发布!本次发布会将首次公开开源 PolarDB 的总体结构设计和企业级特性,对 PolarDB for PostgreSQL 的存储计算分离架构、HTAP架构、三节点高可用架构进行全面介绍。 2021年&a…

产学研专家共议中国金融机构数字化转型,“守正创新”成主基调

《中国金融机构数字化转型》白皮书同期发布。 7月12日,由华为云与《清华金融评论》联合主办,清华五道口“数字中国”企业家课程项目提供学术支持的《中国金融机构数字化转型》专题研讨会在线上举办,并在央视财经等平台直播。研讨会邀请到多位…

极速生成缩略图,Serverless 支撑赛事转播锁定冬奥亮点

简介:阿里云函数计算(FC)支撑用户开发赛事视频截图的核心业务代码,实现了弹性高可用免运维的直播视频截图服务,满足用户开发成本低、一键部署的业务需求,比赛期间完美支撑视频转播实时锁定冬奥亮点。 作者…

html拼接日期,html日期加减

//显示某年某月某日function getForecastTime(date) {date new Date(date);var nDate date.getFullYear() "年";nDatedate.getMonth() 1 "月" date.getDate() "日";return nDate;}//日期加减function dateChange(num, date) {debugger;if…

“电信级”运行多年,亚信科技推出核心交易数据库AntDB7.0

亚信科技AntDB数据库为全国24个省份的10亿多用户提供7*24小时实时在线服务,已在通信运营商核心系统持续稳定运行多年。同时,AntDB在金融、交通、能源、公共服务等多个领域商用落地。 数字化浪潮和信创的趋势下,国产数据库市场迎来了快速发展期…

关于质量标准化的思考和实践

简介:最近部门在推质量标准化,通过质量标准化,推动质量内建,从而提高研发部门的交付质量,作者深度参与其中,并在推进过程中总结了一些经验以及思考,在此通过以下定义、共识、实践三个大方向和大…

计算机科学与因果关系,计算机科学与技术

摘要:In order to improve the detection reliability of effective connectivity in brain network, an fMRI (Functional Magnetic Resonance Imaging) analytical approach of effective connectivity is proposed based on the Granger causality (GC) and the …