Table of contents
No headings in the article.
原文地址:Don’t write reusable code
可复用的代码通常是开发人员和领导们的目标。 主管和副总裁曾多次和我说,我们有“可复用性问题”,我们需要更多可复用的代码。 DRY(Don’t repeat yourself 不要重复自己)原则经常被引用来支持编写可复用代码这样的行为。 在我的经验看来,一些最有害和最难维护的代码是带有代码复用性的心态编写的。
我不写可复用的代码,并且我积极劝阻其他开发人员,建议他们也不要这样做。 这并不意味着我的代码没有实现复用; 事实上,我的代码经常达到了显著的复用。 这篇文章是关于避免一个常见的编码陷阱; 它也是通过不花精力在代码复用之上而又能获得代码复用的指南。
复用不是一个问题; 它是一个解决方案。 我从来无法定义何为“可复用性问题”,或者从相信它存在的人那里提取关于它的细节。 我相信,当人们说他们有“可复用性问题”时,他们实际上指的是有一个低生产率问题,或者是一个高可维护问题。 讽刺的是,试图将可复用性强加到代码中可能会使这两个问题变得更糟。 低生产率和高可维护问题完全有可能是由代码的强制可复用性引起的。
我相信这么多的开发者和领导倡导复用的一个原因是他们看到了成功的代码库,这些成功的代码库包含了大量的可复用代码。由此产生了一个错误的假设,即这些代码是为了可重复使用而写的。但这可能不是事实。代码库里产生的可复用代码是编写简洁代码的副产品,这些简洁代码解决定义明确的具体问题。
代码不应该为复用而写。这从根本上说是个坏主意。编写可重复使用的代码的根本问题是,没有任何模式或定义来说明如何做到这一点。代码复用是一种结果,而不是一种设计模式。编写可复用的代码时,通常会对未来进行假设,且代码经常会用配置来实现,使其行为可以改变,以解决多个用例。这两种方法都是反模式。
对一个你无法控制的未来做出假设,很少能有效果。即使你对问题有经验,对未来有很好的想法,你也无法控制塑造未来的外部影响因素。公司不断地重组,团队拆分或合并;还有新的领导层,往往是非常有主见的领导。新技术入场,公司根据周围不断变化的世界来调整他们的业务目标。如果你看一下公司已经使用了一年多的代码库,你很可能会发现死代码和为未来使用而准备的配置,从未实现。
编写带有配置的代码往往是最危险、最有害的代码。它往往通过强制来实现某种程度的复用;但同时也降低了生产效率,增加了维护量。可配置的代码容易出错,因为它引入了多个故障点,而且可能很难理解哪些配置是有效的。可配置的代码很难维护,因为每个用例都必须考虑。还有特别有害的是,开发人员在使用代码时经常会有创造性,他们经常以意想不到的方式滥用代码。这种类型的代码复用的可能结果就是典型的 "意大利面条代码":其中一个改进或bug修复导致一个或多个新的bug被引入。这往往会导致的结果是大家都不敢去修改代码库的代码。
代码是用来解决一个小而具体的问题的。问题越小、越具体越好。这将成就高度可维护的代码,而这些代码将随着问题的演化而继续演化来解决问题。这种类型的代码很容易理解,而且开发人员很难以创造性和非故意的方式滥用。
当一个问题重新出现时,这时候才会发生代码复用。当一个问题重新出现时,代码可以被复用来解决它。如果问题没有重现,代码仍然需要用来解决这个问题。因此,没有必要花精力去确定一个问题是否会再次发生。开发人员和领导只需要专注于理解问题,并编写简单而简洁的代码来解决这个具体问题。当问题再次发生时,代码的重用会自然发生。
通过不写可复用的代码;你会对你实现的代码复用的程度感到惊讶。
案例学习: Spring Framework
github.com/spring-projects/spring-framework
以下是由import语句确定的Spring框架代码库中被重用最多的10个类。
1,279 Assert.java
491 StringUtils.java
403 Log.java
365 LogFactory.java
289 ObjectUtils.java
299 ClassUtils.java
252 HttpHeaders.java
222 CollectionUtils.java
204 MethodParameter.java
197 MediaType.java
这些类中的每一个都解决了一个小而具体的问题。大多数构造器和方法都很简单,只接受一个或很少的几个参数。这些类中没有一个对Spring框架的未来做出假设。这些类中没有一个是可配置的,因此它们可以解决多种用例。每个类都解决了一个在整个代码库中重复出现的问题。