软件开发的7个黄金法则:从KISS到YAGNI,助力你成为更出色的程序员
软件开发的7个黄金法则:从KISS到YAGNI,助力你成为更出色的程序员
成为一名优秀的程序员不仅需要掌握各种编程语言和工具,更需要遵循一些基本的软件开发原则。这些原则可以帮助开发者写出更简洁、更可靠、更易于维护的代码。本文将介绍7个最重要的软件开发原则,帮助你提升编程水平。
1. 你不会需要它(You Aren’t Gonna Need It - YAGNI)
这个原则简单明了,但并不是每个人都能遵守。添加代码时,要确保它是当下需要的。不要因为你觉得某些代码以后可能有用就把它们留在那里。
在进行重构时这个原则同样适用。如果你重构一个方法/类/文件,不要舍不得删除那些没用的方法。即使它们过去有用,但现在没用了。也许有一天你又需要它们了,那时你可以通过Git仓库让它们“起死回生”。
2. 不要重复自己(Don’t Repeat Yourself - DRY)
这个概念最早由安迪·亨特(Andy Hunt)和戴夫·托马斯(Dave Thomas)在《程序员修炼之道:从小工到专家》一书中提出。这个理念围绕着“单一事实来源”展开。
保持单一事实来源有助于构建更可靠、更易于理解的代码库。代码重复是一种浪费。你需要在两个地方维护相同的逻辑,在两个地方进行测试,而且当一个地方发生变化时,你必须记得修改另一个地方。
大多数时候,代码重复是由于对系统缺乏了解。在编写任何代码之前,要务实一点:先看看周围。也许这个功能在其他地方已经实现了,也许这个业务逻辑在其他地方已经存在了。复用代码总是一个明智的选择。
3. 保持简单,傻瓜(Keep It Simple, Stupid - KISS)
这个设计原则是20世纪60年代美国海军提出的设计原则。该原则指出,更简单的系统将运行得更好、更可靠。
应用到软件开发中,它的意思就是——不要过度设计。有时候,最聪明的解决方案就是最简单的那个。用简洁的方式构建高性能、高效的代码是很棒的。
如今,最常见的错误之一就是仅仅因为新工具很炫酷就尝试使用它们。开发者不应该仅仅因为新技术是新的就有使用它们的动力,而应该是因为它们适合这项工作。
4. 预先进行大量设计(Big Design Up Front)
这种软件开发方法至关重要,但很多时候却被忽视。在开始实施之前,要确保一切都经过深思熟虑。
“很多时候,提前把事情考虑清楚能让我们在后续开发中避免严重的头痛问题……在规格说明书中做这个更改只需要一两个小时。如果我们在代码中做这个更改,可能会让项目周期增加数周。我无法更强烈地表达我对预先进行大量设计的信念了,尽管极限编程的支持者们认为这是一种禁忌。通过使用这种方法,我一直都能节省时间并开发出更好的产品,无论极限编程的狂热者们怎么说,我都为使用这种方法而自豪。在这一点上,他们就是错的,我再清楚不过了。”
——乔尔·斯波尔斯基(Joel Spolsky)
很多开发者觉得如果还没开始编码就是没有进展,这是错误的。通过制定一个具体的计划,你可以避免自己可能需要重新从头开始的情况。有时候,设计中的缺陷需要其他人参与讨论。这种讨论越早进行,对大家越好。
一个非常常见的反对观点是,修复问题的成本比规划它们的时间要低。这肯定是不对的。用户遇到的错误/不一致性越少,他们的体验就越好。你可能没有第二次机会去抓住用户了。
5. SOLID原则
这是最著名的软件原则。SOLID是以下几个单词的首字母缩写:
S)单一职责原则(Single - responsibility principle)
它的重要性怎么强调都不为过。每个对象、类和方法都只应有一个职责。如果你的对象/类/方法做的事情太多,最终就会出现著名的“面条式代码”。下面是一个例子:
这个方法看起来没什么问题,但它做得太多了:
- 在后端(BE)保存对象
- 处理用户界面(UI)通知
- 一些导航功能
另一个副作用是测试。纠缠在一起的功能更难测试。
O)开闭原则(Open - closed principle)
软件实体应该对扩展开放,但对修改关闭。我的意思是,我们不应该仅仅因为需要更多功能就重写方法/类。
继承是实现这一原则的好方法。在JavaScript中,主要通过组合来实现。
小提示:如果你修改一个实体来使其可扩展,那么你第一次就违反了这个原则。
L)里氏替换原则(Liskov substitution principle)
这个原则是指超类的对象必须能够被其子类的对象替换,并且应用程序仍应按预期工作。
I)接口隔离原则(Interface segregation principle)
这个原则是罗伯特·C·马丁(Robert C. Martin)在为施乐公司做咨询时提出的,这是一个很明显的原则。
“客户端不应该被迫依赖它们不使用的接口。”——罗伯特·C·马丁
软件应该被拆分成多个独立的部分。应尽可能减少副作用以确保独立性。
要确保你没有强迫对象去实现它们永远不需要的方法。下面是一个例子:
并不是所有动物都能飞、走或游泳,所以这些方法不应该是接口的一部分,或者应该设置为可选的。
D)依赖倒置原则(Dependency inversion principle)
这个原则的重要性再怎么强调也不为过。我们应该依赖抽象,而不是具体的实现。软件应该具有低耦合和高内聚的特性。
你不应该关心事物是如何构建的,而应该关心它们是如何工作的。一个简单的例子是在JavaScript中使用日期。你可以构建自己的抽象层。这样,如果你要更换日期提供程序,你只需要在一个地方修改,而不是在成千上万个地方修改。
有时候,构建那个抽象层需要花费一些精力,但从长远来看是值得的。
例如,date - io就创建了这样一个抽象层,使你可以与多个日期供应商一起使用。
6. 避免过早优化(Avoid Premature Optimization)
过早优化是指在还未证明优化是必要的情况下,开发者就进行不必要的优化。我认为如果你遵循KISS和YAGNI原则,就不应该陷入这种情况。
不要误解我的意思,尝试预测可能出现的问题是好的,但在深入实施细节之前,你需要检查这些优化是否真的有用。
一个非常简单的例子就是扩展。你不会因为觉得你的新应用会火就购买40台服务器。相反,你应该根据需要增加服务器。
过早优化可能会导致你的代码延迟,从而增加产品推向市场的时间成本。
很多人都认为过早优化是万恶之源。
7. 奥卡姆剃刀原则(Occam’s Razor)
“奥卡姆剃刀(Occam’s razor、Ockham’s razor、Ocham’s razor,拉丁语:novacula Occami)或简约法则(拉丁语:lex parsimoniae)是一种解决问题的原则,即‘如无必要,勿增实体’[1][2],或者更简单地说,最简单的解释通常是正确的。”——维基百科
在编程世界中这意味着什么呢?不要在不需要的时候创建不必要的实体。要务实——想想是否真的需要它们,因为它们可能最终会增加你的代码库的复杂性。
总结
这些原则并不复杂。事实上,正是它们的简单性让它们如此美妙。如果你觉得不知所措,不要担心。目前,你只需要努力提高自己的意识,并尝试一次将一个原则融入到你的日常工作中。
有一些基本但强大的原则可遵循,这将有助于你成为一名更好的程序员,并让你更清楚为什么要做这些事情。
如果你已经在凭直觉应用其中的大部分原则,那么当你明白为什么自己一直以某种方式做事时,那种顿悟的感觉是很好的。