低扇出,高扇入
我承认,判断一段代码的好坏,有很多主观的因素,你大可以来批评我,『你看不惯别人的代码,别人还看不惯你的代码呢,既然如此,何不和和气气,多包容包容』。我的回答是『No,不好就是不好,我在批评的时候,除了主观因素,确实还有一些客观标准的,不信拉倒』。
我承认,判断一段代码的好坏,有很多主观的因素,你大可以来批评我,『你看不惯别人的代码,别人还看不惯你的代码呢,既然如此,何不和和气气,多包容包容』。我的回答是『No,不好就是不好,我在批评的时候,除了主观因素,确实还有一些客观标准的,不信拉倒』。
经常,你可能会觉得,原来代码写得不好,想要重构,但是重构的时候,是先把原来的代码拷贝过来,确保不影响老的功能。然后新功能做好后,逐步修改老功能。最终实现完成重构,代码得到优化。
上面的故事和计划很美好,所以,它们十有八九不能被完整执行,后果往往就是,拷贝了一堆代码,老代码大摇大摆继续运行,新功能不断压来,系统里多了一堆代码的拷贝。这时候,只要祈祷不要出bug就好,不然就是双倍的工作量,恶劣的,还会造成数据不一致,新老代码操作数据有细微差别就会有这种情况,一般差别很细微,还特别不易发现。
如果相信我,一个一线写了五年代码的人,那就请相信,任何时候,都不是你拷贝代码的借口,哪怕是打着『重构』、『优化』这种冠冕堂皇的借口,也不可以,哪怕有 deadline,也不可以,哪怕时间紧也不可以,刀架脖子上了,那也不可以,那时候还写个屁代码啊?还不快跑。
拷贝代码,只会增加你自己的工作量,或者增加别人的工作量。不想越做越多的话,别那么干。
重构是一种艺术,如果你真想完全不破坏老的功能,正确的做法,是为老功能编写测试用例,然后直接改代码,抽取也好,剥离也好,就是不能拷贝,然后通过测试用例来判定,老功能是否受到破坏,而不是不敢动,通过拷贝来给自己做个沙盒,这一开始就是没有自信的表现,不能凭感觉,要靠科学。
2015年上半年,是牛市的半年。其实从去年开始,就陆续在牛市了,会玩的人,已经赚得很开心了。不能免俗的,我也进去了。现在来写这个文章的时候,我已经持续交易一两个月了。这时候出来写点感受,算是对自己心态的一个记录。
无论是在以前的团队,还是在现在的团队,都有人主张抽象出所谓的Service层,他们认为Model只负责跟数据库沟通,不应该混杂过多的东西,而同样也不赞成在Controller的Action里面,做太多事情,那样不利于复用。而他们赞成的方案,就是『抽象』出一层所谓的Service层,从而实现代码的复用。
而我通过观察他们具体的实现的代码,发现,这是一个很糟糕的想法。因为很少有人能忍住诱惑不去滥用。
在PHP里面,public static function其实就是最最原始的函数式编程模式的全局函数而已。任何一个软件里,如果全局函数满天飞,肯定不是一个『抽象』优秀的系统。如果不是绝对克制,那程序员会忍不住在任何地方,调用全局函数,甚至,只要一能复用代码,就忍不住去调用一下全局函数,得到好处后,就会进一步把更多的东西变成全局函数,而最后发现,所有的业务逻辑都在全局函数里了。
这种做法,其实就是饮鸩止渴而已,在单人工作模式下,绝对自我控制的人,你还能采用这种方式,但是一旦到了团队合作的时候,你很难阻止同伴滥用,哪怕滥用了一次,这种做法就会无休止蔓延,就好像破窗户理论说的,整个大楼一破再破,直到崩塌。
我举个简单例子,因为在全局函数里,你可以调用任何全局作用域的对象,当你那么做了以后,任何地方哪怕能复用到一部分这个方法,你就会忍不住去调用,因为是全局函数,总是可以被调用的,所以调用点的作用域,也全局化了。最后,整个系统就遍布着全局函数了。
可能说得比较绕吧,但是有个大原则我是信奉的,也希望读者你能看懂:全局函数和全局变量是邪恶的,我们应该拼尽全力去减少全局变量和全局函数,而不是增加他们。如果你想实现一个所谓的Service层的时候,请不要使用public static function,因为那根本就是全局函数。
另外,重申一下,不是说抽象Service层有多错误,我真正反对的是,使用public static function去进行所谓的抽象,那对抽象毫无帮助,说明你的抽象能力还停留在抽象一个函数的能力。
在我最新任职的团队里,我们采用Git正式作为我们团队开发管理的工具。我们使用Git来做版本控制,研发管理,和线上部署。我们将Git的版本库直接作为代码目录,来存放线上代码,发布的方法,就简化成了,将线上环境的代码目录,checkout 到指定的 tag,简单,快捷。
这个方法执行了一段时间后,发现一个新的烦恼,就是中央版本库的tag数量会变得非常多,多的时候,达到300多个,这其实也没什么了不起,但是我们自己采用gitlab来搭建自己的中央版本库,这个gitlab,还是很多bug的,当tag多了以后,整个网站都呈现出不是特别正常的样子,所以,就需要保持较少的tag列表,让网站保持比较高的性能。然后我就有了一个动机,就是删除远端的tag列表。
我用Google 搜了 how to delete git tags batch,发现老外的说法大概是,bulk delete,哈哈,英语不行啊。
无非就是shell下的一些做法,感觉实际使用上也够了。
首先就是找到远端要删除的tags列表,关键是用对指令。1
2
3
git show-ref --tag
这个指令可以列出所有的远端的tag列表,然后就是shell下的一般处理手段了。1
2
3
git push origin :
如上指令,会致使远程的tag被删除。用管道一连接,万事大吉。1
2
3
git show-ref --tag awk '/(.*)(\s+)(.*)$/ {print ":" $2}' xargs git push origin
上面的指令就是拼接完整的指令了,不过这个指令,会删除远端所有的tag,慎用,如果希望删除符合条件的,应该修改awk指令的正则表达式。
删除完了远端的tag,本地的tag,删法还不是太一样,不过原理相同。1
2
3
git tag grep "v1.1.0.\d$" xargs git tag -d
举个例子,上述命令删除本地所有 v1.1.0.x 的tag,这个指令,会最多删除10个tag。
在安装有些vim插件的时候,需要Vim支持Python,比如YouCompleteMe,但是,最近升级到Jessie后,发现,默认的vim,是不支持Python的,于是在网上搜索了一下,如果需要vim的二进制版本带有Python支持的话,应该安装一个叫 vim-nox 的包,其介绍为:
Vi IMproved - enhanced vi editor - with scripting languages support
就这样。
以前,我使用 Windows 作为自己的工作系统,后来,改用 Mac 作为自己的主要工作系统了。
在 Windows 下,快速搭建*AMP 环境,使用 xampp 或者 WAMP 之类的集成包,会一口气装好所有需要的软件,而在 Mac 下,相应的,做得比较好的是 MAMP,我选用的是与之对应的收费版本 MAMP Pro,总体差别不大。
程序员圈子里流传着一个段子,说编程只有两个难题:缓存失效和变量命名。而我们中国有句古话,说:名不正则言不顺。这里面都提到了一个至关重要的问题,就是“取名字”。我认为,名字问题之所以如此重要,是因为,“名字”其实是对客观世界中实体的符号化表示。而这些符号,成为人类语言描述和思维的主要原料。如果名字有问题,就会严重干扰人类的思维。
目前的计算机,还只能按照完全确定性的方式去运行,而与之相对,人类的思维运转却存在极大的不确定性和任意性,如果说,编程实践总是由一个人完成,写出来的代码即可以运行,而不再需要阅读和与人合作,各种各样的规范,根本不需要存在;而事实恰恰相反。约束是为了更大程度的自由,所以,编码规范、命名规范,就是为了给所有共同合作的程序员一个基础。这个基础,可以帮助大家去提高效率,促进理解。
在最近两年的编码实践中,我感受到,数据库因为其特殊性(主要是总以服务形式出现,通过SQL语句操纵),其命名规范,别具一格,并不完全遵循一般编码规范的命名规则。而且,有时候,特意分开,反倒可以提高效率和促进理解。后面,我就展开列举一下,我们在实践过程中,习得的一些经验,这些做法未必是大家实践的准绳,但是希望可以给读者提供一个有效的参考。
tbl_前缀,可能是为了与字段名区别开来,或者自动转化成变量名的时候,可以清楚地知道这个变量名来自于数据库,当然,实际上,这个前缀并没有显示出过多的价值,因为表名直接自动转化为变量名的机会比较少(分库分表的时候,表名容易成为变量名),另有一些方法,使得表名很容易区别于字段名和变量名v_作为前缀,有助于程序员对数据库的理解和预防错误(比如,看到v_就不必尝试去update其中的字段了)F,感觉没什么用orderalias,例如,很多表都有id、type、status等等字段,在联表写SQL语句时候,为了防止它们的混淆,经常要做额外的工作_on,在时间(DateTime)字段后面加_at,也可以是加date或time作为后缀,关键是全团队的认可和保持一致我试图去搜索或寻找一些所谓的数据库命名方面的最佳实践,有些网友会推荐,采用微软SQL Server的范例数据库中的命名规范,并作出了相应的分析,但是我简要阅读了一下,凭直觉是无法比我们现在的做法带来更多的好处的。
另外也参考了一些StackOverflow上面高支持率的答案内容,感觉国外这个领域,也没有一个相对权威的说法,所以,我个人觉得,这个里面是如人饮水冷暖自知的一个情况,各个团队,还是要找到跟自己团队比较契合的一个规范。
不过,有一点我是相当确定的,就是有规范一定好于没有规范,现在一般都是团队作战了,规范的约束,可以提高整个团队的效率,避免了一些没有必要的学习成本。
参考:
http://justinsomnia.org/2003/04/essential-database-naming-conventions-and-style/
Git——以及所有一切的版本库——的核心目标,就是保证代码不会丢失。我所熟知的两个版本控制工具——SVN和Git——都是通过提交代码(commit)来实现这个目标的。
虽然我反对使用SVN来类比Git,但是,如果仅是为了强调它们的“不同”,而进行比较,我觉得还是有助于理解的。
SVN使用过程中,版本仓库是在云端的,程序员的个人电脑上,只是一个工作副本,或者叫代码暂存,如果写好的代码,没有被送到云端的版本库,就意味着有潜在丢失的风险。所以,SVN的提交(commit),其本质,就是将代码从本地电脑传送到云端服务器,这个过程,我们称之为“入库”。
说实在的,Git我已经学习了很久很久,从最开始的,零星的学习,然后偶尔使用,到现在成为公司的唯一版本控制方式,断断续续没有两年,也有三年。Git官网上写着,简单易用(easy to learn),我就是被这四个字骗了,开始用上了Git。现如今,它已经成为一种避无可避的工具了,必须学会。
要开始上手使用Git,可能真的是很简单的事情,如果你翻开一些成体系的文档或者书籍,可能上来会教你使用git init命令。这个命令的目的是创建一个新的git版本库。但是,就我个人的经验来看,一个新人,接触版本控制系统,可能第一件事情,往往是融入一个开发团队,接手一块业务,然后开始贡献代码,不太会是上来先建立一个版本库。