《软件方法》第1章2023版连载(01)

2023-09-21 23:27:20

DDD领域驱动设计批评文集

做强化自测题获得“软件方法建模师”称号

《软件方法》各章合集


决定把第8章一部分关于“伪创新”的内容移到第1章,因此此次也更新第1章。


第1章 建模和UML

牵着你走进傍晚的风里,看见万家灯火下面平凡的秘密。

《情歌唱晚》;词:黄群,曲:黄群,唱:曹崴;1994

1.1 利润=需求-设计

1.1.1 利润=需求-设计

利润=收入-成本。不管出售什么,要获得利润,需要两个条件:

(1)售价要高;

(2)成本要低。

妙就妙在,价格和成本之间没有固定的计算公式,这正是创新的动力之源。

放到软件业上,我也炮制了一个式子:

利润=需求-设计

在软件开发中,需求工作致力于解决“提升销售”的问题,设计工作致力于解决“降低成本”的问题,二者不能相互取代。能低成本开发和维护某个系统,不一定能保证它好卖。系统好卖,如果开发和维护成本太高,最终还是赚不了多少钱。

(有的读者可能会想:我做的项目是单位内部项目,不卖钱。那我只能说too simple, sometimes naïve了,可以继续往下看。)

同上,需求和设计之间不存在,也不应该存在有规律的映射——也幸亏如此,否则人工智能就可以取代人完成。人(即软件开发人员)存在的价值就是在很多种现有可行的映射方案中,努力挑选出其中最好的方案,甚至通过技术革新,创造出更好的方案。

我们先来看自古以来就有的一个系统,“人肉系统”。

人肉系统的功能(需求)是(人能够)走路、跑步、跳跃、举重、投掷、游泳……但是设计人肉系统的结构时,并不是从功能(需求)直接映射到设计,得到“走路器官”、“跑步器官”、“跳跃器官”……人肉系统的器官是眼、耳、心、肺、肝、胃、骨架、皮肤……这些器官和人肉系统的功能不是一一对应的,在互相协作以完成系统的功能时,它们和功能之间的关系是多对多的。

图1-1是某个人肉系统的需求和设计。可以看到,需求和设计的映射是多对多的。各个器官被各个功能共享,不能说“心脏是老板的”、“肺是老爸老妈的”。

图片

图1-1 人肉系统的需求和设计

图1-1的映射只是造物主——用《异形(Alien)》的说法就是工程师(Engineer)——当初挑选的映射方案,今天,人类也成为造物主开始“造人”的时候,我们挑选的映射方案可能和人类的造物主(如果存在)制造人类的映射方案是不一样的,如图1-2。当然,目前人类的科学技术水平,连细胞都造不出来,想要做一样的方案也做不到就是了。

图片

图1-2 人类和“新人类”

如果老板要雇一个民工扛煤气罐,他只要求这个民工能跑能扛,管他体内构造是心肝脾肺肾(如图1-2上部)还是电路板(如图1-2下部)——如果电路板民工更便宜,他会淘汰掉心肝脾肺肾民工;民工找工作也要从市场的需要来找——“有老板雇人扛煤气罐,我可以!”,而不是从自己的内部器官出发来找——“老板,我每天都管理我的心脏,你请我吧!”

以上所说的这些,总体意思就是:要学会把需求和设计分开,这也是贯彻全书的核心思想,后面还会反复强调——用词可能会有变化,例如“卖和做分开”、“外和内分开”。

软件开发中,如果从需求直接映射设计,会得到大量的重复代码,成本增加;如果从设计出发定义需求,会得到一堆假的“需求”,卖不出去。总之,利润就会缩水。

而这一点,很多软件开发人员并没有意识到。

1.1.2 常见错误

1.1.2.1 “子系统”其实是需求包

我们经常听到这样的说法,“本系统分为八大子系统,包括销售子系统、财务子系统、库存子系统……”,这就是需求和设计不分的一个例子。其实,正确的说法可能应该是“本系统的功能需求分为八大需求包……”。

需求包是基于涉众视角对系统功能分包而得到的,子系统(用UML的说法是组件)是基于内部视角根据系统部件的耦合和内聚情况切割而得到的,这两者不是一一对应的。所谓的“财务子系统”,其实可能是“把财务人员使用的功能放在一个包里”,如图1-3。

图片

图1-3 “子系统”其实是需求的分包

1.1.2.2 “功能模块”是错误用语

另一个常见的需求和设计不分的说法是“功能模块”。

功能(Function)。当我们说起这个词的时候,一般指的是系统的功能需求。因为对于组织,一般说“组织的服务”,对于类,一般说“类的操作”。

不过,“功能需求”仍然不够精确。例如,以自助柜员机(ATM)为研究对象,“取现金”是“功能”,“登录”也是功能,“计算手续费”也是“功能”,到底“功能”有多大?用例的术语要严谨得多。“取现金”是一个用例,“登录”是用例中的一个回合,“计算手续费”是一个步骤。

因此,“功能”是一个模糊用语。本书在后文会尽量使用严谨的用语,不用模糊用语。

模块(Module)。当我们说起这个词的时候,研究对象一般是系统。模块表示系统的组成部分,但这个词也是模糊的。这个模块是一个控件?一个类?若干个类形成的组件?

如果说“功能”和“模块”是模糊的,那么连起来说“功能模块”就是错误的。“功能模块”意味着在意识里认为“功能”和“模块”有直接的映射关系,甚至认为“模块”是属于某个“功能”的模块,是为了完成某个“功能”而存在的。

我简要归纳需求和设计的区别如图1-4,在后面的章节中再慢慢进一步阐述这些区别。

图片

图1-4 需求和设计的区别

高焕堂在他的书《USE CASE入门与实例》[1]中说过:用例是收益面,对象是成本面。本书基于他的思想做了扩展。

1.1.2.3 微服务的遮羞布

最近几年鼓吹的新词“微服务”造成一定的误导。有的人误以为“微服务”就是“需求设计一一对应”。

假设考虑到开发团队的结构,把系统分成多个“微服务”,分由各个小团队应用各自的技术栈独立完成。例如图1-1中的男士,可能会被分割为“996微服务”、“交作业微服务”、“扛煤气罐微服务”。

且不说这样划分是否合理,即使这样划分了,“微服务”内部也要通过自己的各个部件(可能是残缺的)协作完成,例如“做作业微服务”要完成“做作业”用例,也需要眼睛、耳朵、手、脚、心脏、**等(可能是残缺的)协作完成,并非映射一个“做作业模块”然后就搞定。更何况,有的用例需要若干个“微服务”协作才能完成。

另外,“微服务”是妥协的不良结构。如果这样的划分风格所得到的软件结构真的是良好的结构,我们几十年前就可以这样做。即使一个人做的项目,也不妨引入一个假设“由各个小团队应用各自的技术栈独立完成”来改善软件的结构,不必等到今天才大兴“微服务”之风。

我用盖大楼作类比:

两座大楼耸立在那里,要判断地震来了哪座大楼不容易塌,要考虑的是大楼的结构、所用的材料、所在位置的地质环境等,和这座楼是哪家公司建造的,要了多少钱,建造大楼的公司内部是怎样的组织结构,一共有几支工程队,当时怎么分工的,甚至大楼是猫建造的、狗建造的、外星人建造的,已经没有直接关系——因为大楼已经在那里了。

但要研究这些让大楼不容易塌的直接影响因素,涉及到艰深的工程力学、流体力学、岩土力学等知识。架构师李三没把这些知识学扎实,正在那里犯愁呢。

这时,伪创新专家张四出现了。张四说,时代变了,现在盖楼要讲“新建筑学”,要考虑到人际关系,要搞好团结。

于是,李三想着反正“老的”工程力学那些我也搞不懂,还是搞“人”轻松一些。这样吧,有几个包工队跟自己混,就分几个包,大家开干就是。

转换思想后,李三每天累并快乐着,灯红酒绿,推杯换盏。

而且,运气好的时候,盖出来大楼确实也能住人。

如果李三说,公司又不是我的,想那么多干什么,这可以理解;

如果李三和张四说,这么干盖楼快,反正老板要的就是在某某大日子到来之前有个样子货交差,这也可以理解;

如果李三和张四说,这么干有利于建筑团队的安定团结(虽然坑顾客),这也可以理解;

但如果李三和张四说,“新建筑学”盖出来的大楼更抗震,甚至到清华大学建筑学院开课“划时代革命性的工程力学”,取代原有的“工程力学”——这就是无耻了!

更多推荐

idea Terminal 回退历史版本 Git指令 git reset

——————强制回滚历史版本——————一、ideaTerminal第一步:复制版本号(右击项目–>Git-->ShowHistory-->选中要回退的版本–>CopyRevisionNumber,直接复制;)第二步:ideaTerminal(确认项目)输入指令:gitreset--hard版本号示例:gitreset

【计算机组成原理】第一章部分课后题

冯·诺依曼型计算机的主要设计思想是什么?它包括哪些主要组成部分?冯·诺依曼型汁算机的其本没计思想为:①以二进制形式表示指令和数据②程序和数据事先放在存储器中,计算机在工作时够高速地从存储器中取出指令加以执行③由运算器、控制器、存储器、输入设备和输出设备五大部分组成计算机硬件系统它的主要组成部分为:运算器、控制器、存储器

数据治理-分类法

分类法是一种命名结构,包含用于概述主题、启用导航和搜索系统的受控词表。分类法有助于减少歧义并控制同义词,层次分类法包含了对索引者和搜索者都有帮助的多种类型的父/子关系。这样的分类法常用于向下扩展分类。分类法可以有多种不同的结构:扁平分类法:在受控类别集之间没有关系,所有类别都是平等的。这类似于列表。例如,一个包含多个多

[CISCN 2019 初赛]Love Math 通过进制转换执行命令

目录hex2binbin2hexbase_convert动态函数第一种解法通过get获取参数绕过第二种解法读取请求头getallheadersechoa,b第三种解法异或获得更多字符这道题也是很有意思!通过规定白名单和黑名单指定了函数为数学函数并且参数也只能是规定在白名单中的参数我们首先要了解通过进制转换执行命令的第一

【论文基本功】【LaTeX】个人常用易忘LaTeX命令

【论文基本功】【LaTeX】个人常用易忘LaTeX命令1.基本符号2.引用3.字体及符号大小4.其他参考1.基本符号符号LaTeX命令备注∣⋅∣|\cdot|∣⋅∣|\cdot|绝对值∣∣⋅∣∣||\cdot||∣∣⋅∣∣\|\cdot\|范数⌈⋅⌉\lceil\cdot\rceil⌈⋅⌉\lceil\cdot\rce

SpringBoot MyBatisPlus Oracle

官网官⽹:https://mybatis.plus/或https://mp.baomidou.com/pom<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www

shell脚本自动化执行jar包

需要用shell脚本来自动化执行jar包,以后可以用jenkins来CI/CD,记录一下对应实现。实现需求以命令行执行shell传入的第一个参数为jar名进行执行。对应jar已存在执行进程,关闭对应进程后再执行。以后台方式执行对应的jar包,输出log文件并判断是否成功执行。测试用jar包和功能为了保持进程执行不退出,

简单的分析下dart实现grpc客户端的流程,以helloworld为例

第三步:实现实现gRPC方法在HelloWorldClient类中,为每个定义在.proto文件中的rpc方法实现对应的Dart方法。简单的分析下dart实现grpc客户端的流程,以helloworld为例这里给出helloworld的proto文件,grpc协议下客户端和服务端都只需要关注相同的proto文件并以自己

JVM-环境准备&性能指标&基础知识

环境准备&性能指标&基础知识环境准备JDK—工具JDK(JavaDevelopmentKit)是用于开发Java应用程序的软件开发工具集合,包括了Java运行时的环境(JRE)、解释器(Java)、编译器(javac)、Java归档(jar)、文档生成器(Javadoc)等工具。简单的说我们要开发Java程序,就需要安

YOLOv8快速复现 训练 SCB-Dataset3-S 官网版本 ultralytics

目录0相关资料SCB-Dataset3-S数据训练yaml文件YOLOv8训练SCB-Dataset3-S相关参数0相关资料YOLOV8环境安装教程.:https://www.bilibili.com/video/BV1dG4y1c7dH/YOLOV8保姆级教学视频:https://www.bilibili.com/v

【R语言】完美解决devtools安装GitHub包失败的问题(以gwasglue为例)

Rstudio,R4.3.1,命令在Rstudio的命令行即console中运行。文章目录一、问题复述二、分析三、解决四、安装示例:gwasglue一、问题复述使用devtools安装一个github的包。devtools:devtools是R语言中一个非常有用的包,它提供了一套工具和函数,用于开发、测试和维护R包,d

热文推荐