Split Loop -- 分离循环
来源:互联网 发布:淘宝梦幻西游账号 编辑:程序博客网 时间:2024/05/04 16:34
Split Loop
You have a loop that is doing two things
一个循环做了两件事情。
Duplicate the loop
复制循环。
void printValues() {double averageAge = 0;double totalSalary = 0;for (int i = 0; i < people.length; i++) {averageAge += people[i].age;totalSalary += people[i].salary;}averageAge = averageAge / people.length;System.out.println(averageAge);System.out.println(totalSalary);}
void printValues() {double totalSalary = 0;for (int i = 0; i < people.length; i++) {totalSalary += people[i].salary;}double averageAge = 0;for (int i = 0; i < people.length; i++) {averageAge += people[i].age;}averageAge = averageAge / people.length;System.out.println(averageAge);System.out.println(totalSalary);}
Motivation
You often see loops that are doing two different things at once, because they can do that with one pass through a loop. Indeed most programmers would feel very uncomfortable with this refactoring as it forces you to execute the loop twice - which is double the work.
你经常会看到一个循环做了两件事情,因为这两件事情可以通过一个循环来完成。对于大多数程序员来说这种重构手段不太适应,因为两个循环势必会造成两倍的工作量。
But like so many optimizations, doing two different things in one loop is less clear than doing them separately. It also causes problems for further refactoring as it introduces temps that get in the way of further refactorings. So while refactoring, don't be afraid to get rid of the loop. When you optimize, if the loop is slow that will show up and it would be right to slam the loops back together at that point. You may be surprised at how often the loop isn't a bottleneck, or how the later refactorings open up another, more powerful, optimization.
像这种优化,一个循环中做两件事情会降低清晰度。分离循环会引起一些问题,如引入一些临时变量。但是重构的时候不要害怕去除循环。你经常会吃惊由于循环造成的性能瓶颈并不是经常发生。
Mechanics
- Copy the loop and remove the differing pieces from each loop
- 复制循环,使得每个循环做一件事情。
- Compile and test.
- 编译测试。
- Reorganize the lines to group the loop with related code from outside the loop
- 重新组织循环外相关的代码
- Compile and test.
- 编译测试
- Consider applying extractMethod or replaceTempWithQuery on each loop
- 对于每个循环考虑使用extractMethod和replaceTempWithQuery
Example
Start with this code.
private Person [] people;void printValues() {double averageAge = 0;double totalSalary = 0;for (int i = 0; i < people.length; i++) {averageAge += people[i].age;totalSalary += people[i].salary;}averageAge = averageAge / people.length;System.out.println(averageAge);System.out.println(totalSalary);}
The loop is calculating both the total salary and the average age. This is two separate tasks, which just happen to use the same data structure. So I'll split the loops for now, knowing I can optimize later.
这段循环代码计算总薪水和平均年龄。这是两个不同的任务,仅仅因为使用了相同的数据结构people数组。所以我们现在分离它。
The first move is to copy the loop and remove from each leg one part of the calculation.
首先复制循环,然后分离计算任务。
void printValues() {double averageAge = 0;double totalSalary = 0;for (int i = 0; i < people.length; i++) {totalSalary += people[i].salary;}for (int i = 0; i < people.length; i++) {averageAge += people[i].age;}averageAge = averageAge / people.length;System.out.println(averageAge);System.out.println(totalSalary);}
I can now compile and test this.
编译测试
Then I can reorganize the text to group things together.
然后重新组织代码进行分组。
void printValues() {double totalSalary = 0;for (int i = 0; i < people.length; i++) {totalSalary += people[i].salary;}double averageAge = 0;for (int i = 0; i < people.length; i++) {averageAge += people[i].age;}averageAge = averageAge / people.length;System.out.println(averageAge);System.out.println(totalSalary);}
One thing that has bothered me about this refactoring is that there's a lot of duplicate loop setup code - and duplication is the worst smell of all. On the whole, however, I don't feel that concerned about it. Fundamentally the duplication is due to the godawful way that Java does loops. Other modern languages with a foreach
statement avoid the duplication completely.
这个重构有一点困扰我,重复的循环代码并且重复是万恶之首。总体上来说,我不会太关注这个。可以以foreach 语句替换掉。
Officialy that's the end of the refactoring. But the important thing here is what it leads you to do. In this case I'm inclined to apply Replace Temp with Query to each loop.
到此重构就算完成了。
void printValues() {System.out.println(averageAge());System.out.println(totalSalary());}private double averageAge() {double result = 0;for (int i = 0; i < people.length; i++) {result += people[i].age;}return result / people.length;}private double totalSalary() {double result = 0;for (int i = 0; i < people.length; i++) {result += people[i].salary;}return result;}
- Split Loop -- 分离循环
- split分离字符串
- 字符串分离 split
- 分离字符串Split函数
- jquery分离方法split()
- jquery分离方法split()
- for loop循环
- 循环不变量(Loop invariant)
- loop invariant 循环不变量
- loop 设备 (循环设备)
- loop 设备 (循环设备)
- 汇编中loop循环
- ruby loop循环
- Loop Invariant 循环不变量
- plsql loop循环
- loop 设备 (循环设备)
- shell循环loop
- pl/sql loop循环
- 传颂之物
- 杭电ACM2035人见人爱的A^B
- RMQ模板
- 2014.3.18——一个C++中没有的C的功能
- 例题2——2
- Split Loop -- 分离循环
- OpenCV基础数据结构
- 求数组中最长递增子序列—动态规划入门(编程之美)
- Oracle
- memcached的并发问题
- 简述MVC分层
- 连续整数之和为指定值
- 嵌套模型(DAG上的动态规划)—动态规划入门(算法经典入门)
- ADS错误the session file 'C:\user\username\default-1-2-0-0.ses' could not be loaded解决办法