小函数:让你的函数变短的九个好处
Small Methods: Nine Benefits of Making Your Methods Shorter
小函数:让你的函数变短的九个好处
译者注:本文英文版来自http://langrsoft.com/articles/smallMethods.shtml。翻译不改变原文的版权。中文版版权归本人所有。
I've espoused, on many occasions, making your methods short. The pattern Composed Method, defined by Kent Beck in Smalltalk Best Practice Patterns, says that methods should do things only at one level of abstraction. Methods should be short; a good size for Smalltalk methods is one to a half-dozen lines. That translates to about one to twelve lines (not counting braces!) for Java methods.
I recently engaged in a discussion at JavaRanch where someone thought "20 to 25 lines" was too short. After being taken aback, my response was that there are many reasons that your average method size should be considerably smaller. Here are nine benefits to short methods:
在很多场合我都表明过支持短小的函数。Kent Beck在Smalltalk Best Practice Patterns中定义的Composed Method模式指出函数应该只能做一个层次上的抽象。函数应该是短小的;对于Smalltalk函数大小应该在一至六行。翻译到Java应该是一至十二行(不包括大括号!)。
我最近在JavaRanch参加了一个讨论,那儿有些人认为“20到25行”太短。吃惊之余,我的回应是有很多原因让你的平均函数体积应该相当的小。下面是使用小函数的九个好处:
- Maintenance costs. The longer a method, the more it will take you to figure out what it does, and where your modifications need to go. With shorter methods, you can quickly pinpoint where a change needs to go (particularly if you are coding using test-driven development).
- Code readability. After the initial learning curve, smaller methods make it far easier to understand what a class does. They can also make it easier to follow code by eliminating the need for scrolling.
- Reuse potential. If you break down methods into smaller components, you can start to recognize common abstractions in your code. You can minimize the overall amount of code dramatically by reusing these common methods.
- Subclassing potential. The longer a method is, the more difficult it will be to create effective subclasses that use the method.
- Naming. It's easier to come up with appropriate names for smaller methods that do one thing.
- Performance profiling. If you have performance issues, a system with composed methods makes it easier to spot the performance bottlenecks.
- Flexibility. Smaller methods make it easier to refactor (and to recognize design flaws, such as feature envy).
- Coding quality. It's easier to spot dumb mistakes if you break larger methods into smaller ones.
- Comment minimization. While comments can be valuable, most are unnecessary and can be eliminated by prudent renaming and restructuring. Comments that restate what the code says are unnecessary.
- 维护成本。越长的函数越要花费更大的成本去了解它要做什么,以及在什么地方作修改。而对于小函数,你可以快速的查明应该在何处作修改(尤其是在应用测试驱动开发的时候)。
- 代码可读性。在初始的学习曲线之后,小函数使得你更容易理解一个类要做什么。而且你不必滑动窗口就可以理解代码。
- 拥有重用潜力。如果你把函数分解成一些小的模块,你可以识别出代码中通用的抽象。你可以通过使用这些通用的抽象使你的代码总量急剧下降。
- 拥有子类化潜力。函数越长,你就越难以创建一个子类使用这个函数。
- 命名。小的函数命名起来要容易一些,因为它做的事情少。
- 性能测度。如果你遇到了性能问题,一个使用composed method的系统更容易定位性能瓶颈。
- 灵活性。小函数使得重构更加容易(并且容易找到设计缺陷,比如feature envy)。
- 代码质量。如果把大函数分解成小函数,定位隐晦的错误更加容易。
- 最小化注释。虽然注释是很有价值的东西,大多数注释可以通过谨慎的命名和调整结构消除。重述代码已经说清楚的注释是没有必要的。
You should get the idea that most of the benefits are about improving the design of your system. Breaking methods up into smaller ones obviously leads to lots of smaller methods. You will find that not all of those methods should remain in the same class in which the original method was coded. The small methods will almost always point out to you that you are violating the basic rule of class design: the Single Responsibility Principle (SRP).
你应该已经发现多数的好处都是关于提升系统设计的。把函数分解成小函数当然会带来大量的小函数。你会发现并不是所有的这些小函数应该留在原来那一个类中。小函数几乎总是会指出你违反了类设计的基本规则:单一职责原则(the Single Responsibility Principle (SRP))。
The SRP states that a class should have only one reason to change. Put another way, a class should do one thing and one thing only. A class to present a user interface (UI) should do just that. It shouldn't act as a controller; it shouldn't retrieve data; it shouldn't open files; it shouldn't contain calculations or business logic. A UI class should interact with other small classes that do each of those things separately.
Break a class into small methods, and you will usually find all sorts of violations of the SRP.
SRP规定一个类只能因为一个原因去修改。换一种说法,一个类应该做并且只做一件事情。一个呈现用户接口(UI)的类,它就只能做它要呈现的这些事情,而不应当作为控制器,或者接收数据;或者打开文件或者包含计算和业务逻辑。一个UI类应该与其他的小类交互而有那些小类分别去完成那些事情。把一个类分解成很多的小函数,你通常会发现各种各样的对SRP的违反。
Initially, you may find it more difficult to work with code with lots of methods. There is certainly a learning curve associated with doing so. You will find that the smart navigational features of your IDE (for example, Eclipse) can go a long way toward helping you understand how all the little methods fit together. In short time, you will find that well-composed code imparts much greater clarity to your system.
One oft-repeated resistance to short methods is that it can degrade performance in your system. Indeed, method calls are usually fairly expensive operations. However, you rarely create performance problems with more methods. Poor performance can usually be attributed to other factors, such as IO operations, network latency, poor choice of algorithm, and other inefficient uses of resources.
开始,你可能会发现使用大量小函数更加困难。这只是学习曲线的问题。你会发现IDE(比如Eclipse)的智能导航特性会对你的理解这些小函数如何组合在一起大有帮助。短期,你会发现这样的代码给予系统更好的清晰度。
经常遇到的对于小函数的抵抗是它会降低系统性能。确实,方法调用通常是比较昂贵的操作。然而,你极少有机会因为更多的函数制造性能问题。低性能通常是由其他因素造成的,比如IO操作,网络响应,差算法,以及其他的低效的资源使用。
Even if additional method calls do noticeably impact performance (performance is not an issue until someone recognizes it as one), it's very easy to inline methods. The rule of performance is always: make it run, make it right (e.g. small methods), make it fast (optimize).
甚至即使多余的方法调用对性能产生了显著的影响(如果没有人注意到性能就不是问题),inline method是非常容易的。关于性能的规则总是:先让它跑起来,然后让它正确(比如小函数),然后让它快起来(优化)。
While it's difficult to do, you can go too far and create too many methods. Make sure each method has a valid reason for existing; otherwise inline it. A method is useless if the name of the method and the body of the method say exactly the same thing.
There are exceptions to every rule. There will always be the need for the rare method larger than 20 lines. One way to look at things, however, is to look at smaller methods as a goal to strive for, not a hard number. Instead of debating whether 25 lines, 12 lines or 200 lines is acceptable, see what you can do to reduce method length in code that you would've otherwise not touched. You'll be surprised at how much code you can eliminate.
虽然本来这做起来并不容易,你可能会做得太过火并且创建过的函数。确信每个函数有一个恰当的存在的原因;否则inline之。如果一个函数的body已经清楚的表明它做什么这个函数就没有必要单独提出来。任何规则都有特例。总是有时候极个别函数需要超过20行。看问题的角度是,把小函数看作一个奋斗的目标,而不是一个固定数字。与其争论25行,12行或者200行那个更可以接受,倒不如看看你可以做点什么来减少那些你不愿意碰的函数的行数。你会吃惊的发现你可以消除多少代码。
Few people promote pushing in the other direction. Increasing the average method size represents sheer carelessness or laziness. Take the time and care to craft your code into a better design. Small methods!
很少人支持相反的观点。增加平均函数大小完全是不小心或者懒惰。花点时间修理一下代码改善设计。小函数万岁!