Archive for the ‘software’ tag
新年逛书店
因为最近想尝试一些OpenGL ES的开发,所以想找本入门+进阶的书。在amazon上找到几本,但仅凭preview和review没有办法确定这些书是否适合我,于是去书店逛了逛。
到了书店的计算机部,有好多书吸引了我,有的是因为主题,有的则是因为别致的设计。
令人震撼的骨董计算机之美
摄影和计算机让人联想起什么?如果你想到的只是PS,那么你绝对应该看看O’Reilly的这本 Core Memory : a visual survey of vintage computers (目前还没有中文版,我称之为《Core Memory:骨董计算机之美》),这是摄影艺术对于计算机之美的诠释、对于机器和人类智慧之美的诠释!
我从time.com上找来了一些书中的图片,在这里引用两幅。
这本书是2007年出版的,这么久了,在国内却一直不知道…… Read the rest of this entry »

架构师的选择(觉悟)
原文链接:アーキテクトの選択(あるいは覚悟)
架构师的工作大部分时间都是在“做选择”,这些选择都是在一切发生之前所做出的,因此,一旦决定就不能更改了。
架构师所要选择的是静态的结构。方案一旦确定,就开始转入退化过程。随着时间的推移,系统的适应性会变差,对做出的决定进行修改往往要付出巨大的代价。
当然,项目经理对于进度计划以及项目人员体制等方面的安排也属于“事先选择”。但是,这些选择对象都属于动态的过程。
动态的过程能够随着时间的推移适应其过程中出现的变化。包括敏捷等迭代式过程在内的开发过程,它们都推荐在开发过程中设立短期目标并根据实际作业情况做出调整。这是非常有效的方法。动态过程承认事先选择中所发生的过失和偏差,且允许在事情发生之后做出改变。
有这么一说:“Good managers do things right (优秀的管理者会做正确的事)”,项目经理所做的是把握事先选择(计划)和事后情况(实际)两者之间的偏差,针对这些偏差对各种各样的参数做出调整,将项目的发展方向始终沿着预定的轨道不断进行修正。
然而,架构师的选择却是静态的结构,敏捷的推进方式无法适用于这些静态结构。

isHUD v0.2发布声明
isHUD v0.2发布声明
目的
作为一个多语言的Mac OS X用户,我使用系统默认的快捷键(Command+空格, Option+Command+空格)切换输入法。但是,当我按下Option+Command+空格(即选择下一个输入源)的时候,系统并不会出现输入法选择框(按Command+空格时候出现的那个列表)。当启用的Lion的全屏模式的时候,要确认当前所使用的输入法十分不便。
于是isHUD诞生了!isHUD是“input source HUD”的缩写。
有了isHUD,每当切换输入法的时候,屏幕中央就会出现一个HUD窗口,提示选中的输入法,这样,你无须移动视线就能知道所选的输入法了。
如果你想要更快捷地切换输入法,那么这篇博客也许对你有用。其中也提到了为什么要做isHUD。

OS X键盘应用技巧:一键切换输入法
工作的时候,我常常需要在多个输入法之间切来切去。
Mac默认的输入法切换是Command+空格和Option+Command+空格。虽然默认也没有什么不方便的,但是,我发现在我的键盘上有个键几乎从来没用过,那就是右侧的Option键,于是我想能不能通过这个键实现一键切换输入法呢?

OS X键盘使用技巧:自动根据应用程序切换F1~Fx功能键
Mac用户应该都知道,就像下面这张图片那样,Apple的键盘最顶上一排默认情况下是多媒体控制键,而不是传统PC上所使用的F1~Fx功能键,要使用功能键的时候需要配合Fn键。
对于原生的Mac应用来说,这并不成问题。但是如果像我这样时不时要用到终端(iTerm2)、虚拟机什么的,那么在这些环境中能无须使用Fn键就能得到F1~Fx键就会方便不少(比如vim的快捷键绑定)。当然,你可以通过“系统偏好设置”将功能键默认修改为传统的Fx键,不过这样的话,在Mac应用中调节音量,打开mission control什么的又不太方便了。
经过一番搜索,我找到了圆满解决这个问题的方法。答案就是——Palua,一款自动切换功能键行为的工具。
Palua的图标已经非常直白地解释了它是做什么用的了。下面就简单介绍一下自动切换功能键的设置方法。安装好Palua之后,就能在系统菜单栏中看到其状态指示图标了。
要让Palua根据应用程序自动切换工作模式,需要进入其偏好窗口增加一些配置。很简单,看图,一目了然!
首先,要启用“Smart Mode”。然后,在应用程序列表中添加需要的应用程序,再设置对应的功能键的默认行为即可。完成后立即会生效,把应用程序开起来试试,方便多了吧~
最后,别忘记将Palua设置为开机自动启动。
美中不足的是,Palua并不是免费工具,在App Store上的价码是$0.99,不过只要花不到1美元就能解决问题的话,对于有需要的用户来说也不是很贵啦,毕竟有了它确实很方便!

利用mock发现接口
引言
前几天,《Mock Roles, not Objects》一文的日语版《ロールをモックせよ(对角色进行模拟)》公开发表了。这是篇发表于2004年的论文,作者阵容相当豪华,他们是:Steve Freeman、Nat Pryce、Tim Mackinnon、Joe Walnes。另外,Steve Freeman和Nat Pryce还是《Growing Object-Oriented Software, Guided by Tests (Addison-Wesley 大师签名系列)》(即GOOS)的作者,《Mock Roles, not Object》可谓GOOS的思想根基。
在这篇文章中,我想就《Mock Roles, not Object》(以下略称为MRnO)所提到的使用Mock的基本思想,顺着GOOS的思路继续深入挖掘一下。 Read the rest of this entry »

网页中跨域iframe避免相互刷新死循环的方法
最近在做的系统,需要与客户的网页集成,因此牵涉到了跨域访问的问题。所以使用了大量的iframe绕过浏览器的安全策略。
由于跨域系统的安全限制,这些iframe之间是不能相互通信的,需要靠onload事件和父窗口进行交互,而iframe的刷新动作则须由父窗口控制。
其中遇到了一个有意思的问题。大致是这样的:页面打开时,用户没有登录系统,所有的iframe加载后处于未登录状态,点击任意一个iframe,系统会弹出登录画面,登录系统后,需要重新加载这些iframe,从而实现登录状态的同步。
如下面2张图所示:


于是,我在父窗口中写了这样的jquery脚本:
function refresh() {
__self = $(this);
$('iframe.myDomain').each(function(){
if($(this).attr(id) != __self.attr(id)) {
url = $(this).attr('src');
url = url.replace(/\?rand=.*$/, '?rand=' + Math.random());
$(this).attr('src', url);
}
});
}
$('iframe.myDomain').each(function(){
$(this).bind('load', refresh);
});
每当onload事件发生的时候,refresh函数会被触发,然后就会更新其他的iframe。但是,这样做有个重大的问题!如下图所示,当其他的iframe刷新完成的时候,同样会产生onload事件,此时,refresh再次被触发,又去刷新其他的iframe,产生了连锁反应,整个加载动作陷入了死循环!

为了避免这样的死循环,我们需要让接受到刷新指令的iframe在重新加载页面后不向其他iframe再次发送刷新指令,同时又要让其自身做好接受下一个刷新指令的准备。实现的方法很简单,只要稍稍修改我们的js代码即可。
function noRefresh() {
//不触发任何动作的onload事件处理函数
//重新绑定事件处理函数,为下一次处理onload事件做准备。
$(this).unbind('load');
$(this).bind('load', refresh);
}
function refresh() {
__self = $(this);
$('iframe.myDomain').each(function(){
if($(this).attr('id') != __self.attr('id')) {
url = $(this).attr('src')
url = url.replace(/\?rand=.*$/, '?rand=' + Math.random());
//将待刷新的iframe的onload处理函数重新设置
//其自身刷新后,调用noRefresh,防止刷新事件死循环
$(this).unbind('load');
$(this).bind('load', noRefresh);
//现在,刷新时就不会引起连锁反应了。
$(this).attr('src', url);
}
});
}
$('iframe.myDomain').each(function(){
//初始化的时候,关闭所有的onload事件
$(this).bind('load', noRefresh);
});
OK,问题解决!

最近安装新工作换进的问题总结
配置新的Ubuntu工作机的时候,遇到了些问题,在此总结一下。
A. q4m无法正确编译。
这是由于gcc的版本过高引起的(默认安装的是gcc-4.4)。解决方法如下:
-
安装gcc-4.1:
1$ sudo apt-get install gcc-4.1
-
执行configure的时候用如下的参数:
1
2
3$ ./configure --with-mysql=/usr/local/src/mysql-dfsg-5.1-5.1.41 \
CPPFLAGS=-I/usr/include/mysql \
CXX=g++-4.1
B. evince打开pdf后,左边的目录出现乱码。
原因是由于apparmor禁止evince访问我自定义的字体路径(/fonts),参考了launchpad上的讨论,解决方法如下:
-
修改安全规则,编辑/etc/apparmor.d/usr.bin.evince,加入对字体目录的访问权限:
1
2
3
4
5
6/usr/bin/evince {
#include <abstractions/evince>
#加入下面这2行
/fonts/ r,
/fonts/** r,
#后略 -
重新启动apparmor,此后再启动evince,打开pdf即可:
1$ sudo /etc/init.d/apparmor restart
C. MySQL Workbench 的sql编辑窗口出现乱码
原因不知道,解决方法很简单,只要打开Preferences -> Appearance,删掉Editor的字体名称即可。(汗,之前试了很多字体,都没成功……)

Equinox p2笔记
Equinox p2是Equinox的组件之一,极大增强了基于Eclipse的包管理功能。
引入p2之后,典型的eclipse目录结构如下:
eclipse/
configuration/
config.ini
org.eclipse.equinox.simpleconfigurator/
bundles.info
dropins/
features/
p2/
plugins/
eclipse.exe
eclipse.ini
...
- p2
目录用于存放p2自身的配置文件 - bundles.info
保存的是安装的插件列表,这个文件由p2维护。有时因为开发需要,也可以手工修改(不建议这么做)。 - dropins
向下兼容用的插件目录,对于无法使用p2安装的插件,直接扔进去就能使用。后面会详细说明。
dropins
p2提供了一种监视目录机制(watched directories),能够自动从被监视的目录中安装及卸载插件。dropins是默认的监视目录。p2在加载dropins目录中的插件时,能够自动解决依赖关系。需要特别注意的是,如果通过p2升级一个安装在dropins目录中的插件,则新版本会安装在eclipse/plugins和eclipse/features目录中。
dropins目录中的插件可以以多种目录组织方式部署,具体可以参看Supported dropins formats。
此外,还可以让多个eclipse共享一个dropins目录,具体的做法在《使用 Equinox p2 简化 Eclipse 插件的安装》有详细介绍。
Bundle pooling
引入p2前,共享插件时间很麻烦的事情,需要通过links的方式。p2支持bundle pooling的方式共享插件包。避免因磁盘上重复包太多引发的一系列管理和空间浪费的问题。
关于bundle pooling的例子,可以参看Bundle pooling
参考资料

OSGi 初体验
最近开始入门OSGi。找到一本《Modular Java —— Creating Flexible Applications with OSGi and Spring》,只有200多页,先从简单的开始吧!
之前对OSGi一直没什么清晰的概念,而这本书里一开始就给了OSGi一个很形象的比喻:
OSGi is sometimes described as “SOA in a JVM.”
在模块化方面,OSGi相对于传统的JVM,有显著的优势:
- Bundle is given its own class space (Bundle运行于独立的类空间之中)
基于这个特性,多个版本的bundle可以在运行时并存。 - 动态模块化,OSGi平台管理bundle的声明周期。可以在运行时动态安装、启动、停止、卸载bundle。
但有一点必须强调:与任何技术一样,OSGi也不是银弹。OSGi仅提供了一种更为灵活和丰富的模块化架构的平台,而真正高质量的模块化设计依然需要设计师遵循了模块化设计的思想。








