分类存档: 后端技术

Ruby学习(1) – Symbol(符号)总结

在Ruby的学习过程中应该不乏接触到Symbol,就是以冒号开头的变量名如 :tems_of_service,特别是在Rails中,更是大量使用Symbol。

这不乏让初学者感觉有些疑惑,疑惑的是Symbol有什么作用,什么时候使用Symbol才是正确的?以下根据最近学习的体会进行总结。

1、什么是Symbol

Jim Weirich:Symbol是有名字的对象

Austin Ziegler:An object that is a name

2、Symbol和字符串

Symbol和字符串的主要区别在于,内存的存储方式上。

符号 :a_symbol在多次使中引用的是同一个内存地址。

而字符串 “a_string”在多次使用中指向的是不同的内存地址,即每次都生成一个新的对象。

Symbol和字符串是可以相互转换的,一般来说使用Symbol的地方使用字符串来代替都是合法的。

可以通过以下方法进行转换:

:a_symbol.to_s #=>"a_symbol"

:a_symbol.id2name #=>"a_symbol"

"a_string".to_sym #=>:a_string

"a_string".intern # =>:a_string

3、Symbol的作用

第一是 节省内存的用量,提高性能

特别对于Rails如果不适用Symbol,某一个字符串可能会被使用很多次,在大访问量情况下节省的资源还是不可忽视的。

另外对于hash对象,如果使用Symbol也可以提高效率,因为使用字符串必须每次计算字符串的hash。

第二是 易读性

它使得语言的理解更加自然,如attr_accessor :a_name 我们很容易理解Ruby将生成一个以a_name为名字的访问器。

4、什么时候使用Symbol

引用Ruby黑客Jim Weirich的两句话:

如果对象的内容(字符创序列)总要,那么使用字符串。

如果对象的一致性重要,那么使用符号。

使用GH-Unit对iOS应用进行单元测试

单元测试的目的

  1. 保证代码的正确性
  2. 支持未来的代码重构

基础环境:

  • 使用苹果系统的电脑
  • XCode

GH-Unit是一个强大的单元测试框架,由Gabriel Handford开发,使用GH-Unit进行单元测试需要进行一些配置。

  1. 新建一个项目并添加一个测试目标(Target)
    我这里新建了一个“Window-based Application”,新建完成后先尝试“Build and Run”保证程序能正常启动,在Targets上右击选择“Add - New Target…”
    Add new target to project
    Target的名称可以命名为Tests或者类似的名字。
  2. 下载GH-Unit框架并添加必要的框架到项目
    下载地址:https://github.com/downloads/gabriel/gh-unit/GHUnit-0.4.28.zip
    解压缩后拖到XCode中,选择拷贝源代码到项目,并且目标选择为Tests
    Adding GHUnitIOS.framework
    打开Tests这个目标进行配置,设置目标依赖到第一个目标,添加CoreGraphics、Foundation、UIKit这几个框架。
  3. 检查“Framework Search Paths”
    检查“Framework Search Paths”这个参数是否指向GHUnitiOS.framework的父目录,一般默认已是正确的。
  4. 针对测试目标的“Other Linker Flags”添加“-Objc”,“-all_load”参数
  5. 修改Tests-Info.plist文件
    修改里面的“Main nib file base name”参数,将默认为“MainWindow”的值清空。
  6. 添加GHUnitIOSTestMain.m (http://github.com/gabriel/gh-unit/blob/master/Project-IPhone/GHUnitIOSTestMain.m)
    下载后拖到Other Sources中,选择拷贝到项目,并且选择目标为测试项目。
  7. (可选)创建Tests_Prefix.pch
    从原来的GHUnitExample_Prefix.pch拷贝一个文件并重命名为Tests_Prefix.pch,并使用XCode添加到项目中。
    修改Tests_Prefix.pch针对移动设备平台的话添加#import <GHUnitIOS/GHUnit.h>,添加后不用在创建的测试代码中引用库。
    最后修改Tests目标的配置文件,搜索GCC_Prefix修改为Tests_Prefix.pch。
  8. (可选)设置Makefile文件
  9. 创建测试
    为了便于源代码管理在项目目录下建立Tests,并导入到XCode中。
    在Tests组下添加一个测试类,用来测试配置是否正确,命名为“SetupTests”,从NSObject继承,不生成头文件。
  10. 运行测试
    选择Tests目标“Build and Run”,便可运行iPhone模拟器开始单元测试,若碰到问题请检查Tests-Info.plist配置是否正确。

参考资料:

http://gabriel.github.com/gh-unit/_installing.html

http://4arrowsmedia.com/2010/09/ghunit-setup/

Python应用:轻量级Web框架Quixote

缘起

Quixote是 由美国全国研究创新联合会(CNRI,Corporation for National Research Initiatives)的工程师A.M.Kuchling、Neil Schemenauer和Greg Ward开发的一个轻量级Web框架。和几乎所有的开源项目一样,Quixote也是为了满 足实际需要而出世的。

CNRI当时在进行一个名为MEMS Exchange的项目(http://www.mems-exchange.org/)。MEMS是微机电系统的缩写,制造一个MEMS设备往往需要多种制造设备,单个工厂可能无 法提供所需的所有设备。因此,MEMS Exchange项目就是要整合起多家制造厂的资源,利用互联网派单和追踪制造过程,形成一个分布式的MEMS设备制造网络。

起初,他们做了一个Java版的客户端程序提供给用户,但他们发现,没有人愿 意使用这个客户端程序,大家还是习惯性地用邮件发送加工过程。最终他们认识到,虽然客户端的表现力更强,功能也更完整,但相比起要下载一个庞大的程序,用 户更加愿意使用他们每天面对的浏览器来做事情。于是,他们决定改到Web界面上来,要做一个Web应用。但是用Java的servlets开发Web应用 是一件非常低效的事情,所以他们选择了Zope(和现在不同,在1999年,Python的Web应用框架没有什么选择的余地,基本上是Zope一家独 大)。3个月的开发之后,他们得到了一个运转良好的系统。

然而,Zope带来的快乐并没有持续多长时间。几个月后,他们想提供更加复杂 一点的界面,却发现用Zope写的代码难以维护和调试,在浏览器的文本编辑框里写代码也实在不是什么好的体验。由于当时除了Zope之外也没有什么别的 Python Web框架,他们决定:自己写一个!在2000年,编写一个新的Web框架是类似于向风车挑战一样的事情,开发团队自嘲地用堂吉诃德的名字命名这个框架:Quixote。

Quxiote的特点:

一、目录式的URL分发规则

所有的的Web框架要解决的第一件事,都是如何将用户的URL请求映射到程序上去。与ROR和Django这类基于Route和正则匹配的框架不同。Quxiote使用目录的方式逐层查找来实现的,最后请求将被映射到一个类的方法上。

假设你有一个应用是app。如果用户请求http://localhost/hello/,Quxiote将会将这个请求映射到app.hello._q_index()这个方法上,_q_index()方法是Quixote默认的根路径方法。如果用户请求http://localhost/hello/world, Quxiote将会将这个请求映射到app.hello.world()这个方法上。如果你需要为用户的访问设置权限,你只要实现相应目录下的_q_access()方法。

二、最接近Python的模板语言

Web 框架的模板一直是备受争议的环节,因为不同的模板框架提供了不同的模板标签,这提高了开发人员的学习成本。

所以Quxiote提倡用Python来写模板,最大程度的使用已有的Python编程能力。

Quxiote的模板语言叫做PTL(Python Template Language),PTL的模板文件以.ptl结尾,需要执行Quxiote的quixote.enable_ptl()之后Python才会像解析.py一样解析.ptl文件。PTL文件将html代码嵌入到Python代码中,并进行切块。这样你能在模板中随意的书写Python的代码来实现模板。这和现在比较流行的模板实现机制恰好相反。本人还是比较支持,以html作为模板文件,再用Python来解析html中的标签。这种方式更加清楚,可维护性更高。

三、显示标记,拒绝魔术

在The zen of python 中有一句话

Explicit is better than implicit. #显示的说明要比不言明的好。

所以如果你在Python命令行中输入:
import this
便可以看到有趣的提示,这便是Python编程所坚持的哲理

在Quixote中需要公布出来的路径需要配置在一个_q_exports=[]列表中。配置的内容即方法名称。

Quixote的优点:

  1. 简单,Quxiote的全部代码量为7000行左右,而且包含了大量的注释,如果去掉注释,则只有大约2500行代码。这也是我选择Quixote来学习Python的原因,因为你能容易通过阅读代码看到Quxiote做了什么。
  2. 高效,这一方面得益于Python语言本身的特点和Quxiote简单的架构,另一方面得益于用PTL模板。
  3. 安全,这也得益于Quxiote的简单,使得我们能很好的控制框架,并且它提供了一些HTML输出方法,保证了HTML输出的安全。
  4. 自由,开源就是好!
  5. 久经考验,历史悠久,在大量的企业应用中被证明是一个高效,灵活,稳定的框架,最著名的应用就是豆瓣(http://www.douban.com),我也是从豆瓣的架构中知道了Quxiote。

Quxiote的缺点:

  1. 没有内置的数据库支持和安全验证机制
  2. PTL适合程序员,并不适合美工参与前端代码的编写和修改
  3. 内置服务器不能很好的支持Debug,如果使用simple_server.py来调试虽然可以跟踪到,但是如果修改代码必须重启服务器,如果使用cgi,虽然修改代码后不用重启服务器,但是无法跟踪到代码,并且Quixote提供的Session支持会失效,除非使用Session持久化。
  4. 没有内置WSGI的支持,WSGI是Python PEP中提出的规范即(Web Server Gateway Interface)这个规范被广泛应用,使得Python Web Server 和 Python Web Framework能很好的兼容。

总结:

首先,对于想学习Python Web开发的人来说,通过使用Quixote将会带来很多的好处,Quxiote很接近Python,不会像Django和Pylons虽然提供了很好的开发流程,也能很快的上手,但是很难了解到这些框架到低做了什么,至少对于初学者来说,使用这些框架并不太适合。而Quixote代码量少,但包括了很多核心功能的实现,如Request,Response,Session,WebServer等。

其次,Quixote的简单使得Quixote非常灵活,也意味着你需要做更多的二次开发,所以想用Quixote做出好的网站,还需要有一定的Python基础。如数据库开发,Python多线程应用等等。

由于Quixote并没有为我们提供数据库的支持和安全验证机制,但是你同样可以使用一些已有的框架来解决这个问题,如SqlAlchemy。SqlAlchemy可以说是Python的ORM标准,就像Java中的Hibernate一样,所以是不二的选择,很多人没有选择Django,也是因为Django的ORM解决方法并不能让人满意。

另外本人并不使用Quixote的PTL,毕竟时代的发展已经有更好的技术来替代他了,比如Python的模板引擎Mako,豆瓣在新的开发中也部分使用了Mako。

SqlAlchemy和Mako的介绍以及和Quixote集成的文章也会陆续推出。

【扩展阅读】

The zend of python :http://www.python.org/dev/peps/pep-0020/

Python Web Server Gateway Interface:http://www.python.org/dev/peps/pep-0333/

Quixote White Pager:http://www.quixote.ca/overview/paper.html

QuixoteCookbook:http://www.quixote.ca/qx/QuixoteCookbook

Oracle查询指定记录数的奇怪问题

首先看一段代码:

dbo.getPreparedStatement("select * from (select * from Entity_HotLink wherehotLinkSortId = ? and hotLinkStatus = ? order by hotLinkOrder ASC, lastModifiedDate DESC) where ROWNUM <= ?");
dbo.pstmt.setInt(1, hotLinkSortId);
dbo.pstmt.setInt(2, hotLinkStatus);
dbo.pstmt.setInt(3, count);

环境1:windows + oracle 10g 正常
环境2: Redhat E5.2 64bit + oracle 10g(RAC集群) 查询执行,但是返回记录数只有10条,不管你的count有多大。

改成

dbo.getPreparedStatement("select * from (select * from Entity_HotLink where hotLinkSortId = ? and hotLinkStatus = ? order by hotLinkOrder ASC, lastModifiedDate DESC) where ROWNUM <= " + count);
dbo.pstmt.setInt(1, hotLinkSortId);
dbo.pstmt.setInt(2, hotLinkStatus);

则都能正常查询记录。

此问题比较奇怪有问题再研究研究。

Python2.6.4 配置Mysql问题

操作系统:window xp sp3
python版本:2.6.4
mysql:5.1
MySQLdb:MySQL-python-1.2.2.win32-py2.6.exe

在Python上配置mysql会碰到以下问题:
1、ImportError: DLL load failed: 找不到指定的模块。
解决方法:下载libmmd.dll(附件)和libguide40.dll(附件)两个dll文件并复制到python安装目录的Lib\site-packages下,或者windows/system32下。
参见:http://sourceforge.net/forum/message.php?msg_id=5613887

2、DeprecationWarning: the sets module is deprecated
from sets import ImmutableSet
解决方法:
1) file “__init__”, replace:

from sets import ImmutableSet
class DBAPISet(ImmutableSet):

with

class DBAPISet(frozenset):

2) file “converters.py”, remove:

from sets import BaseSet, Set

3) file “converters.py”, change “Set” by “set” (IMPORTANT: only two places):

line 48: return set([ i for i in s.split(',') if i ])
line 128: set: Set2Str,
参见:http://sourceforge.net/forum/message.php?msg_id=5808948

资源下载:http://i.19830102.com/archives/164

FastDFS试用

环境:Ubuntu 9.10 64bit
FastDFS 1.21

FastDFS总体来说安装比较方便,配置简单。
安装可参照官方文档
./make.sh
./make.sh install
如果无法执行这些命令请先安装gcc
sudo apt-get install gcc
另外在Ubuntu系统上安装时需要将make.sh最后一段if去掉,否则./make.sh install时会报错。

接着新建一个数据存放的目录
sudo mkdir /data
sudo chown user:group /data

然后配置参数,分为两部分一部分是storage.conf另外是tracker.conf
文件在/etc/fdfs中
启动tracker
sudo /usr/local/bin/fdfs_trackerd /etc/fdfs/tracker.conf
重启tracker
sudo /usr/local/bin/restart.sh /usr/local/bin/fdfs_trackerd /etc/fdfs/tracker.conf
启动stroage
sudo /usr/local/bin/fdfs_storaged /etc/fdfs/storage.conf
重启stroage
sudo /usr/local/bin/restart.sh /usr/local/bin/fdfs_storaged /etc/fdfs/storage.conf

如果启动时报找不到http.conf则sudo touch /etc/http.conf再启动就好了

monitor
sudo /usr/local/bin/fdfs_monitor /etc/fdfs/storage.conf

更换storage的IP后,需要删除以前的IP信息,使用fdfs_monitor命令:
/usr/local/bin/fdfs_monitor config_file [list|delete [storage_ip]]

测试上传
/etc/fdfs/storage.conf upload /usr/include/stdlib.h

Ubuntu 9.10的163源速度很快

deb http://mirrors.163.com/ubuntu/ karmic main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ karmic-security main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ karmic-updates main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ karmic-proposed main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ karmic-backports main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ karmic main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ karmic-security main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ karmic-updates main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ karmic-proposed main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ karmic-backports main restricted universe multiverse

Linux下的链接

Linux下的链接一般使用ln命令创建
以下是ln命令的说明:
指令名称 : ln
使用权限 : 所有使用者
使用方式 : ln [options] source dist,其中 option 的格式为 :
[-bdfinsvF] [-S backup-suffix] [-V {numbered,existing,simple}]
[--help] [--version] [--]
说明 : Linux/Unix 档案系统中,有所谓的连结(link),我们可以将其视为档案的别名,而连结又可分为两种 : 硬连结 (hard link)与软连结(symbolic link),硬连结的意思是一个档案可以有多个名称,而软连结的方式则是产生一个特殊的档案,该档案的内容是指向另一个档案的位置。硬连结是存在同一个档案系统中,而软连结却可以跨越不同的档案系统。
ln source dist 是产生一个连结(dist)到 source,至于使用硬连结或软链结则由参数决定。
不论是硬连结或软链结都不会将原本的档案复制一份,只会占用非常少量的磁碟空间。
参数 :
-f : 链结时先将与 dist 同档名的档案删除-d : 允许系统管理者硬链结自己的目录-i : 在删除与 dist 同档名的档案时先进行询问-n : 在进行软连结时,将 dist 视为一般的档案-s : 进行软链结(symbolic link)-v : 在连结之前显示其档名 -b : 将在链结时会被覆写或删除的档案进行备份-S SUFFIX : 将备份的档案都加上 SUFFIX 的字尾-V METHOD : 指定备份的方式–help : 显示辅助说明–version : 显示版本
范例 :
将档案 yy 产生一个 symbolic link : zz
ln -s yy zz
将档案 yy 产生一个 hard link : zz
ln yy xx

对于一些特殊情况ln会达不到你想要的效果可以使用
mount –bind olddir newdir
他和普通mount的区别是可以将一个目录以像设备一样挂载到另一个目录上而ln只是创建了一个符号链接,本质上还是属于一种文件。

Spring 和 Hessian的兼容性

今天试了一下Hessian和Spring的整合。
发现有兼容性问题。
Hessian3.15 3.16使用一代协议 Hessian3.2及以上使用的是二代协议。
而Spring2.56只支持一代协议,所以做多只能使用Hessian3.16如果使用更新的版本会报错。
支持更新的Hessian版本只能等Spring3了。

在Linode上配置自己的VPN

Linode每个月有200G的流量,一般来说是用不完的。
正好看到网上有人把Linode拿来做VPN所以就试试,用来翻墙的确不错。

更新软件包数据
apt-get update

安装pptpd
apt-get install pptpd

设置本地地址和远程地址范围
修改/etc/pptpd.conf文件
localip 192.168.0.1
remoteip 192.168.0.234-238,192.168.0.245
注意:如果是Ubuntu的系统此处请将logwtmp注释掉,否者无法登录vpn
网上的一些方法说在/etc/ppp/pptpd-options添加logfile /var/log/pptpd.log 尝试过并无效。
所以先注释掉。

添加VPN用户
修改文件/etc/ppp/chap-secrets
username pptpd password *
分别代表用户名,服务,密码,允许IP

添加DNS
修改文件/etc/ppp/options
ms-dns 8.8.8.8
ms-dns 8.8.4.4
上面两个是公用的DNS地址,好记。

编辑/etc/sysctl.conf文件,找到”net.ipv4.ip_forward=1″这一行,去掉前面的注释。
net.ipv4.ip_forward=1
运行下面的命令让配置生效。
sysctl -p

重启pptpd服务
service pptpd restart

开启IP转发
/sbin/iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j MASQUERADE

配置完成 可以在windows的网络连接中添加vpn了!