前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >架构设计考古:Bob大叔的整洁之道

架构设计考古:Bob大叔的整洁之道

作者头像
用户1682855
发布2018-10-22 14:31:35
1.2K0
发布2018-10-22 14:31:35
举报
文章被收录于专栏:前沿技墅前沿技墅

本文作者 Robert C. Martin

The Clean Coder、Clean Code等名著作者Bob大叔,从1970年起编程至今。他是cleancoders.com和UncleBob Consulting LLC的创始人,8th Light, Inc.的“首席匠人”,曾任C++ Report主编及敏捷联盟(Agile Aliance)首任主席。

自1964年,12岁的我写下了人生的第一行代码算起,到2016年,我已经编程超过50年。我实际构建过大大小小的软件系统。我写过小型的嵌入式系统,也构造过大型的批处理系统;我构建过实时控制系统,也构建过Web网页系统;我写过命令行程序、图形界面程序、进程管理程序、游戏、计费系统、通信系统、设计工具、画图工具等。

我写过单线程程序,也写过多线程程序;我写过由几个重型进程组成的应用,也写过由大量轻型进程组成的应用;我写过跨多个处理器的应用,还有数据库类、数值计算类和几何计算类应用,以及很多很多其他类型的应用。

回首过去,经历了这么多应用和系统的构建过程,我最意外的领悟是:

软件架构的规则是相同的!

我知道,你也一定会对这个结论感到吃惊。为此,我要回顾一下自己从1970年到现在所经历过的几个比较有特点的项目,现在就让我们一起来看其中的一个项目,故事发生在20世纪70年代。

4-TEL维护中心计算机(SAC)是基于M365迷你计算机开发的。这个系统与所有外地部署的COLT进行通信,通过专线或者拨号线路。该系统会命令这些COLT计算机测量每条电话线的状况,接收原始数据,进行一系列复杂分析从而识别和定位问题。

工单分派

这个系统工作的一个核心原则是保证修理工资源的合理利用。根据工会规则,修理工分为三个类别:中央办公室修理工、线路、客户修理工。中央办公室修理工只能维修中央办公室内部的线路问题,线路修理工负责维修中央办公室与客户之间的线缆问题,而客户修理工负责修理客户现场内部与线缆末端连接的问题。

当收到客户投诉时,我们这套系统可以远程分析问题,以决定派遣哪种类型的修理工。这样可以避免派错修理工而无法解决客户问题,造成浪费和延迟,更节省了电话服务公司大量的金钱。

负责决策派遣规则的这段代码是由一个非常聪明,但是非常不善沟通的人设计和实现的。传言这段代码的构建过程是这样的:“他花了三个星期盯着天花板构思,然后用两天时间拼尽全力写成了这段代码——接下来他就离职了。”

没有人理解这段代码。每次我们尝试加一段新功能,或者修复一个问题的时候,都会引入新的问题。由于这段代码事关整个系统存在的核心意义,每个新的问题都让公司上下蒙羞。

最终,管理层要求我们将这段代码封闭起来,不允许再次修改了。这段代码已经正式固化了。

这段经历让我从此以后对代码的整洁性深感重视。

系统架构

这个系统是在1976年用M365汇编语言编写的。作为一个单体程序,它差不多有6万行代码。操作系统是一个我们自己开发的、非抢占式的、依赖轮询的任务切换器。我们将其称为MPS,即并行处理系统。M365计算机没有预置堆栈,所以任务相关的变量都需要在一个特定内存区域中存储,每次上下文切换时会换入换出。共享变量用锁和信号量来管理。代码重入与竞争问题是很常见的。

当时,系统中没有对设备控制逻辑、UI逻辑与业务逻辑代码之间的隔离。例如,调制解调器控制代码交织在业务逻辑与UI代码中间。没有任何模块化或者接口化的工作,调制解调器都是通过散落在各处的代码在比特层面直接控制的。

终端UI 相关代码也类似。消息和格式化代码也没有隔离,散落在6 万行代码中的各处。

我们当时使用的调制解调器硬件模块是设计为挂载在PC电路板上的。我们从第三方公司购买了这些模块,与其他的电路一起集成到我们自己设计的背板上。这些设备相当昂贵。几年过后,我们决定设计自己的调制解调器模块。我们软件组苦苦哀求硬件设计师,在设计新调制解调器时,一定要与老的组件采用同样的控制接口,一直到位级别。我们反复解释,控制代码散落在整个代码库的各处会导致难以修改,而且我们的系统未来还要同时处理两种不同的调制解调器。所以,我们反复不停地强调和哀求:“请一定要和原来的调制解调器采用同样的软件控制接口。”

然而,当我们实际拿到新的调制解调器时,控制结构是和以前完全不同的。不仅仅是有所区别,而是完全、彻底不一样。

谢谢啊,硬件工程师!

我们怎么办?这可不是仅仅将老的调制解调器替换为新的调制解调器,而是要混合部署到系统中。软件必须能够同时处理两种不同的调制解调器。我们是不是要在所有设备的代码中都增加各种特殊情况判断呢?这样的地方有几百个!

最终,我们采用了一个更糟糕的办法。

程序中有一个特定的子程序是用来向串口通信总线写入控制数据的,其中包括与调制解调器的通信。我们修改了这段代码,让它主动识别与老的调制解调器通信时候的字节位特征,同时将其转换为与新的调制解调器通信的代码。

过程相当复杂!向调制解调器发送命令的时候,需要向不同的IO地址发送不同的数据,我们的这段黑科技代码还要解析这些数据,然后按照原始顺序,将它们以完全不同的格式和不同的延时发往不同的IO地址。

最终这段代码还是正常工作了,但是这段程序真的是黑到不能再黑的黑科技。经历了这次事件之后,我深深懂得了将硬件代码与业务逻辑代码隔离——使用抽象层的重要意义。

大型重写

随着20世纪80年代的到来,生产自己的迷你计算机和设计自己的计算机架构逐渐失去了吸引力。市面上有很多迷你计算机可供选择,整合它们要比自己根据20世纪60年代的私有计算机体系架构来设计和实现更符合标准和省钱。另外,基于SAC 软件糟糕的架构设计情况,我们的技术管理部门开始推动SAC系统的一次架构重新设计。

新系统计划采用存储在硬盘上的UNIX操作系统,用C语言编写,运行在8086微型计算机体系上。我们的硬件团队开始设计实现硬件平台,同时一小部分软件开发者组成了“虎之队”,负责重写软件部分。

我就不在这讲中间发生的许多故事了。简单来说,第一个“虎之队”在消耗掉2人年到3人年的成本之后,没有能够交付任何东西。

一年或者两年之后,可能在1982年左右,整个过程又启动了一次。这次的目标是重用C语言和UNIX,在我们自己新设计的、非常强大的80286硬件上,将SAC整体重写。我们将这台计算机称为“深思者”。

这项工程耗费了几年时间,然后又延迟几年。我不知道第一套基于UNIX 的系统是何时部署的,我认为直到我离开公司的1988年,也没有部署成功。可能这套系统最终也没有部署成功。

为什么项目总是延期?简单来说,对一个重新设计的团队来说,想要和一大群积极维护旧系统的团队保持一致是非常困难的。下面是他们遇到的其中一个困难的情况。

欧洲

在用C语言重新设计SAC项目启动的差不多同一时期,公司开始向欧洲进军。当然,不可能等待新的软件系统设计完成,所以很自然,基于老的M365的系统被用来在欧洲部署。

问题是,欧洲电话系统与美国电话系统非常不同,不仅如此,人员分工与管理结构也是完全不一样的。所以我们当中的一个最好的软件开发人员被派遣到了英国,在当地带领一个软件开发团队解决欧洲的问题。

当然,没有人认为能把这些修改集成到美国使用的版本中,别忘了,当时可没有可以跨大洋传递大量代码的网络基础。英国开发团队简单地将US代码复制了一份,根据需要自己修改了。

当然,这样造成了其他困难。大洋两侧的代码发现了同样的Bug,需要在两地各自修复。但是由于模块在两地系统中已经被修改得面目全非,很难保证美国一侧的修改可以在英国系统中正常运行。

经过几年的折磨之后,同时也伴随着一条连接美国和英国办公室的高带宽网络线路的开通,我们开始了第一次整合两个分支的尝试,目标是将两套系统的功能区分变为配置文件的区分。这项工作第一次尝试失败了,第二次尝试又失败了,接下来是第三次尝试。两套代码,虽然十分相似,但是细节部分区别实在太多,无法简单整合——尤其是在当时市场多变,两地都在不停修改的情况下。

同时,“虎之队”在尝试用C语言和UNIX来重写这套系统时,也意识到了这个重新设计需要同时处理欧洲和美国两地的情况,当然,这只会让其进度更缓慢。

关于这套系统我还有很多故事可以讲,但是这实在是太让人郁闷了。简单来说,我软件研发生涯中的大部分教训都来自维护这套可怕的SAC汇编代码的经历。

————

本文节选自经典著作《架构整洁之道》附录部分。Clean Architecture问世以来好评如潮,抢鲜拜读英文版本的读者无不将其列入年度最佳书单。其穿越架构变迁的洞见,让几经浮沉的资深架构师深深折服,也让奋战一线的开发工程师提前警醒,更让临阵备战的架构初学者得窥门道。阅读原文已经开启智慧之门,点击方知不虚此行!

  • 内容简介:《架构整洁之道》是创造“Clean神话”的Bob大叔在架构领域的登峰之作,围绕“架构整洁”这一重要导向,系统地剖析其缘起、内涵及应用场景,涵盖软件研发完整过程及所有核心架构模式。本书分为6部分,第1部分纲领性地提出软件架构设计的终极目标,描述软件架构设计的重点与模式;第2~4部分从软件开发中三个基础编程范式的定义和特征出发,进一步描述函数、组件、服务设计与实现的定律,以及它们是如何有效构建软件系统的整体架构的;第5部分从整洁架构的定义开始,详细阐述软件架构设计过程中涉及的方方面面,包括划分内部组件边界、应用常见设计模式、避开错误、降低成本、处理特殊情况等,并以实战案例将内容有机整合起来;第6部分讲述具体实现细节;附录则透过作者数十年的软件从业经历再次印证本书的观点。对于每一位软件研发从业人员——无论从事的是具体编码实现、架构设计,还是软件研发管理,本书都是不可或缺的。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-09-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前沿技墅 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 4-TEL维护中心计算机(SAC)是基于M365迷你计算机开发的。这个系统与所有外地部署的COLT进行通信,通过专线或者拨号线路。该系统会命令这些COLT计算机测量每条电话线的状况,接收原始数据,进行一系列复杂分析从而识别和定位问题。
    • 工单分派
      • 系统架构
        • 大型重写
          • 欧洲
            • 关于这套系统我还有很多故事可以讲,但是这实在是太让人郁闷了。简单来说,我软件研发生涯中的大部分教训都来自维护这套可怕的SAC汇编代码的经历。
            • 本文节选自经典著作《架构整洁之道》附录部分。Clean Architecture问世以来好评如潮,抢鲜拜读英文版本的读者无不将其列入年度最佳书单。其穿越架构变迁的洞见,让几经浮沉的资深架构师深深折服,也让奋战一线的开发工程师提前警醒,更让临阵备战的架构初学者得窥门道。阅读原文已经开启智慧之门,点击方知不虚此行!
            相关产品与服务
            数据库
            云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档