从对象中抽取值
我们曾有过一段JavaScript代码,用来把用户的位置格式化成“城市,国家”这样友好的字符串,比如Santa Monica,USA(圣摩尼卡,美国)或者Pairs,France(巴黎,法国)。我们收到的是一个location_info字典,其中有很多结构化的信息。我们所要做的就是从所有的字段中找到"City"和"Country"然后把它们接在一起。
下图给出了输入/输入的示例:
到目前为止这看上去很简单,但是微妙之处在于“4个值中的每个或所有都可能缺失”。下面是解决方案:
·当选择"City"时,"LocalityName"(城市/乡镇),如果有的话。然后是"SubAdministrativeAreaName"(大城市/国家),然后是"Administrative-AreaName"(州/地区)。
·如果三个都没有的话,那么赋予"City"一个默认值"Middle-of-Nowhere"。
·如果"CountryName"不存在,就会用"Planet Earth"这个默认值。
下图给出两个处理缺失值的例子。
我们写了下面的代码来实现这个任务:
当然,这个有点乱,但是它能完成工作。
但是几天之后,我们需要改进功能:对于美国之内的位置,我们想要显示州名而不是国家名(如果可能的话)。所以不再是"Santa Monica,USA",而是变成了"Santa Monica,California"。
把这个功能添加进前面的代码中会让它变得更难看。
应用“一次只做一件事情”原则
与其强行让这段代码满足我们的需要,不如我们停了下来并且意识到它现在已经同时在完成多个任务了:
1.从字典location_info中提取值。
2.按喜好顺序找到"City",如果找不到就给默认值"Middle-of-Nowhere"。
3.找到"Country",如果找不到的话就用"Planet Earth"。
4.更新place。
所以我们反而重写了原来的代码来独立地解决每个任务。
一个任务(从location_info中提取值)自己很容易解决:
做到这儿,我们已经用完了location_info,不用再记得那些又长又违反直觉的键值了。反而我们得到了4个简单的变量。
下一步,我们要找出返回值中的“第二部分”是什么:
类似地,我们可以找出“第一部分”:
最后,我们把信息结合在一起:
本章开头展示的"碎片整理"实际上体现了原来的方案和这个新版本。下面是同一幅图,添加了更多细节:
如你所见,在第二个方案中把4个任务整理到独立的区域中了。
另一种做法
在重构代码时,经常有很多种做法,这个例子也不例外。一旦你把一些任务分离开,代码变得更容易让人思考,你可能会想到重构代码的更好方法。
例如,早先的一连串if语句需要小心地去读才能知道每种情况是否都对。在那段代码中其实有两个子任务同时在进行:
1.遍历一系列变量,找出可用变量中最满意的那一个。
2.依据国家是否为"USA"而采用不同的列表。
回顾从前的代码,你可以看到"if USA"的逻辑交织在其他的逻辑中。我们可以分别处理USA和非USA的情况:
如果你不了解JavaScript的话,a||b||c的写法会逐个计算直到找到第一个“真”值(在本例中,是指一个定义的非空字符串)。这段代码的好处是观察喜好列表很容易,也容易更新。大多数if语句都被扫地出门,业务逻辑所占的代码更少了。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论