把这个方法应用于更大的问题
前一个例子把过程应用于小块代码。在下一个例子中,我们会把它应用于更大的函数。你会看到,这个方法可以帮助你识别哪个片段可以分离,从而让你可以拆分代码。
假设我们有一个记录股票采购的系统。每笔交易都有4块数据:
·time(一个精确的购买日期和时间)
·ticker_symbol(公司简称,如:GOOG)
·price(价格,如:$600)
·number_of_shares(股票数量,如:100)
由于一些奇怪的原因,这些数据分布在三个分开的数据库表中,如下图所示。在每个数据库中,time是唯一的主键。
现在,我们要写一个程序来把三个表联合在一起(就像在SQL中的JOIN操作所做的那样)。这个步骤应该是简单的,因为这些行都是按time来排序的,但是有些行缺失了。你希望找到这3个time匹配的所有行,忽略任何不匹配的行,就像前面图中所示的那样。
下面是一段Python代码,用来找到所有的匹配行:
这个例子中的代码能运行,但是在循环中为了跳过不匹配的行做了很多事情。你的脑海中也许闪过了一些警告:“这么做不会丢失一些行吗?它的迭代器会不会越过数据流的结尾”?
那么如何来把它变得更可读呢?
用自然语言描述解决方案
再一次,让我们退一步来用自然语言描述我们要做的事情:
我们并行地读取三个行迭代器。
只要这些行不匹配,向前找直到它们匹配。
然后输出匹配的行,再继续向前。
一直做直到没有匹配的行。
回头看看原来的代码,最乱的部分就是处理“向前找直到它们匹配”的语句块。为了让代码表现得更清楚,我们可以把所有这些乱糟糟的逻辑抽取到,名叫AdvanceToMatchingTime()的新函数中。
下面是代码的新版本,它使用了新的函数:
如你所见,这段代码容易理解得多,因为我们隐藏了所有行对齐的混乱细节。
递归地使用这种方法
很容易想象你将如何编写AdvancToMatchingTime()——最坏的情况就是它看上去和第一个版本中难看的代码块很像:
但是让我们把我们的方法同样应用于AdvanceToMatchingTime()来进改这段代码。下面是对于这个函数所要做的事情的描述:
看一下每个当前行:如果它们匹配,那么就完成了。
否则,向前移动任何"落后"的行。
一直这样做直到所有行匹配(或者其中一个迭代器结束)
这个描述清晰得多,并且比以前的代码更优雅。一件值得注意的事情是描述从未提及stock_iter或者其他解决问题的细节。这意味着我们可以同时把变量重命名得更简单,更通用。下面是这样做后得到的代码:
如你所见,这段代码比以前清楚得多。该算法变得更简单,并现在那种微妙的比较更少了。我们用了像t1这样的短名字,却不用再考虑那些具体涉及的数据库字段。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论