相比于“一门语言”,
“一门程序语言”更多时候是“一门规范”。
(当然,“语言”本身就是“规范”。)
上次讲到了写代码想偷懒的话,
搞明白、想清楚再写是解决根源的一个办法。
但是凡人(没打错字)的需求始终不是重点,
写程序要偷懒,
最终还是在代码上偷懒的。
Best Practice
外国程序员很喜欢念叨一个词,
叫Best Practice
。
比如说Java
里面JSON
要怎么处理,
就可以搜Java JSON Best Practice
;
比如我对数据库一窍不通,
但我就是要学,
可以搜Database Best Practice
;
比如我是甲方,
我不知道我自己想要什么,
我也可以搜Requirements Best Practice
。
这种英文单词一般会有一个直译的中文,
叫最佳实践
,
听起来巨蠢。
但是用来举例子就很好用。
我加入再惠的时候,
只写过一点Python
,
代码习惯也是不加encoding
,
不知道from __future__
,
写print
不写括号的,
所有要用到的第三方库都装在全局的site-packages
下面。
来了以后我知道了virtualenv
。
后来张总玩Lucene
的时候我给他配了下Gradle
,
并解释了一下:“这个东西很简单的,跟virtualenv
是类似的概念。”
张总感慨道:
“其实学一门语言就是从这些工具开始啊,
这样才有一种我上手了的感觉啊!”
还有就像Go
语言的gofmt
命令,
这个命令会强制执行统一的代码风格调整,
不能配置、不能定制化、缩进统一使用Tab。
我十分痛苦,
不过也十分认可这里的思想:
“语言风格就是林黛玉哈姆雷特,千人千面。
相比于完美的风格,统一的风格更科学。”
Best Practice
就是实际操作时的指南,
了解、掌握、实践Best Practice
可以少些很多代码少走很多弯路,
用精妙的方法解决实际问题。
精妙的方法
按照套路,接下来应该讲一段精妙的方法。
不过小弟我没啥精妙的方法,
就只能举自身当反例了。
在写API
的时候,
经常要处理URL
,
处理URL
实际上是字符串拼接。
比如Python
里面把一个dict
转换成query string
格式,
我以前会这么写:
params = {'name': 'afu', 'action': 'take a plane'}
query_string = '&'.join(['{}={}'.format(k, v) for k, v in params.items()]) # 'name=afu&action=take a plane'
当时自我感觉良好,
觉得Python
不愧是Python
啊,List Comprehension
真优雅,真好看。
然而这段代码不仅有Bug,
其实Python
有专门的库urllib
来处理这类问题,urllib
也已经考虑了各种边界情况(比如带非法字符等):
# 举Python3为例
import urllib
params = {'name': 'afu', 'action': 'take a plane'}
query_string = urllib.parse.urlencode(params) # 'name=afu&action=take+a+plane'
后来又学到了urlencode
函数在Python2
和Python3
的位置都不一样,
一般是用six
这个库去处理兼容性的。
下面这段代码就不需要额外说明_举Python3为例_了:
import six
params = {'name': 'afu', 'action': 'take a plane'}
query_string = six.moves.urllib.parse.urlencode(params) # 'name=afu&action=take+a+plane'
虽然有很多种方法都能达到同样的效果,
但软件工程中,
大家往往都定下一个Best Practice
然后遵守它。
这样不仅能省下写程序的功夫,
也能省下沟通争辩的功夫。
就像Zen of Python
里说的一样:There should be one-- and preferably only one --obvious way to do it.
之前我一直很好奇大部分人在用Python
写datetime
类型的时候,
都是用import datetime
+datetime.datetime(), datetime.date()
的写法,
我就一直不解,from datetime import datetime, date
+datetime(), date()
这样感觉更好啊?
而且后续的代码更短。
后来读到Kenneth Reitz
的Hitchhiker's Guide to Python
的时候我才明白,Explicit is better than implicit
的体现就是显式指定包名,
这样代码表现力就会更强,也更易读。
## Very bad
[...]
from modu import *
[...]
x = sqrt(4) # Is sqrt part of modu? A builtin? Defined above?
## Better
from modu import sqrt
[...]
x = sqrt(4) # sqrt may be part of modu, if not redefined in between
## Best
import modu
[...]
x = modu.sqrt(4) # sqrt is visibly part of modu's namespace
从学到这一点以后,
我就下定决心再也不用from datetime import datetime
了。
总结
Best Practice
这种东西,
看起来很美好,
用好了可以大大偷懒减少工作量。
但它有一个重要特性:Best Practice
从来不是试出来的,
而是思索、学习、择优得到的。
多加一个if
,多加一个机器,多招一个人,多加一点班
可能只能解决当下的问题。
平时多学习一个,
才能到了要解决问题的时候,
面临技术、业务、上线时间的多重压力,
优雅地使用Best Practice
解决问题。
总的来说,
为了偷懒 少干活提高效率,
我们又定下了这么些小目标:
- 多学习一个
Best Practice
- 学到了就用,能用精妙的方法就不用愚蠢的方法
- 通过思考来学习,而不是完全通过试错反馈机制来学习
毕竟编程风格可不能是散弹枪编程呀。