[导读]以下为译文: 重写代码消耗了12个月! 我们从头开始重写代码浪费的时间。 你能想象在软件行业,12个月的时间没有任何新产品推出,没有任何新版本更新吗? 真的,我不由自主地问自己这个问题: 在这个快速发展的世界里,12月的时间能让我们做多少事情? “2015
以下为译文:
你能想象在软件行业,12个月的时间没有任何新产品推出,没有任何新版本更新吗?
在这个快速发展的世界里,12月的时间能让我们做多少事情?
“2015年1月20日,星期二,下午5:10,AntiMalware软件终于进入了第一次公测。”
经过几十个小时的不眠不休后,第一个版本的软件说明书终于发布到了网站上,这标志着我们的新旅程的开始。
我在一家为企业和终端用户提供安全软件的小型网络安全公司工作。我们开发的软件保护用户免受恶意软件的侵害。如果用户的电脑被恶意软件感染,我们的软件会帮助他们清理。AntiMalware就是其中一个软件。
第一个测试版收到的反馈令人鼓舞。我们有四个开发人员为这个产品工作,不断地修复Bug, 改进产品功能,推出新版本。
经过两个月的纠错、功能改进和编码工作,我们发布了AntiMalware的第一个稳定版本。
大多数用户的反馈都很好,他们喜欢这个产品。这让我们的团队深受鼓舞,大家卯足了劲地干活,来改进这个产品的核心功能。
AntiMalware软件处于它的最佳期,它成为了我们的旗舰产品。用户纷纷把它推荐给他们的朋友们。所有与安全相关的博客和论坛也都在推荐这个软件。它成了拯救被恶意软件感染的用户的首选软件。
下载、安装、销售,一切都向好的方向发展,用户群在几个月内迅速增长。创始人很高兴,团队也是如此。大家都在想:“我们做到了!像其他大公司一样,我们认为我们创造了自己的成功故事。“
后来,公司决定进入企业市场。一个新的企业产品团队成立了。原产品负责人离开了公司,我们的CTO接任成为新的产品负责人(这是灾难的开始,稍后我会解释)。
一些开发人员离开了公司,但没有什么影响。我们把每件事情处理得很好,AntiMalware软件仍然是市场上最好的选择。
正如我前面所说,我们的CTO成了AntiMalware的产品负责人,他需要处理AntiMalware的方方面面。而且他还是该软件的首席开发人员,负责不间断地发布更新和功能提升。同时,他的职位让他还需要处理公司的其他事务。
当然,一开始都很顺利,我们的情况就像所有软件开发一样,我们不间断地维护和改进我们的软件。
正如我们应该预料到的(显然我们没有),不知何故,软件开发过程开始慢下来。
新的版本更新开始延期了,这种情况持续了一阵子,很快就变成没有版本更新了。这让我很不安,有一天我问CTO:
“这个产品出了什么问题?为什么版本更新要花费那么多时间而且开发进展缓慢?”
“我们的代码太复杂,它的结构不好,耦合太紧。架构设计完全错误,用户界面和核心逻辑代码混杂在一起,每当修复一个Bug或作某些改变时,其他部分就会受影响。即使是小的改变也很难做好。每次更新,都会引起新的问题。
一些方法竟然有20个参数,方法体的代码有两页长!你能想象吗?有许多不应该实现的东西不知为何都实现了。
这就是为什么每次更新都要花费很长时间而我们无法推出新功能的原因。每次我们推出一个新版本,我都担心可能会引入新的Bug,而那些现在工作得很好的核心功能则有可能因此无法工作。在这种情况下,发布新版本太冒险了,我们可能会失去我们的用户,我们的软件无人再愿意使用。”
他的回答中提到的一系列问题其实我们都知道。只是,我们期望从他的口中说出来。
我还问了一个问题。负责这个软件的前任首席开发人员为这个软件开发了一年时间,而他都在CTO的管理下,那么CTO为什么允许这样混乱的代码出来呢?
“我不想打击他的积极性,我们必须尽快进入反恶意软件市场,他很擅长这个,所以我才没有制止他这样做。”
也就是说,为了以最快的速度进入市场,我们牺牲了代码质量,这样做也等于破坏了这个产品的未来。
要在第一时间对不好的代码设计说“不”,不要让“面条式代码”毁了你的产品的未来。要确保做出的软件产品有可持续开发性。
“我们都是程序员,而程序员的心中都驻着个建筑师,当他们到达一个地方的时候,他们想做的第一件事就是把这个地方夷为平地,然后在上面建造一些宏伟的建筑。我们对那些渐进式的更新不感兴趣:如小修小补、改进、种种花草等等。”
- Joel Spolsky,Stackoverflow公司CEO
开发人员总是倾向于抛弃旧代码然后从头开始,他们有这样做的理由。因为他们认为旧代码都是无用而且凌乱的。但是这只是想当然的理由。当我们试图找出背后的真正原因时,我们会发现:
旧代码对我们来说可能看起来很凌乱,必须从头重写的原因并不是因为代码本身,而是因为一个重要的,基本的编程法则:
这解释了代码重用困难的原因,也解释了为什么我们认为旧代码象头发一样凌乱。因为这个原因,当我们阅读另一个开发人员的代码时,我们的潜意识会不断对着我们耳语“扔掉它,重新开始”。
像所有开发人员一样,我们也落入了这个陷阱。只是读一遍我们的凌乱的代码就足够让我们下决心考虑从头重写了。
在一系列的会议之后,即使CTO对重写代码有抵触(他是对的),他最终还是被说服了,我们决定从头重写代码。
那是一个周末,星期日,我边喝早茶边读一些推送文章。就像我的推送知道该向我展示什么一样,我读到了那篇最著名的关于重写代码的文章,就是Joel Spolsky写的Netscape 的代码重写故事(https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/)。
读完那篇文章后,我立马分享给了AntiMalware开发团队,包括CTO。
本来说服CTO作出代码重写的决定就已经很难了。他在读完那篇文章后马上改变了主意,他决定中止代码重写。这让其他团队成员生气了,他们冲我大喊大叫:
“你为什么给他看那篇文章?我们都已经说服他了。这个产品必须从头重写,这是唯一的解决方案。”
我们的第一次重写代码的尝试到此结束了。关于这个话题的讨论也终止了。我们的CTO相信我们可以管理好这个糟糕的代码,并有能力在它之上发布新版本,直到严酷的现实击倒我们为止。
每天,我们都得面对这些来自用户的负面评论。作为一家小公司,我们需要管理的产品太多了,而且,我们又进入了企业市场,这些加在一起,使得我们陷入了这样的困境。
把所有这些结合起来,你就会得出这样的结论:我们忘记了我们的用户。
回想一下,我们不想发布新的版本,因为我们不想失去用户。
但事实应该是相反的:如果我们不发布新的更新,我们肯定会失去用户,而我们已经一年半没有给他们任何新版本了。
在被现实打了一巴掌之后,我们决定回头。对我们来说,除了重写代码别无它途。我们做到了。
“2018年12月17日,星期一,21:40。测试的电子邮件准备好了,即将发送给我们的内部测试组。”
经过12个月筋疲力尽的工作,代码重写终于完工。我们准备了第一个测试版本说明,就像上次这个产品面市的第一天一样。
这个产品的重写版本仍处于测试阶段。测试已经快一个月了。我们正在修复错误,倾听用户的意见,审查用户反馈……一切就像4年前一样……
但是在这12个漫长的月中,我们错过了什么呢?如果不是重写,我们会做出什么新产品?!
许多问题可以在这里提出来。但我知道我们只有重写一条路,我们看不到任何其他的解决方案。
如果你也落入了这个陷阱,开始思考“我是否应该从头开始重写代码”,那么在开始代码重写的第一步之前,就考虑自己提问下面的问题,每个开发人员都应该问问自己:
这个问题很重要!请诚实地回答:你真的准备好抛弃所有的知识,所有收集到的错误和修复,年复一年的编码结果吗?抛弃旧代码并从头开始,真的是你所期望的吗?当你从这个角度来审视代码重写的决定,你会发觉很痛苦,不是吗?所有那些试图修补bug的不眠之夜都会在你眼前闪过。相信我,因为我有切身体会。
你必须和很多用户交谈才能找到导致你的软件不能正常工作的问题所在,然后你要在你的软件中定位这个错误,重现这个问题,然后找到解决方法,然后……等等。
这点很重要:当你从头开始的时候,没有人能保证你会比第一次做的更好。
因为你选择抛弃关于这个软件的所有知识和已经收集的错误和修复,所以同样的错误很可能再次出现在你的新代码里。
可能代码重写团队已经不是第一个版本的开发团队。所以你实际上没有“更多的经验”。你会犯下旧版本中的大部分的的错误,并带来一些新错误,而这些新错误在旧版本中并不存在。
如果你没有很好地计划重写工作,你可能面临新版本比原始版本更糟的风险。然而,既然作出了重写的决定,你就要承担这个风险,这个风险可能导致你失去你的客户。
你准备好将几个月/几年的时间优势拱手送给你的竞争对手吗?
代码重写牵扯到大量的精力、计划和准备工作。你必须把每项任务计划好,然而一个接一个地冲刺。你必须确切地知道完成这个痛苦的过程的最后期限。没人知道你会不会错过这个最后期限。有很大的可能你不能准时完成这个过程。
你不得不在数月或数年时间内只能交付旧版本给用户,这将置你于极其危险的境地。你完全无法进行任何战略改变或对市场所需的新功能作出反应,因为你没有任何新代码可以交付。
你的客户可能会抛弃你,因为你除了不断地提供一成不变地旧版本外,无法给他们任何新的东西。
从头开始重写一个系统,本质上就是承认作为一个设计师的失败。它其实是在声明,“我们未能设计一个可维护的系统,因此必须重新从头开始。”
——摘自 Max Kanat-Alexander的 Code Simplicity
像其他设计师一样,我们承认我们未能设计好我们的软件,我们从这个精疲力尽的过程中学到了很多东西。在这里,我分享一些我们从中获得的经验教训。
代码重写是开发人员的一种错觉,大多数情况下它不是解决方案。
当你的代码遇到问题时,准确地诊断问题很重要。像每个开发人员一样,你最初的想法不应该是代码重写。代码重写只是一种错觉。因为你在阅读别人的代码的时候,你会认为如果你从头重写代码,你能做得更好。在这种情况下,请始终牢记那个重要的,基本的编程法则。
有针对性的重写对于处理代码库中最严重的错误很有用。如果可以限制范围并解决大部分问题,就不要进行整体重写。例如,软件的加载速度非常慢。但这只影响到项目的一小部分。通过小心地移动代码、重构和更改接口,这个问题可以一次性解决。你不必重写所有代码。
代码重写是一条比预期耗时更长、更困难、更容易失败的路。
告诉大家一个开发人员通常在错过最后期限后才意识到的事实:一切都比想象的要花更长的时间。代码重写成本的估计通常很悲观,然而实际的成本几乎总是比你想象的更高,花费的时间也更长。因为总是会有想不到的复杂问题要解决,这些都会使重写过程变得更加困难和痛苦。最后,你很可能不得不接受失败的结果。
确保重写后的产品能够更好地解决用户的问题,至少相同,不能接受更差。
重写对用户没有直接的影响/好处。因为用户不关心代码,他们只想解决自己的问题,仅此而已。在用户看来,能够解决他们问题的产品就是好产品。否则,他们不会用它。用户不关心你的代码重写决定,所以重写后版本必须至少和旧版本一样有效地解决他们的问题。
在我们的案例中,我们有一年的时间没有向用户提供任何软件更新。这对于我们今天生活的世界来说是太长了。尽管我们的产品依然足够优秀,但是没有更新用户肯定会抱怨。当程序员重写代码时,永远不要停止维护当前正在使用的系统。在重写过程中,旧的代码仍然需要维护,小的更新和错误修复需要及时提供给用户。否则,你将面临失去用户的风险。
确保定期向用户展示最新进展,以便他们能够帮助你捕获最严重的错误。尽快与用户见面是很重要的。他们的反馈将帮助您根据他们的需求设计新产品。不要实现任何不必要的功能,这将避免你的代码库过于复杂化。
一个产品团队不仅仅包括编程队伍,营销、支持、编程、设计……所有团队需要协力工作。通过定期汇报重写进展情况来确保整个团队步调一致。
在我们的案例中,我们遇到了很多这样的问题。例如,营销团队准备产品测试活动时,他们必须准确了解产品方面的情况,以便让客户为即将到来的产品改变做好准备。但是,有时我们在没有通知他们的情况下做了一些更改。这害得他们必须从头开始准备他们的测试活动。记住:不要浪费任何人的时间。
了解你的产品的弱项和强项,这一点很重要。切记不要改变产品的强项,也即用户喜爱的方面。如果用户对用户界面满意,不要对用户界面作大改动。只做最小的更改和小的用户体验改进。当您用重写后的版本替换现有版本时,确保你的用户不会被新的巨大变化所困扰。有许多情况用户放弃了新版本,因为他们找不到以前版本提供的相同的功能。不要让同样的事情发生在你身上。
在我们的案例中,CTO是负责开发我们软件的首席开发人员。由于他的立场,我们的产品开发进展缓慢。即使是很小的变化也需要几个星期,有时甚至几个月。我想表达的关键点是保持一直更新,永远不要停止。
当您确认新版本已经准备好,开始用新版本替换旧版本时。要一步一步,循序渐进。
首先,从一个小型的内部测试组开始,将您的产品发送到该组。收集他们的反馈和崩溃报告,修复错误,迭代新版本,然后重复这个过程,直到你确认你的产品已经准备好公开测试。
进入公开测试后,用户的反馈是你最期待的。你的第一个目标应该是确保您的产品能够解决用户的问题。当你确认新版本提供的功能与旧版本相同或者更好时,就可以进行更换了。这时候开始为新用户发布新版本,并将现有用户迁移到新版本。
以上这些都是我从代码重写过程中吸取的关键经验教训。代码重写几乎永远都不应该是解决方案,重构才是更好的选择。强烈建议采用代码重构循序渐进解决问题。这样做的风险更低,客户也更满意。
然而,有时候重写代码也是合适的解决方案。下面我我列出了重写代码的几种情形:
当一种语言变得如此古老,导致你很难找到开发人员,或者必须花大价钱才能找到时。
如何确认你的代码变得不可维护呢?这个很难,但是如果你发现即使是很小的更改也很难实现,或者新的更新比正常需要花费的时间多得多,或者任何新的更改都会影响到软件的其他部分并导致新的错误,那么你可以确认你的代码变得不可维护了。
重写代码的时候,永远不要停止维护当前正在使用的系统。只要系统在使用中,必须始终对其提供维护。记住,你的个人注意力也是一种必须考虑的资源,如果你打算同时为新系统和旧系统做设计工作,你要考虑是否每天有足够的时间。
这不应该出现在重写代码的原因列表中。因为你可以随时在团队中调配开发人员,也可以雇佣新的开发人员来解决瓶颈问题。
然而,就像我们的情形一样,有时你可能需要将它作为代码重写的一个原因。因为我们的软件使用的是旧技术,而CTO是唯一负责开发它的人。我们很难找到一个新的开发人员,因为这个平台年代太久。即使我们能找到一个新人,对我们来说也太昂贵。因此。我还是把它作为代码重写的情形之一,列在这里。
软件的年龄太长(我说的是10-20年或更长时间):
随着时间的推移,一个软件的代码会变得越来越凌乱,维护也会变得越来越昂贵。这是因为为了快速推出修复补丁,初始架构有时会被牺牲掉。而且,懂得旧技术的开发人员越来越少,人员成本也越来越高。同时,很难找到适合旧的应用程序运行的硬件、操作系统和框架。此外,随着业务的发展,旧的系统很可能无法满足新的业务需求。
所以,你必须在旧系统高昂的维护成本,新系统的潜在好处,以及从头重写的成本之间作一个权衡。
如果你的情形符合上述一点或多点,代码重写可能是你能接受的选项。否则,正确的做法是通过一系列简单的步骤改进系统的设计,在不重写代码的情况下处理解决现有系统的复杂性。
从头重写代码可能是你犯的最大错误,但同样地,不重写代码也可能导致相同的结果。我的建议是优先考虑重构而不是重写。
有些开发人员坚信所有系统最终都必须重写。记住这并非总是对的。设计一个不需要抛弃的系统是可能的。总有软件设计师会告诉你,“无论如何,总有一天我们会丢掉所有的东西”。但是,如果软件是从一开始就设计得很好,而且一直有很好的维护,为什么它会被抛弃呢?

作者:Roman Luzgin
译制:CSDN
原文:https://medium.freecodecamp.org/lessons-learned-in-my-10-years-as-a-developer-3d33c8702828
免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!
扫描二维码,关注更多精彩内容
本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。
关键字:
驱动电源
在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。
关键字:
工业电机
驱动电源
LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...
关键字:
驱动电源
照明系统
散热
根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。
关键字:
LED
设计
驱动电源
电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...
关键字:
电动汽车
新能源
驱动电源
在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...
关键字:
发光二极管
驱动电源
LED
LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。
关键字:
LED
驱动电源
功率因数校正
在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...
关键字:
LED照明技术
电磁干扰
驱动电源
开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源
关键字:
LED
驱动电源
开关电源
LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。
关键字:
LED
隧道灯
驱动电源
LED驱动电源在LED照明系统中扮演着至关重要的角色。由于LED具有节能、环保、长寿命等优点,使得LED照明在各个领域得到广泛应用。然而,LED的电流、电压特性需要特定的驱动电源才能正常工作。本文将介绍常用的LED驱动电...
关键字:
LED驱动电源
led照明
LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电源转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。
关键字:
LED
驱动电源
高压工频交流
种种迹象都在表明,半导体行业或已提前进入寒冬时期,越来越多的厂商开始扛不住了……
关键字:
LED
半导体
驱动电源
崧盛股份9日发布投资者关系活动记录表,就植物照明发展趋势、行业壁垒等问题进行分享。植物照明未来市场需求广阔崧盛股份指出,植物照明将会走向长期产业领域。主要原因有三:第一,LED植物照明赋能终端种植更具有经济价值。由于LE...
关键字:
崧盛股份
驱动电源
在当今高度发展的技术中,电子产品的升级越来越快,LED灯技术也在不断发展,这使我们的城市变得丰富多彩。 LED驱动电源将电源转换为特定的电压和电流,以驱动LED发光。通常情况下:LED驱动电源的输入包括高压工频交流电(即...
关键字:
LED
驱动电源
高压直流
人类社会的进步离不开社会上各行各业的努力,各种各样的电子产品的更新换代离不开我们的设计者的努力,其实很多人并不会去了解电子产品的组成,比如LED电源。
关键字:
LED
驱动电源
低压直流
随着科学技术的发展,LED技术也在不断发展,为我们的生活带来各种便利,为我们提供各种各样生活信息,造福着我们人类。LED驱动电源实际上是一种电源,但是它是一种特定的电源,用于驱动LED发射带有电压或电流的光。 因此,LE...
关键字:
LED
驱动电源
电流
LED灯作为一种新型节能和无污染光源,由于其特有的发光照明特性,在现代照明应用中发挥着革命性的作用。作为 LED 照明产业链中最为核心的部件之一,LED 驱动电源的驱动控制技术所存在的可靠性低、成本高等典型问题一直制约着...
关键字:
多路
LED
驱动电源
随着社会的快速发展,LED技术也在飞速发展,为我们的城市的灯光焕发光彩,让我们的生活越来越有趣,那么你知道LED需要LED驱动电源吗?那么你知道什么是LED驱动电源吗?
关键字:
LED
开关电源
驱动电源
早前有新闻称,Cree在2018年开始宣布转型高科技半导体领域,并一边逐渐脱离照明与LED相关业务,一边持续投资半导体。在今日,Cree宣布与SMART Global Holdings, Inc.达成最终协议,拟将LED...
关键字:
cree
led照明