您如何向非技术人员(通常是PHB或客户)解释重构(和技术债务)?(“什么,这要花我一个月的时间而没有明显的区别?!”)
更新感谢到目前为止的所有回答,我认为此列表将提供一些有用的类比,我们可以向相应的人员指出(尽管删除对PHB的引用可能是明智的!)
您如何向非技术人员(通常是PHB或客户)解释重构(和技术债务)?(“什么,这要花我一个月的时间而没有明显的区别?!”)
更新感谢到目前为止的所有回答,我认为此列表将提供一些有用的类比,我们可以向相应的人员指出(尽管删除对PHB的引用可能是明智的!)
Answers:
当您有一个大型家庭影院并添加东西时,缓慢但可以肯定的是,大老鼠会在后面筑巢。
如果您经常更换零件,有时值得理清所有这些东西。
当然,如果您这样做,它会比以前更有效,并且不会比开始时更好,但是当您不得不再次对其进行弄乱时,事情会容易得多。
在任何情况下,最好将其与PHB或客户已经熟悉的某些领域进行类似的比较,例如汽车或建筑等。
重构就像重新整理行李箱直到一切都整齐放置的过程一样。有时,在此过程中,您想知道为什么为什么要一开始那么多地扔进垃圾里。
我不会解释技术债务的概念,因为这不是必需的。相反,应该专注于重构:您正在更改程序的设计,而不一定要使其“更好”或“得到改进”,而是要对其进行更改,以便它可以接受您需要进行的更改。
打个比喻可能很适合:您需要在汽车上添加空调,但最初并不是为汽车设计的。您不仅必须制造一个奇怪的L形空调,而且还需要先移开其他一些东西并更换通风系统。
我还认为,当您容纳新功能时,这是重构的更好策略:否则,您可能会将设计更改为看上去“更好”的东西,但实际上可能不适合围绕添加新功能的情况。
我使用“技术债务”一词,并将其直接与他们理解的东西-企业债务联系起来。技术债务就像贷款一样。您为此支付利息。例如,您可以建造一个新工厂并直接付款,也可以借贷。如果获得贷款,从长远来看,您实际上会为此付出更多,但是如果条件正确,从财务上讲是有意义的。
但是,如果您要为此类贷款支付25%的利息,则会使自己处于无法维持的状态。技术债务也是如此。有时承担一些技术债务是合理的。但是,有时利息过高,需要还清。一些技术性债务就像房屋贷款,而有些则像信用卡债务。在紧急情况下,信用卡债务是一项重要且宝贵的资产。但是,如果使用不当,它也会破坏银行(或您选择的家庭)。
另一个例子:您可以支付10,000美元购买营销邮件,以吸引更多销售线索。您正在还清“销售债务”。这是一项具有长期回报的支出。等同于为什么现在要“花”钱重构代码片段。在这两种情况下,都不会立即获得回报,但是您将为将来的更好表现做好准备。
与目标受众交谈时,我倾向于使用“ xxxx债务”作为类比。例如,运营债务-我们现在拥有的印刷机运转良好,但是通过停止生产一天(或一周)并升级到新机器,我们可以将产量提高25%。
编辑- 这是对此的另一种看法
“您曾经玩过Mouse Trap吗?当我们坚持使用新功能,更改界面并修复错误时,代码可能看起来像这样。有时候,我们要么必须花费大量资金(时间和精力),要么,这很省钱),以确保所有活动部件在每次进行新更改或添加时都能很好地发挥作用,或者我们可以留出时间来重构设计,从而减少每次更改时我们需要管理的活动部件。可似乎,从最终用户的角度来看,该重构没有任何好处,但效益发生的每一个新功能的添加,重构后的时间,这个过程更快,引入更少的错误,之后是更便宜,更不用说重构的代码通常在整体上更高效。
您可能想知道为什么我们首先让它看起来像鼠标陷阱:
为了不断构建更好的鼠标陷阱,我们必须不断地回过头来寻找减少复杂性和简化现有产品的地方。只拥有具有很多功能的软件和拥有真正高质量的软件是有区别的。”
我会说“代码维护”。使用非技术人员熟悉且对非技术世界观有意义的词很重要。如果非技术人员(客户)熟悉应用程序维护,则可以轻松并行进行代码维护和应用程序维护。即使它们不相同,您也可以说明最终用户是开发人员或如何维护系统。
假设您是一位专门定制汽车的机械师,甚至在客户需要时从头开始建造汽车。经常有一位顾客回到您的商店,总是在他的超大型豪华轿车中放一些新的闪亮物品。
一旦他进来安装了一个不错的音响系统。您可以通过电缆并正确连接所有电缆来认真执行任务。他一天后出去,他很高兴,并且像往常一样支付了丰厚的报酬。
下个月他回来了,但是这次他想要安装一个完整的家庭影院。再一次,您可以坐豪华轿车。作为专业人士,您可以重新安装音响系统,并通过安装用于在汽车周围铺设电线的管路系统使维护起来更加容易。这样可以保护电线,并且更容易拔出电线,如果您需要添加更多电线,也很容易做到。因此,您将旧电线撕掉,安装管道,并通过音响系统和电影院的多余电线,将其全部关闭即可。
意识到客户没有要求您更换旧的音响系统,您就省下了更换和电子管的一些费用。但是,您仍然可以从交易中获利,只是不如您第一次将系统一起投入系统时那样多。
一个月后,他回来了,这次他想要一个照明系统,并且希望新的扬声器在本周早些时候损坏旧的扬声器。
因为一切都保持整洁,所以您可以快速将新的照明电线穿过灯管,安装系统并更换扬声器。但是这一次您可以更快地完成工作,通过使您保持游戏的领先地位,重构将获得回报。
您的竞争对手一直在嘲笑您撕裂了完美的电线并安装了所有这些多余的管子,但他们仍在努力让他的客户满意。当然,在大多数情况下,他的工作进度都比您快,但随着时间的流逝,他的客户抱怨到越来越多的延误以及工作的整体质量下降。
看到这一点,您就会意识到,不仅要保持业务发展,而且要成为一流的企业,目标是平衡您在满足客户需求方面所做的工作以及为使您的生活更轻松而要做的事情。很少有客户会为这两者付费,因此您必须密切管理。您会赌注,即使以两倍的代价来主动执行正确的事情,也可以将维护成本保持在生产率的受控稳定百分比内。
软件是相同的,只是程序员可以在很长一段时间内使用数字胶带进行播放,然后客户和经理才能真正感受到效果。不幸的是,到那时,正确做事的成本相对于存在多少胶带和所述胶带的平均寿命呈指数增长。
这就是为什么我们继续重构系统很重要的原因。很多时候,经验会向我们展示一种新的更有效的方式来执行相同的操作,或者我们可以组合相似的功能并利用冗余,而不仅仅是复制它们。这就是我们保持系统精简和卑鄙的方式。时间将表明,不断重构系统以满足需求将通过控制维护量来保持生产率恒定。
放置输送带会瞬间增加生产率,但要以携带次优系统为代价。只要有利于立即提高生产力而损害系统的其他方面,就会招致技术债务。债务比喻很好,因为就像借入资本的利息吞噬了利润一样,借来的时间使事情变得很快会导致更高的维护成本,并且增加了系统的脆弱性,迫使团队花费更多的资源进行维护而不是创建。就像其财务亲戚一样,如果继续借贷不减,则大部分资源将用于偿还利息,而几乎没有改善的余地。技术债务将吞噬技术资源,以致大部分资源都被浪费在仅仅使系统运行停止所有其他可能的增强上的地步。
因此,最终的问题不是我们应该还是不应该这样做,而是让管理者和客户相信他们可以依靠使用数字胶带而人为肿的生产力数字是否合乎道德。有人会认为这是一个商业决策,但坦率地说,这仅仅是因为经理们不理解它。最后,有人将不得不通过繁重的重构或通过迁移到新系统来偿还债务。最终,对我们(程序员)来说,要保持系统的可维护性,您不必要求进行重构,因为它是工作的固有部分,如果不了解这一点,那就意味着您不了解软件工程的全部含义。这就是说,我知道那里已经有一些系统产生了重要的债务,要偿还这些债务将需要付款人做出决定。您的工作就是这样的情况,至少要尽自己的一份力量来停止借款。发生了这笔债务在美国,也许是因为我们并不了解,因为我们被迫这样做,但我们还是被迫承担了这笔债务,而我们交纳债务的人常常不理解它,因此无法适当地管理它。
这是您的软件,已全部完成,希望您喜欢它。...呵呵,顺便说一句,我已经用尽您的信用卡,希望您别介意... cya
以台式计算机为例。您有一个塔架,显示器,键盘,鼠标,打印机,扫描仪和扬声器。最终,您想要的只是一个有条理的办公桌。因此,您只是盲目插入东西,几分钟后,瞧瞧,一切都按照您想要的方式进行了设置。好吧...几乎就是您想要的方式。
一天后,当您改变扬声器的平衡时,您意识到自己不小心将左右扬声器放在错误的区域,因此您想调换其位置。但是,哦,不!有一个纠结的绳索丛林。当您继续移动扬声器时,鼠标线会钩住,现在您的鼠标会与扬声器一起拖动。而且,您的键盘现在没有任何松弛-过去您可以将其从桌子移动到膝盖上。
好了,您只需拔下鼠标和键盘,然后重新插入即可,一切都已修复。但这对将来的重组和将来的添加没有帮助。同样,在丛林中编织鼠标和键盘线也很麻烦。
更好的解决方案是重新插接所有东西,以干净整洁的方式将它们插回去,使每根电线都不会相互干扰。现在,未来的变化很容易,而且将继续变得容易。您需要预先投资以获取较大收益。
关键是,原始解决方案大部分是有效的。重构就是这样:它从一开始就起作用,但是您需要更改已有的方式,以轻松进行将来的更改(移动扬声器)。
这有点像是从前一天晚上疯狂疯狂的聚会后打扫房子。
假设客厅完全被垃圾摧毁了。房子仍然是房子,客厅仍然是客厅。它有效,但事实并非如此。盯着烂摊子后,您意识到它需要清理。
因此,您开始将垃圾打包。看起来已经更好了。因此,您环顾房间,并决定整齐家具。您放回一件,然后再放下一件。哇,房间真的很好。你真骄傲
你姐姐走进去,说房间看起来像垃圾,应该固定书架并抽空地毯。没错 房间看起来真的非常好。
您环顾四周,发现如果窗框的高度相同,则它们看起来会更好。做完了 哇,房间很棒。
以相同的方式对待您的代码。
国际海事组织(IMO)对物理世界中所有与事物有关的比喻(如建造剧院)都是可怕的。
您需要说明重构代码就像...重构代码。软件具有延展性,而物理类似物则不具有延展性。随着事情变得越来越复杂,必须对代码库的大块或小块进行反应(或重做,如您所愿),以便我们可以继续增加复杂性而不会发疯。
我们为什么要重构?因为从未重构的代码每分钟维护和更改的成本更高,最终变得更加棘手。
重构的有趣之处在于,我们重做了代码库,但是至少在一开始,其功能仍保持不变。
我想到了另一个示例,这里显然没有人提及:重构与重新排列数学方程式几乎完全相同(尽管我认为这可能超出了“非技术人员”的范围)。
重新排列方程式时,只需“移动内容”即可使其变得更具可读性和可用性,而无需更改含义。
给他们一个简单的数学方程式。例如:
哪个更简单?
y = x + x
要么
y = 2x
重构是一个类似的概念,只是您使用算法代替了简单的数学方程式。主要思想是您可以在两种做事方式之间进行互换,因为它们会产生相同的结果。
可以完成的最简单的重构是重命名。
doX() { ... }
{
doX()
}
现在,由于我们并不真正希望将其称为doX,因为我们并不真正了解它的含义,因此我们将其重命名为其他名称,这些名称更易于说明,并在使用过的任何位置进行替换。
doBusinessTransaction() { ... }
{
doBusinessTransaction()
}
这将在以后出现问题或增强功能时为您节省金钱,因为它减少了人们理解和修复您的应用程序的时间。为了进一步节省金钱,有一些免费工具会根据您使用的语言自动为您执行此操作。这些工具也已获得许可,因此不受限制,并且如果直接使用它,除了确认它之外,还需要您做其他特别的事情。
考虑一下“ 重构”中给出的答案,不要向非技术人员解释。重构是他们不需要了解的技术活动:
当然,许多人说,他们是由质量驱动的,但更多是由进度驱动的。在这些情况下,我会提出更多有争议的建议:不要说!
颠覆性的?我不这么认为。软件开发人员是专业人士。我们的工作是尽快构建有效的软件。……受日程安排驱动的经理希望我以最快的方式做事;我该怎么做是我的事。最快的方法是重构。因此我重构。
(重构,Martin Fowler,2000年,第61页)
当然,如果您要花一个月的时间只做重构,那么这是行不通的,但是我认为这通常是个坏主意,最好重构到使您当前或下一个任务更轻松所需的程度,这会更好,或清理您刚刚使用过的代码。