各位同学大家好。
本节课程是 东北师范大学 信息科学与技术学院 计算机系 系列课程的一部分。这个系列课程名为 新技术讲座。本节的内容是工程师基本素养。
我是计算机系教师杨贵福。
本节课将从以下三个方面展开,1.工程师的责任,2.工程师的价值观,3.工程师的方法。
第一部分是 工程师的责任。
工程师是一种职业,理工科学生毕业后,不少人在企业、高校、研究所中要沿工程师的职称序列成长。根据经验、能力、贡献,有时根据年资,先是初级工程师,后来工程师、高级工程师。
不同的自然科学学科在生产实践中应用,工程师也相应地分布在许多不同的行业中,土木工程、电力工程、电子工程、化学工程。计算机科学也创造了很多工程师岗位,硬件、嵌入式系统、软件工程、数据分析工程……很多。
这些工程师既有学科的特色,互有差别,同时也有很多共同点。正如软件工程首先是工程,其次具有软件的特色。我们来看一般的普遍的工程师责任,也正是这种责任决定了工程师不同于其他行业的价值观和方法。
工程师所制造的是产品,每个产品是一个系统,为系统以外的用户提供服务。在软件工程中,我们把系统的边界以外的用户称为角色,服务大致视为特定场景中的功能,称为用例 use case。用例相关的技术手段非常丰富,在UML和RUP中都是重要的线索。
这里还有个特别关键的因素,如此关键,以至于在大多数系统中都不把这个元素画出来。就是边界。
边界以规定哪些*不是*我需要关心的,这样的方式来规定出哪些是我的责任。
工程师不关心why。地球为什么围绕太阳转,为什么月球总是以相同的一面对着我们,为什么mp3和jpeg有损压缩以后人类几乎感觉不到效果变差。完成这些工作的责任在科学家的肩上。虽然对于科学原理的讨论,甚至更深入的道德和哲学的讨论,工程师作为个体也会参与,但是这些并不直接地影响工程项目的实施准则。工程师所依据的准则,那些为什么,是既定的先验的。工程上不允许任意探险,作为客户,我们希望的是工程师完成任务,采用确定有效的方法,在确定的期限内,达到确定的效果。
工程师也不关心感受美,那是艺术家的事。
也不关心公众是否理解工程项目所依据的原理,这是科普的事,从另一个角度说,客户关心的只是效果,不是原理。
黑客很酷,但窥探不是工程师的责任。避免客户被窥探,防止系统漏洞损害用户的利益,这是工程师关心的。
游戏很好玩。工程师是制造这些好玩的东西的人,玩这件事本身,不是工作责任的一部分,没有人为你玩游戏付钱。你快乐没人付你钱,让别人打游戏快乐,才有人付钱。
工程师也会做实验确认产品和项目中的一些事实,但是对于这些以外事实的确认,增加人类知识库的事实,不是工程师关心的。
工程师手里的武器是 自然的法则,是科学家所发现的why,以及人类共同知识库中的定理、断言、谓词。
工程师的目的是帮助他人,解决客户的问题。通过为客户解决问题而为社会做出贡献,这也是工程师取得收入、安身立命的来源。客户为什么需要我们,因为有些问题客户无法解决,我们能够解决,客户已经能解决的,我们能解决得更好。花钱更少,速度更快,更少人力,质量更高。
通过什么方法帮助他人呢。产品。这些产品是工程项目,是工具。制造某种工具,或者使用现有的工具,用成熟的原理,巧妙地组合,为用户解决问题。用这样的方法帮助他人。
所以,工程师的责任是提供服务。客户有需求,我们有自然法则这样的知识。怎么服务呢,不是通过教授用户这些知识,那是教师的责任,而是通过制造工具,用工具自动地,工程师不在现场的时候,科学家不在现场,用户不必掌握这些知识的情况下,替用户解决问题。
人们对工程师所提供的服务当中最主要的期待,是可靠。
稳定的服务。
什么是稳定?当NBA教练换人的时候,他需要考虑候选运动员的方差。你有两个选择对象,一个是发挥极其稳定,但是水平一般,另一个是偶尔爆出冷门,但是也可能炸裂地差劲。如果快输了,我们就会选不稳定的这个,万一赢了呢,反正不然也是输。如果我们现在正领先,就需要稳定的输出,不连续输就行,保持就好。什么体育精神拼搏打出最优秀的效果,不是冷静地以胜负为目的时应该考虑的。
古代战争为什么很少夜袭,偶尔出现就值得记录下来大书特书。因为夜袭的方差非常高,可能快完蛋的一方突然把对方将军斩了。在白天“正常”的打法中,这种高方差是不容易出现的。
客户对工程师的期待是稳定输出,你肯定不希望我尝试先进技术,你的系统没事就崩溃吧。
怎样才算稳定?不受干扰的影响。山崩于前不变色,海啸于后不动容。你可以说这是木讷,同时这也就是稳定。外界环境不断变化,而我的输出始终如一。外界这些改变,都不是我的函数的自变量。下可以工作在零下20度,上可以工作在75度高温,这才是好的CPU。
工作中,特别是刚工作的同学,也有人会说“那我也不能工作在75度”啊。这得看规约spec是怎么定的,也就是清晰的边界。到底是不是你的责任。如果由你负责,那么不能推给别人。”word排版结果就是这样的,就是与学校的论文格式要求不一样,我也不知道怎么回事,整不了。”这是不能接受的。
上级让我飞,可是我没有翅膀怎么办。这是与行政上级间的契约。如果你受理了这个项目,这条写在规约里了,你就得兑现。如果做不到呢?你的上级不是工程师,他不见得有这个能力判断这件事能不能实现,他也没有这个责任。你需要告诉他,这个做不到,为什么做不到,不仅我做不到,根据自然法则,你找谁做也白扯。拒绝不合理的,包括不符合自然法则的,包括自相矛盾的,拒绝这样的客户需求,也是工程师的责任。
这样,我们就能稳定地兑现我们的承诺,给客户一个可以预期的稳定的世界。
工程师为了稳定地完成责任,形成了与自然科学科学家共同的价值观。
当我们评论一件事的情况,对这件事做出褒贬,这样的时候,我们会有三个维度。在工程师的价值观中,这三个维度的顺序不可以颠倒。
一是 真假。什么是真假,就是事实。事实是没有感情色彩的,不具有道德判断,即不讨论善恶,甚至也没有动机。我们在这里谈到某个方案好坏的时候,不是指提出方案的这个人是好的还是坏的,而是指这个技术方案会不会达到我们期待的效果。至于这个效果是善是恶,这个工程师的道德修养,出于什么动机揭示这一事实,是不是想害我,那都是另一个问题,并不在真假中讨论。
二是 是非。是非是道德判断。道德判断需要在真假之后才能讨论。不能因为我们觉得这件事是恶的,为了显得我们是善良的,就掩盖事实的真实性。或者因为揭示事实的人是我们的敌人,一般称为“友商”,或者他们动机不良,我们就不承认事实。事实只能以事实来否定,是非必须居于事实之后,诉诸动机和是不是我们一伙的对于判定真假都没有帮助。
三是 里外。你的项目不符合社会道德的,违背工程伦理,因为我和你是一伙的,咱俩同一导师是师兄弟,咱俩一个专业,咱俩是老乡,咱俩同一公司,共同对外,就认为你做的是对的。这就是里外代替了是非。或者咱俩一个小组,所以项目里你的数据我就得承认。如果你换了个小组呢,换到敌对方,那么原来正确的就变成了错误的?这是里外代替了真假。
真假、是非、里外,这个顺序不可以颠倒。这是工程师的价值观。“按道而行”是极其艰难的,有时代价巨大。也许我们做不到每件事都符合我们所认可的价值观。但是,我们要知道那是错的,不符合我们所追求的道,而不是给自己找个借口骗自己。错了就是错了,做错事是错的,对错事的认可是另一次错误。
推荐扩展阅读这本书,《公正》,网上还有视频课可以看。
第3部分讨论工程师的方法。
工程师与科学家虽然同属于理工科,都讨论自然科学的法则,但是一个是发现法则,一个是应用法则,在方法上有些区别。
工程师的问题来自客户,最终归结到付钱的人,或者付钱的人所关心的人,软件工程中把这些人称为 stake-holders。
到底要达到什么样的效果,什么样的效果用户才能满意。软件的响应速度需要几毫秒,卡顿有明显影响用QoS,数据丢失更可怕的时间用”尽力而为”BE。最终的,都是由用户的利益决定的。
新方案可能带来什么样的负面效果,需要对现有体系做哪些变更,这些变更是不是符合工程规范。有多大概率会失败,失败的结果中有多大比例比不用这个方案还差。在确定地了解这样的效果之后,包括正面的和负面的,还要不要实施。这些都需要授权,授权直接来自你工作中的上级,最终来自用户、法律法规。
从用户脑袋里的需求,到我们手里的自然法则,中间要有问题/领域分析和建模的过程。这些都是工程师的责任,用户只要看效果和成本就可以了。关于求解,延伸阅读推荐波利亚的这本书。
从用户的需求到实现的方法,通常不能朴素地映射,或者说,朴素地问题都轮不到你做,早有人做完了。比如两个苹果加三个苹果等于五个苹果这类问题,在一般意义上,模型是确定的,无须工程师出手。
从需求到方法,首先要提炼出问题,需要明确边界。明确边界,表面上看是承诺哪些属于本项目要完成的内容,事实上同样重要的另一个方面,常被忽略的,是哪些是与本项目无关的。再次拿出这张图来,边界是系统中至关重要的方面。
有了边界以后,我们就看到了“函数”。当用户操作或者环境变化作为自变量输入或者激励,系统总是会给出特定的输出或者响应。为了达到这个目的,我们就需要无二义性地定义哪些是自变量,这些指标如何测量,定义域的范围是什么。函数值也是一样的。人类自然语言的沟通,充满了甚至工程师也难以察觉的歧义,用户以为自己说的是一回事,工程师以为的是另一回事。同一个行语在此时此地是一个意思,在彼时彼地是另一个意思。
用户常说的一个词,“正常”。”你就正常做,我就正常操作,正常速度就行。”什么是正常,这个话题深入讨论需要相当长时间才能揭示用户的动机,《概率论和数理统计》对什么是正常有精确的定义,不过那不一定是用户认同的。
我们需要把用户的需求映射到物理量,量化这些指标,还需要用户确认我们的理解与他们的意思一致。我们需要帮助用户去除二义性选定指标,给出指标的度量方法。然后我们给出指标间的数量关系和因果有关系。这些关系是用户期待的产品,由用户来确认确实是他们想要的,由我们来实现。
值得指出的是,不要相信网上公众里号连作者都不懂意思的所谓的模糊、复杂。作为初学者我们有机会工作的范围,没有到达这种程度。事实上,即使在更高级些的项目中,引入了模糊数学和系统科学复杂系统的,模糊的定义也是精确的,复杂也可以分析的。模糊和复杂这样的字眼,并不是我们平时聊天时的意思。
刚才提到用函数描述用户的需求。为什么呢,因为自然法则也是用函数描述的。
在项目中,函数是这样一种关系,它描述了 当我们已知此时此地的状况,即使不经过实验测量,也确定地知道彼时彼地会有什么样的结果。用实验一测,结果刚好一致。
想像一下,如果我知道你的出生年、月、日、时辰,就能说出你未来做什么职业,配偶什么样,人生有哪些坎坷。这就是函数想做到的,输入是时间,输出是,嗯,一大堆可观察可检测的变量。
孙子说,“夫未战而庙算者胜”。所谓运筹帷幄决算千里之外,是用算筹这种计算工具,在帐篷里这个此时此地,估算出千里之外彼时彼地的结果。这也是函数。
我们高等数学老师裴教导我们,函数就是个豆浆机,它的机制就是这样的。你给它绿豆,就出绿豆浆,你给它红豆,就出红豆浆,你给它黑豆,就出黑豆浆。你给它黄豆,它出白豆浆,但是绝对不会这次出白豆浆,下次出黑豆浆。总之非常靠谱。我们在算法中把这个特性叫做可重现性。
相声表演艺术家马三立先生讲的段子里说,两个大国比赛吹牛,当然他们自己挺认真的。一个说,我们科技老发达了,造了台机器,这边把猪赶进去,那边出来的就是火腿肠。这就是函数了。另一个别,你们那不算什么,我们有台更厉害的,火腿肠出来以后一尝有点咸,塞回去,那边出来的是猪。哈希这类函数告诉我们,反函数的时代开销特别大。
自然法则和用户的需求都具有这样的特点,希望已知此时此地,推算出彼时彼地。
从用户的需求到自然法则,我们所寻找的模型是某种函数。
但是,我们如何确认这个模型就刚好是用户需求的问题呢?或者说,你怎么知道这个模型就是“对”的呢?
我们分三步讨论。第一,模型从哪里来。
实践论告诉我们,模型是从实践中总结出来的。什么是总结呢,咋就能总结出来了呢?孔子和两小儿都看到太阳了,托勒密和哥白尼也都看到太阳了,他们都总结出了模型。我们可以简单粗暴地总结,总结就是这么总结出来的。
康德不这么认为。简单粗暴地总结,他认为人类的头脑中首先存在模型,外部现实世界的事实该怎么发生怎么发生。人类,是人类主观地判定,某些现象刚好与某些模型是匹配的。推荐延伸阅读材料,哈耶克的《科学的反革命》。这本书比《纯粹理性批判》薄,我们所讨论的这部分也更容易读。另外,这本书一点也不反革命也不反科学。
对于初学的工程师,当把用户的需求去二义性描述为问题以后,我们可以简单粗暴地总结为,接下来找模型就是个主观主义的过程。我们一共就会这么几个模型,就是你在课本里学的,在文献里看的,还有你导师和上级工程师给你的paper里的那些。挨个匹配一遍,哪个最像就是哪个了。手里拿着锤子,看什么都像钉子。要么这个问题是个钉子,你用锤子解决了。要么这个问题不是钉子,你解决了不了,你也没有别的工具。如果还有锯子、斧子、凿子,那么也挨个试试。通常,工程师不需要发明新工具。当你能发明新工具的时候,你就不正常了。当然,你更可能发明以后才知道,这样的工具早就有了,就你不知道。
当然,第一时间能判定这个问题超出了你的学科范围(这里有重大的技术风险,必须第一时间判定),或者需求不合理内部有矛盾,不仅你谁也解决不了,这些也是你工作的一部分。
模型,不是你,不是你这个人从实践中总结的。至少别人的、前人的模型从哪里来,这样的哲学问题,超出我们的课程范围了。
模型为什么正确的第二个问题,抽象。
模型是对用户需求的抽象,把现象抽象为函数。从这个角度,抽象可以理解为 并非从事实中提炼出模型,而是找到现有模型与观察到的事件之间的相似关系。抽象,并非增加出一个模型,而是去除现实事件中与模型中指标无关的因素。望文生义或者顾名思义帮助记忆的话,abstraction的字根中的ab就是away,from, tract是拖拉。抽掉不关注的部分,留下的就是模型。选择,就是放弃。当把苹果抽象为个数的时候,我们就舍弃了重量、成熟度、颜色、口感。当把学生抽象为分数时,就抛弃了快乐、人品,也与籍贯、身高、性别等诸多因素无关。
抽象是找相似,找现实与模型的相似。那么,什么是相似呢?
手机的仿真模型,用来帮助用户体验重量和触感的,这种模型和传统电话座机,哪种与手机更相似呢?
我们在日常生活中,讨论相似,常用的手法有 类比,老师你就像我妈妈一样和蔼并啰嗦; 有比喻,老师就像红烛一样燃烧自己照亮别人,有举例;有的老师比如你吧,上课净讲段子不够严谨。这些在项目中都不够严谨。抽象,是什么样的相似呢?
在项目中的相似,这个问题相当于在离散数学课的代数系统或者说群论部分里的同构。扩展阅读推荐这本《GEB》。
我们如何保证施加于两个集合上的函数运算,它们的自变量和函数值分别是一一对应的呢?在数学上,我们可以想办法证明。当其中的一个函数是外部世界,我们只能测量其中的一部分自变量和函数值呢?我们如何保证我们主观判定的“相似”总是正确的呢?
现在谈模型选定的第三个问题。选定了模型以后,怎么就知道它是与客观事实的发展相符合呢?
两苹果比三个苹果少,这是指标是个数,量化为一维数值比较。但是为什么你选择那两个大的,给我三个小的,你选择两个红的,给我三个青的烂的呢?这是模型适用错误,得到的结果用户不会满意的。
模型如果对以前的现象都符合得很好,未来就一定也适合么?休谟质疑了这个观点,前天太阳升起来了,昨天太阳也升起来了,明天太阳就一定也能升起来么。罗素讲过一个故事,说明这个问题。美国有只火鸡,农民每天早晨给它喂吃的,就说太阳一升起来就喂吧。上上个月这样,上个月也这样,每天这样,太阳一升起来,农民就带好吃的来了,火鸡得冲在第一个去抢,这样才能长得最健康。有一天,感恩节到了。我们知道感恩节美国人要吃火鸡。所以,根据前天昨天总结的模型,不一定适合于今天。
如果说检测足够长的时间就行了。多长时间算长呢?如何保证更长时间,更多数据的时候,模型不会出错呢?
波普尔说,是不能保证的。我们不能保证现实世界符合我们选定的模型,不能保证。那么用户为什么付我们钱呢,凭什么说我们选定的模型符合要求呢。严格地说,也不能。波普尔的观点是,我们只能通过实验证伪一个模型,一个假说,但是不能证实。如果一个假说一个模型具有可证伪的特性,比如它无二义性地预言了彼时彼地会如何,我们去检验,确实如此。我们就说,这个假说暂时没有被推翻。不是说它是对的,它暂时不是错的。
有时候,我们在工程中暂时的让一个现象消失了,但是我们并无把握我们找到了问题的原因,还有可能是因为其他的我们没有预料到的因素,导致这个现象消失了。甚至这个糟糕的现象还可能出现,我们说这是一个workaround。
假设,假设我们的模型是正确的,也就是说符合客观实际,那么模型能用来做什么呢?如果模型错了,我们怎么才能知道呢?
模型是数学函数,当有了已知数据以后,我们能用模型推演出未来。用算筹,用沙盘,孙子和当代的军人用来这些来推演战局的发展方向。施加什么变量以后系统会有什么变化。ENIAC,第一台计算机,用来计算氢弹和炮弹火力表。以上这些是工具。开普勒三定律是模型,用来推算太阳系行星运行轨迹。Alpha Go是模型,用来推算围棋棋局。以上这些是模型。
这些推算都需要观察现实的数据,作为函数的输入。所以,我们需要观察现实,需要学习各种度量的手段。需要减少误差到什么程度,如何减少误差,哪些误差的影响更大。如何在观测的时候减少对系统的干扰,还记得伏特表和安培表么,为什么大多数情况它们可以视为不影响不干扰测量值。根据度量的结果,使用模型估算出新的结果,再次度量,根据度量的结果修订模型中的参数。比如,你每天到底能集中注意力背单词多少分钟,假期有读几本书的时间,这些,都需要度量才能估算出来。
我们要致力于设计实验的设计,调整环境保证度量的变量是在约束下发生的,怎么测,测什么,测出的结果意味着什么。这些都是需要我们在实验前考虑的。在按下运行键之前,我们对实验的结果就有期待,是根据模型推演出来的结果。凡是与我们期待不同的,就是有问题。实验是用来检验的,不是用来探索“会发生什么呢”。如果实验结果与模型一致,那么我们对现实的猜测模型暂时没有错。如果实验结果与我们期待的不同,那么要不然就是模型不符合客观事实,是错的,要不然就是测量有问题。这些表面上负面的结果都帮助我们认识世界和我们自己的模型,帮助我们前进。
此外,我们还要谨慎地排除没有意识到的假设。是不是偶然的因素,是不是必然的但是并非我们改变和测量的那些变量影响了结果。把青蛙腿切掉,在青蛙的旁边大叫它就不跳了,青蛙的听觉器官在腿上么?
在实验中,在项目中,在日常生活中,都有很多逻辑谬误,会在模型推演中得出与现实世界间不符合的结论。
推荐扩展阅读 据称是人民日报整理的这篇文章,还有批判性思维这样的书籍。
在项目中常见的很多。例如,错误归因。例如,过早优化。
一个与日常生活中差异较大的,比如在技术讨论中当被要求给出证据时就怀疑对方攻击自己了。你跟医生说你发烧了,医生会现场测你体温,你没啥意见,不会说“你居然不信我”。但是在项目中,帮助用户复现故障,或者要求工程师给出依据、论证过程、或者现象的时候,感觉受伤害的不少。在自然科学领域,疑罪从有,主张者举证,是广泛接受的职业道德规范。这是模型吻合问题的重要保证。说大家都用、哪个牛人也这么用、课本就这么写老师就这么讲、张三的模型也有这样那样的缺陷,这些都没用。
如果没有现成的模型怎么办呢?
有个办法,就是 小步快跑,摸石头过河。我们把任务拆成很多个周期,每个小周期称为一次迭代。在每次迭代的开始时用现有模型估算,在当次迭代结束的时候度量,修正模型。这样的思路适合于我们人类对于当前问题尚无明确认识的时候,在工程实践和工程管理中应用都非常普遍。
比如在自动控制中,用PID即比例、积分、微分运算,每种运算的权重不同。通过许多次每次都非常微小的迭代,控制小车在行驶过程中不因为累积误差等原因过多地偏离预定轨道。在工程管理中,用戴明环,在每个迭代中通过四个步骤,即计划、执行、检查、行动,保证不偏离既定目标太多。这样,尽管没有先验的模型,我们也可以在相当程度上,足够好地满足用户需求。
小步快跑,就是快递迭代,每次迭代进步要少量,不可一蹴而就。多次迭代,特别地要求对实验测量的频繁和精确,这就是摸石头。
所以,回到实验上来。工程技术依赖实验科学。是不是满足需求,在执行过程中每个迭代的现状如何,这些都需要测量。测量,根本上,依赖的是实验技术。模型是否足够贴合现实世界,不是模型说了算,而是现实说了算。现实,总是对的,如果不对,那就是模型错了,或者测量错了。所以,实践是检验真理的唯一标准。在这个意义上,连人的主观感受都是实践的,而不是主观的。
自1500年前后,培根创建实验科学,科学和技术才有机会历次工业革命中起到至关重要的作用。
为了保证所测量的恰好是模型关心的变量,无论自变量和函数值,实验技术都有一系列的措施,在一定的条件下实施。要孤立条件,减少意外干扰,尽可能排除错误归因。比如设计最小系统,比如每次只检测一个变量。自然科学和技术不能接受用“复杂系统”这样的名词把问题拉到虚无主义去,给出模棱两可的答案。这些都是没有用的,不符合工程技术的初衷。
关于如何设计实验,提高动手能力,推荐扩展阅读这本书《Netware系统故障诊断与排除
》。东北师大图书馆有纸件。这本书涉及的技术有点古老,199X年,但是实验设计的思路非常清晰,并且至今通用。
有很多因素需要剔除,才能确保模型正确的反应了现实的因果。剔除这些因素本身也是工程问题。包括如果伦理学不允许设计实验环境,比如人的性格到底有多大比例是遗传的,不能够特意组合生一堆孩子测量。这种情况下,可以单纯地观测既有发生的事实,比如孪生兄弟姐妹在不同的家庭中成长的情况。再例如,如果需要观测的指标包括人的主观部分,比如疼痛,比如感冒吃药以后痊愈的速度,需要避免人的主观因素被错误归因到模型的因果链里,要采用双盲实验。即无论医生还是病人,都不知道所采用的药物是被测量被检验的还是安慰剂对比组,避免皮格马利翁效应等心理因素干扰结论。
如果我们自己不严格检查自己的模型,以为能侥幸逃掉,会受到自然法则的惩罚,也可能会受到同行友商的惩罚。友商会在你展示产品的时候跳出来说,你的模型检测方法有缺陷,他们的模型和产品更好。与其那个时候被怼,不如自己内部先充分检查和揭示缺陷。
这样,具备了包括不限于这些工程师的基本素养,才能完成工程师的使命,为人民服务。
感谢各位同学。
如有任何疑问、质疑、指教,烦请电子邮件 [email protected]。
感谢通过讨论为我带来的进步。