周末加班重构代码的几点感慨
上半年的时候在公司实习,做了一个基于django的度量衡工具网站,就是把数据从数据库里面抓出来,统计分析,然后生成各种各样的图表包括饼图、柱状图、线图、以及各种组合起来的比较复杂的图。需要支持前台事件响应,就是在图上进行点击拖动等操作的时候,会有对应的响应。比如说需要深入到饼图的更小粒度。整个网站的架构选用的是django,至于为什么选这个,原因无外乎:django对数据型的网站支持特别好;django是基于python的,这点尤其重要,python的开发相当敏捷,方便,对这种个人英雄主义的项目,尤其重要。前台图表都是基于js的,这是为了兼容的考虑,没有选取基于flash的比如基于flex的那些东东。我们选取的是highcharts插件。
前面这么多都是背景介绍,我想说的是在项目进行的过程当中,由于需求频繁变动,导致程序架构非常紊乱。由于是数据型的网站,最大的毛病在于参数的传递和解析上。前台js代码的参数的封装,url的拼接,后台参数的解析。函数形参的定义等等都是显式的完成,完全没有考虑可扩展性。恍然已经处于半离职状态几个月了,想想活干的不漂亮,总有点不爽,所以在上周末,抽时间去公司对代码进行了大规模的重构。虽然说前段时间轻轻的看了一下设计模式,但是自问没有到可以使用设计模式来解决问题的地步。主要有下面几个感慨:
在参数过多的情况下,一个很简单的办法,就是定义一个数组,或者python里面的字典。这样都能有效的解决问题,当然这些方法都行,但是我在弄的时候是把对象作为一个对象来定义的,主要基于的考虑是,项目的参数很多,而且从前台传入的时候有一个解析的过程。而且参数的格式在不同的地方也不一样,再者就是项目有些地方的计算量非常大,为了提高效率,需要将很多中间结果进行缓存,使用了memcache来缓存中间结果,memcache是一个key-value的内存缓存系统,速度快,支持分布式。为了将各个统计模块的结果进行缓存,需要将参数打包成一个key,以上种种问题,如果将参数定义成一个字典或者数组的话,是无法很好解决的,所以将参数定义成了一个对象,对象内置很多格式化的函数。这样就将对象传来传去。
使用对象作为参数,前面提到的问题都得到很好的解决,但是又会带来一个新的问题,我们知道,对象作为函数的参数的时候,实际上传入的是引用,意思是如果我们在函数内部对对象的内容进行修改的话,实际上会改变实参对象的内容。这一点又不满足要求了。可能你会说,为什么不在函数内部原样复制一个对象参数。我的确是这么干的。但是在python里面不能使用a = b的这种复制办法,python 提供了copy()来对一个对象进行复制,当然我使用的是deepcopy(),至于copy和deepcopy的区别,有个简单的说法是,copy只复制父对象,不复制父对象中的子对象,而deepcopy则是最彻底的复制,当然效率啊性能啊,会有一定的影响。
上面的问题解决以后,基本上后台的参数优化就只剩下体力活了。
关于memcache的好处,用过的人都知道,尤其是在大数据量和数据库交互的时候,我们可以将频繁的查询结果放到缓存中,这样频繁的查询可以直接从内存读取结果,能显著的提高用户体验,一种网上的说法是一台服务器,将memcache设为最大,永久不失效。然后专门作为缓存机器,memcache是天然支持分布式的,和hadoop类似,几台机器可以轻轻的配置一下就可以连接成一个大的缓冲池。
最后想说的就是python。python作为一门脚本语言,已经超出了常规的脚本语言的范畴,python在科研领域比如说科学计算,文本处理等方面都有对应的库,使用相当方便,个人认为这对那些非计算机专业的人来说,python可以说是他们的救星。他们可以用这个来搭建简单的web系统,当然也可以搭建很复杂的。可以用这个来做实验。结果展现也有很丰富的画图库。对计算机专业的人员来说,python敏捷开发的首选语言。当你无聊的时候想写点小程序实现一些很有意思的功能的时候,python将是您的首选。
这也难怪,有人会将python作为黑客必学语言之一。
最后引进不知道那位boss的话,life is short , you need python!