
“星际大战”,Tatu组和Ctrl-Alt-Del组合与旧版代码有什么关系? 当您进入大型项目并遇到难以理解的旧代码时该怎么办? 向当局传达消除技术债务的劳动成本正在得到回报的效率如何提高?
Dylan Beatty的报告并非没有笑话,但是这些笑话伴随着对主要开发问题的认真讨论。 这非常适合会议结束:当听众已经听了很多硬核并且不能再看代码幻灯片时,该是时候提出更一般性的问题和精彩演讲的时候了。 当Dylan关于Legacy代码的演讲结束了我们的DotNext 2018 Moscow .NET会议时,观众最喜欢它。
因此,现在为哈勃(Habr),我们翻译了该演讲的文本:供捐助者和其他所有人使用。 除文字外,剪辑下方还有原始的英语视频录像。
您好,我叫Dylan Beatty。 对话的主题与我非常接近,对我来说,这对参与软件开发的每个人都非常重要:我们将讨论遗留代码。
首先,我会说几句话。 我早在1992年就开始按照行业标准开发网站。 现在,我是伦敦公司SkillsMatter的CTO。 我从今年开始在那里工作,从而继承了代码库:75,000行不是我编写的代码成为我的责任。 我的报告的一部分是基于这种经验。 此外,我是Microsoft MVP,也是伦敦.NET用户组的负责人。

神秘博士,现代星球大战,夏洛克和帕丁顿有什么共同点? 在处理它们时,使用了遗留代码。 我知道这一点,因为我在Spotlight工作了15年。 这是一家位于伦敦的公司,为在电影和电视上表演的专业演员提供在线工具。 由我和我的团队编写的软件被用于所有上述项目以及许多其他项目的工作中。
在新的《星球大战》中,有些人不喜欢演员,另一些人不喜欢情节。 但是没有人从电影院出来时说“我不喜欢经典的ASP用于创作!”
因为没关系。 该代码库已经投入生产很长时间了,是的,有一个经典的ASP代码(比整个.NET都旧),至今仍在电影和电视节目中使用。 必须正确地强调:这些电影和电视节目很重要,并且代码仅用于解决问题。 在运行它之前,代码本身并不意味着任何东西。 价值只有在您启动并用它做事时才会出现。 这就是人们支付的费用-Netflix或DVD。 问题在于,很容易忘记它。
总的来说,今天,我希望与您分享我多年来使用相同代码库的经验。 我观察了它的演变过程,以及其他人如何了解它并学会了如何使用它。 等式的另一面是我的新作品,当我自己不得不结识其他人的代码时,这使我可以从另一面看到相同的过程。
但是首先,让我们讨论一下IT领域正在发生多快的变化。

看看第一台iPhone-今天,它看上去完全古老而笨重。 这个模型只有11年的历史,它于2007年出现,然后售价800美元。 如果您在2007年购买了洗衣机,吉他或自行车,今天您仍然可以使用它们。 但是第一部iPhone不再可用-即使您设法用电池和充电器找到副本,所有使智能手机如此出色的设备都无法在其中使用。
您将无法打开地图,因为地图服务器不再存在。 您将无法进入Twitter,因为最新版本的Twitter应用程序需要无法在iPhone 1上安装的iOS版本。Twitter客户端将简单地答复您:“找不到端点”。 本质上,您将拥有化石。 而且唯一可以使用的是普通电话的功能,您仍然可以拨打它。 因为在这一领域,与IT不同,11年的标准没有改变。
让我们花点时间旅行。 还记得这个吗?
你还记得那一年吗? Tatu在2003年的欧洲歌唱大赛中演出。 2003年,我编写了ASP代码,该代码现在仍在生产中使用。
在我们看来,这是很久以前的事了,但是这段代码仍然有效。 手机制造商设法使人们每两年购买一部新手机,因此他们有能力摆脱旧的开发,禁用API,端点和服务。 但是许多公司没有这样的机会,因此他们继续支持Tatu在Eurovision执行时编写的代码。 该代码很重要,因为它仍然执行重要功能,它会产生收益-也就是说,它是一个遗留代码。
尽管我们都同意遗产的存在,但问题仍然存在:这到底是什么? 这是一个示例代码:

看,想一想:这是遗产吗? 你觉得呢
我发明了该设备,我想明年出售。 将其插入USB端口,选择一段代码,设备会告诉您它是否为旧版!

您刚刚看到的代码不是旧版。 它是
四天前由
Andrey Akinshin (
DreamWalker )撰写的。 这
取自 BenchmarkDotNet。
事实是,仅通过查看代码就无法确定代码是否为旧版。 而且,代码本身与它无关。 重要的是他周围发生的事情:人员,文化,流程,测试等。
如果您在英语维基百科上打开文章“旧版代码”,则可以阅读以下内容:“这是与操作系统或任何其他计算机技术有关的源代码,其支持或生产已停止。” 我们就像:“好吧。” 然后写成:“这个术语最初是由乔治·奥利维蒂(George Olivetti)所使用,与管理员本人未编写此代码所支持的代码有关。”

这句话的结尾是某个塞缪尔·穆伦(Samuel Mullen)博客的链接。 我们认为,“有趣,我们将会看到。” 但是,如果打开该
帖子 ,我们将看到此Mullen依次指的是Wikipedia!

而且,似乎没有人知道这个乔治·奥利维蒂是谁。 因此,看起来我们应该寻找更好的定义。
迈克尔·法瑟斯(Michael Faethers)给出了业界最流行的定义之一:“传统就是没有测试的简单代码。” 迈克尔就这一主题写了一
整本书 ,所以他绝对知道他在说什么。 但是,我并不完全同意他的定义。
因此,我使用我的定义已经有好几年了:“继承的代码太可怕了,无法更新,但是删除却太有利可图。”

后来发现,一个独立于我的定义已经非常相似:“一个非常有利可图的代码,我们害怕更改。” 我不知道这种恐惧来自何处。 关于将没有代码的代码转换成遗留代码的测试有什么用?
双重记帐系统是世界上最古老的商业工具之一。 它已有数百年的历史了,在其中,对银行或公司的每笔交易都进行两次计数:在第一栏中,我记下了我付了多少钱,在另一栏中,记下了我为他们所获得的价值。 此外,两列的总和应相等,如果存在差异,则会在某处产生错误。

在我看来,这种方法的基本思想似乎非常重要:我们做出的所有决策都会两次生效,如果您更改一件事情,那么在其他地方您肯定也会看到需要监视的更改。 这种双重方法可以应用于代码和测试,或者应用于代码和监视系统,或者应用于代码和文档。
我们认为很多旧系统也存在两个版本,但这些版本“在代码和头脑中”。 我认为,这是我们的主要困难之一。
我回想起一页
漫画, “这就是为什么您不应该打扰程序员的原因。” 开发人员看了简单的代码行,立即开始思考现在需要在导航菜单中重写什么,这将如何影响调试器,然后需要在代码中进行更改。 有人走过来问他:“你收到我的信了吗?”,然后所有这些复杂的编辑树从我脑海中飞了出来。
当我们工作时,我们进入意识的改变状态,我们的大脑建立了复杂的模型来解释代码是如何工作的。 当代码是由一个人编写的(例如,在启动项目或开放源代码项目中)时,通常除了头中的模型和代码中的模型外,什么都没有。 这使您可以非常快速地工作-您只需将头脑中的内容转换为代码即可。 头部中的模型是正确的,因此,如果代码中有错误,只需查看一下,然后与头部中的内容进行比较,即可立即看到错误。 而且,当您发现错误时,通常这表明您对任何方面都没有足够的思想,因此先在头中更新模型,然后再更新代码。
杰西卡·科尔 ( Jessica Kerr )在一篇精彩的
文章中说,她的发明除其他外还说发明是如何下山的,而分析则是如何上山的。 我们喜欢编写代码,它很有趣而且很容易:您从头开始,发明新东西,解决问题,编写算法,方法和类。 但是阅读代码很困难-从一开始就在您面前摆着很多其他人的代码,这是完全不同的工作。

因此,在许多组织中,您都可以观察到Alberto Brandolini称之为“地下城主”的现象:这是该系统的第一个版本的编写者。 我是Spotlight中的这个人-我只写了第一个版本的重要部分,并且是用经典的ASP编写的,没有文档也没有单元测试。 他们开始使用这种工具制作电影,做了《星球大战》,我们有了钱,一切都很棒。 但是后来我们开始雇用新员工,这些员工起初不知道这是如何工作的,而且两到三个月后,他们必须熟悉该系统。
很快,开始讨论将系统移植到.NET的问题,因为传统的ASP不够可靠且不够快。 这样的对话将永远是-无论您编写什么代码,都会有人坚持要求将其重写。 发生这种情况是因为此人不了解您的代码,并且编写新代码比研究旧代码更有趣。 编程是一项带来乐趣的工作,我们非常喜欢它。 因此,很自然地,我们可以选择一个更令人着迷的选择。
地牢的所有者是一个知道代码中所有陷阱的人。 他知道无法按下的按钮,否则应用程序将崩溃。 这是2014年TODO挂起的那一款,没人能伸手去拿。 我们行业中的人们已经学会了不再创建这样的系统。 这就是为什么我喜欢诸如DotNext,用户组,社区和StackOverflow之类的事件的原因:当您开始一个新项目时,肯定会被告知您需要编写测试,以示例方式进行规范,集成,监视。 因此,我们的未来将是在F#上实现无服务器微服务,并通过测试覆盖100%的代码。
但是问题不是我们必须编写的软件:我们的世界已经充满了软件。 而且,如果您以金字塔的形式想象这个软件,那么无服务器F#将只占据最顶端。 ASP.NET将有更多内容,测试中将以某种方式涵盖。 甚至更多-Windows XP上的Visual Basic。 但是历史上最受欢迎的商业产品开发平台是Excel电子表格。

我敢打赌,每次您购买机票或住宿时,您的名字都会以某种方式出现在某种Excel电子表格中。 通过测试进行的开发并未考虑到已经编写的大量代码。
但是为什么要坚持重写旧代码? 最初,人们不喜欢经典的ASP,他们想在.NET上重写所有内容。 事实证明,您需要重写4.5版,4.6版和.NET Core上的所有内容。 JQuery不好,因此您绝对应该切换到Angular,然后再进行React,然后是Vue。
我怀疑这里至少有一个原因在于追求时尚。 我们彼此交流,并且完成了行业中最高质量的工作的很大一部分,因为作者希望获得认可和尊重其专业人士。 在我看来,在我们的行业中,人们对新事物和新事物都过于沉迷,并且编程语言会顺应时尚潮流。 但是,毕竟,时尚本身的变化并没有发生任何变化,它们的所有优点都保持不变。
想象一下,面前有两张简历:

毫无疑问,对我来说,处理真正重要的问题中哪个对我更好。 但是,如果您与人力资源部门的人员或刚刚完成编程课程的人员交谈,您会发现他们可以从第一个程序员的技能中赚钱,而他们认为第二个程序员的技能已经过时。 但是它们一点也不落伍-这个人可以解决很多问题。
我认为这种态度的原因之一是人们感到害怕。 我的一些同事离开我们的团队是因为他们想开发Angular或NodeJS。 当我问他们为什么需要它时,他们回答说,如果他们仅继续在.NET上工作,那么两年后他们将找不到工作。 我回答他们:伙计们,我们和.NET一起帮助制作了《星球大战》! 他们说:是的,但是仍然不是Angular。
不要误会我的意思,我尊重他们的决定。 谈不上任何腐败,只有人们担心自己的前途和家人的前途,如果他们不得不找工作。 在我们的行业中,通常会以每年需要从头开始学习所有内容的意义来解释此安全问题,否则您将失去竞争力。 通常,与解决问题的能力相比,我们对技术本身更感兴趣。
在我看来,除了害怕落伍和过时之外,恐惧在改变您不了解的系统中也起着重要的作用。 他们为您提供了一个您一无所知的代码,但是如果其中有任何问题,这是您的责任,并且如果代码出现在深夜,他们将唤醒您。 因此,恐惧就出现了。

我们从同一个《星球大战》中知道,恐惧导致愤怒,愤怒导致仇恨,仇恨导致痛苦,痛苦导致JavaScript。 我们如何应对恐惧和同事的恐惧? 我认为主要有三个方面:
理解 ,
信任和
控制 。
信任是三者中最简单也是最困难的。 我信任这台笔记本电脑,因为它在演示过程中从未崩溃过。 一旦发生这种情况,我对他的信心就会消失。 用英语有句谚语:“信任是一滴一滴赢得的,但是却是一桶钱。” 与一个人工作一个月后,您将准备承认他可能精通他的业务,其中两个人会说他很精通,三个人会同意他非常了解他的业务。 在三个月零一天之后,他的代码中将显示出对SQL注入的漏洞,您会说:“啊,我一直说他没有用”。
信任他人总是很困难,因为这总是意味着要放弃一定程度的控制权。 对代码的信心也是一个重要的话题。 在使用该系统一段时间后,您想相信它会按照您的期望工作。 您的操作系统稳定可靠,并且希望它们不会崩溃。 您信任信息数据库,并希望它们不会丢失。 您希望云提供商可以确保您的站点连续运行,并且不会在黑市上出售客户的信息。
没有获得信任的快速方法。 确实,信任是传递性的:如果我信任您,而您又信任其他人,那么我很可能也可以信任此人。 如果我听取您的意见,并且您认为您可以信任Amazon,AWS,Azure或Google App Engine,那么我将随时相信这些都是不错的服务。 但是没有快速的方法来获得信任。
让我们继续
了解 。 在大学里,我学习了计算机科学三年。 如果土木工程师遵循我们教育的基本原则,那么他们将在第一年建造木棚,第二年建造金属棚,第三年建造高级玻璃棚。

第一年,我们用Lisp编写了小型程序,第二年-用Java编写了小型程序,第三年-Scheme和Prolog编写了小型程序。 我们没有编写大型程序,更重要的是,没有尝试找出它们。
但是土木工程师并没有以棚屋为例来学习,他们被迫了解像我们现在这样的摩天大楼,桥梁,爱乐社团和建筑物。 这些学生从行业中最大,最令人印象深刻的项目中学习。 而且,如果他们按照与教授计算机科学相同的原则进行学习,那么面对面对摩天大楼的真实订单的那名学生,除了在双子塔耸立起来之前,将棚子彼此叠置之外,别无其他。

正是在这种情况下,完成计算机科学课程的学生找到了自己,并被赋予编写分布式商业采购系统的任务。 现有软件的很大一部分是以大致相同的方式编写的。 编写它的人不是不负责任的,只是没有经验。 他们在大学所做的一切都做得很好,这造成了虚假的自信心。 那正是我一次的样子,而且我敢肯定,你们中的许多人一次都是一样的。 我们的行为如下:我们写一个网页,链接到另一个页面,然后链接到另一个页面,复制代码,每个人都会很高兴-我们的客户有产品,我们的公司有钱,我们有花红。 五年后,您看着这个噩梦,思考:这怎么写?
问题的一部分是学习软件的能力。 土木工程师善于研究建筑物,飞机工程师善于学习飞机。 以文学为例:在《战争与和平》中可能有4.5万行(取决于出版物)。 这是世界上最大的书籍之一,需要从事文学批评的人们认真研究。 换句话说,研究如此大的对象是一项工作。 莎士比亚最长的戏剧《哈姆雷特》的大小为6000行。 现在想想:Linux内核的长度是《战争与和平》的三倍。 我们谈论的是一个非常紧凑的代码,井井有条,带有大量的文档和庞大的社区。 然而,了解它就像必须三遍了解“战争与和平”。

看一下这张图,它显示了《哈姆雷特》,《白鲸》,《迪克兄弟》,《卡拉玛佐夫兄弟》,《指环王》,《阿特拉斯耸了耸肩》,《战争与和平》以及Linux和Mono内核中的行数。 。
这个比例对您来说现实吗? 请原谅我误导您。 该图实际上是指数的。
下一张幻灯片上的折线图:

这里的想法非常简单:软件庞大,坐下来阅读是不可能的。 让某人熟悉Linux内核,就像让某人连续阅读《战争与和平》,《阿特拉斯耸耸肩》,《指环王》和所有《哈利波特》一样。 想象一下,您来到一家新公司,他们从门槛告诉您您需要学习所有这些书籍,然后才被允许使用代码。 当然不是。
阅读代码可能非常有用-您可以了解某些模式的工作原理并学习一些示例。 但是,如果您以读书的方式来阅读大型系统,那么您将无法解决。 在我看来,这种方法也许有些高尚,但它不会导致任何事情。 代码太多了,而且写得比这些书还要差。
如果仅阅读代码效率低下,那么如何正确学习它? 回想一下诺贝尔物理学奖获得者Richard Feynman。 对他来说,科学教学的问题非常重要。 他认为,有必要教人而不是科学,而是要教人如何正确地科学。 他之所以受邀进入巴西圣保罗大学,是因为在巴西,学生的成绩很高,但同时无法建立高科技产品。 费曼被要求帮助找出问题所在。
几年来,他每年都来巴西呆几个星期,并与学生交谈。 他发现巴西学生非常了解,例如,对晶体施加压力时发生的现象的名称-三聚体发光。 但是他们都不知道,如果您在黑暗的房间里用钳子将一块糖压碎,就会看到火花滑过-这就是三聚体发光。 Feynman解释说,学生仅接受过教科书的培训,才能通过考试,但他们没有进行任何实验。
我认为,这对我们行业来说是一个重要的教训。 , . , , , . , .
—
. , , , .
—
. , , . , , - .
. ,
.
.
, , .

, — , , . , , - , ? .
- , , - . .

- «I love LAMP», , , . — , , , . : , , , .
, , , . , . , DLL. , , . , — , . , , — .
— ? ? -, « - ». , , . , , . , , Wi-Fi. Wi-Fi , , , . : , , — ? 依此类推。
, , . , , , .

, . , , DLL api.payments.mycompany.com. DLL, , , , , DLL , .
: .
,
: , . . , : , .
. , , . , , . : , , , . , - , . .
Spotlight, ASP Amazon Web Services. , GitHub - « ». , , , , .
- , , . Windows 2016 , ASP, 2003 .

, , , «» , « » Windows 2016 , . ASP.NET MVC 2 , , 3, 4. DLL, , ASP.NET MVC 2, - - microsoft.com, , , Nuget , . Program Files. ASP.NET MVC 2, , .
, . , , - . , : , -?

: , , -?

, , , , . - — -, , . — . , !
, , , - — , .
, . 50 000 , . — 100 000, 200 000… , Int32. , , - id -. , - , , , int, .
, , , . — . , , , .

, , . , , 32 64, . , , . . , , , . , , . , , , .
, 80- 90-, -, , . , . , .

. , — , . , , , , . , .
, . , , . , , . , — « » . , , , . : «, - ?»
, - — , . , , . , ; , — , . . , , . , .

, . , , . , . , . , , , , — , 12 , , , 3 .
, , , . , . , , .
, — ? «definition of done»?
, , GitHub , , , .

, . , . Google Analytics , , . . - , . «», , . — , . , JavaScript, . , .
, , — , . — , 20 . — , .
: , . , . , . GitHub, . - , .
: , .
-. , , , , , , , COBOL. MUMPS? , . , 1960- , 26 . — . , , - .
- , « -» « ». .

:
(control), (alter) (delete) - .
.
, : DotNext 15-16 . .NET- ( -10 ), — , .NET Foundation. , — .