Read Sean

Read me, read Sean.
posts - 508, comments - 655, trackbacks - 9, articles - 4

2005年3月22日

不知道从什么时候开始的,tsocks在Mac下面安装要费些周折,brew官方和曾经一度存在的第三方tap都不再支持直接brew install,需要手工创建formula。过程倒也还OK:

vim /usr/local/Library/Formula/tsocks.rb

require 'formula'

class Tsocks < Formula
  # The original is http://tsocks.sourceforge.net/
  # This GitHub repo is a maintained fork with OSX support

  homepage 'http://github.com/pc/tsocks'
  head 'https://github.com/pc/tsocks.git'

  depends_on 'autoconf' => :build if MacOS.xcode_version.to_f >= 4.3

  def install
    system "autoconf""-v"
    system "./configure""--prefix=#{prefix}""--disable-debug""--disable-dependency-tracking""--with-conf=#{config_file}"

    inreplace("tsocks") { |bin| bin.change_make_var! "LIBDIR", lib }

    system "make"
    system "make install"

    etc.install "tsocks.conf.simple.example" => "tsocks.conf" unless config_file.exist?
  end

  def test
    puts 'Your current public ip is:'
    ohai `curl -sS ifconfig.me 2>&1`.chomp
    puts "If your correctly configured #{config_file}, this should show the ip you have trough the proxy"
    puts 'Your ip through the proxy is:'
    ohai `tsocks curl -sS ifconfig.me 2>&1`.chomp
  end

  def config_file
    etc / 'tsocks.conf'
  end
end

有了上述formula之后,即可 brew install --HEAD tsocks 。

posted @ 2014-05-07 23:23 laogao 阅读(4029) | 评论 (2)编辑 收藏

有了RPi当然免不了要玩玩XBMC,这里推荐XBian,安装配置过程如下:

1- 下载.img文件 ( http://www.xbian.org/download/ );
2- 用dd命令将.img(比如XBian_beta_2.img)写入SD卡;
3- 将中文字体(比如wqy-zenhei.ttc)重命名为arial.ttf,复制到SD卡的~/.xbmc/media/Fonts目录(XBian默认用户为xbian,密码raspberry);
4- 从 https://code.google.com/p/xbmc-addons-chinese/downloads/detail?name=repository.googlecode.xbmc-addons-chinese-eden.zip 下载资源插件并复制到SD卡;
5- 将SD卡插入RPi并连接HDMI到电视机/显示器;
6- RPi开机,进入XBian的配置页面,可以校准屏幕,配置网络连接等;
7- 在系统设置中选择字体为Arial,语言选为中文,此时应该看到界面可正常显示中文;
8- 安装扩展程序,选择之前下载到SD卡的repository.googlecode.xbmc-addons-chinese-eden.zip文件,扩展安装成功后即可在扩展程序列表中看到对应的资源条目,逐一安装即可。

额外提示:XBMC也可以通过网络共享播放视频,之前跟大家提到过XBMC显示中文字幕有时出现整行被方块覆盖的问题,解决方法是在字幕文件中查找并删除或替换"…"字符。Enjoy!

posted @ 2014-04-06 17:45 laogao 阅读(2339) | 评论 (0)编辑 收藏


整理一下 IntelliJ IDEA 最常用的快捷键,按照便于记忆的方式排列:

Ctrl-N              Class... (find by name)
Ctrl-Shift-N        File... (find by name)
Ctrl-Shift-Alt-N    Symbol... (find by name)
Ctrl-G              Line... (goto line)
Ctrl-H              Type hierarchy (hierarchy)
Ctrl-Shift-H        Method hierarchy (hierarchy)
Ctrl-Alt-H          Call hierarchy (hierarchy)
Ctrl-Q              Quick documentation
Ctrl-Alt-I          Auto-indent lines (indent)
Ctrl-Alt-L          Reformat code (line up)
Ctrl-Alt-O          Optimize imports (optimize)
Ctrl-/              Comment with line comment (//)
Ctrl-Shift-/        Comment with block comment (/*...*/)
Ctrl-W              Select word or block (word)
Ctrl-D              Copy line (duplicate line, yyp)
Ctrl-X              Cut line (dd)
Ctrl-U              Uppercase/lowercase (upper)
Ctrl-J              Insert live template
Ctrl-Alt-J          Surround with live template
Ctrl-Alt-T          Surround with (template)
Ctrl-Shift-J        Join lines (join)
Ctrl-E              Recent files (editions)
Ctrl-Shift-E        Recently changed files (editions)
Alt-Shift-C         Recent changes (changes)
Ctrl-B              Delcaration
Ctrl-Shift-B        Type declaration
Ctrl-Alt-B          Implementation(s)
Ctrl-P              Parameter info (parameter)
Ctrl-Space          Basic completion
Ctrl-Shift-Space    Smart completion
Ctrl-Alt-Space      Completion lookup
Alt-Enter           Auto-complete
Alt-Insert          Generate...
Ctrl-Shift-Up/Down  Move statement up/down
Alt-Shift-Up/Down   Move line up/down
Ctrl-Up/Down        Scroll up/down
Alt-Up/Down         Previous/next method
F2                  Next highlighted error
Shift-F2            Previous highlighted error
Ctrl-F              Find
Ctrl-R              Replace
F3                  Next match
Shift-F3            Previous match
F4                  Jump to source
Ctrl-Alt-Shift-T    Refactor this
F5                  Refactor copy
F6                  Refactor move
Ctrl-F6             Refactor change signature
Shift-F6            Refactor rename
Alt-Delete          Refactor safe delete
Ctrl-Alt-V          Refactor extract variable
Ctrl-Alt-F          Refactor extract field
Ctrl-Alt-P          Refactor extract parameter
Ctrl-Alt-M          Refactor extract method
Ctrl-Alt-N          Refactor inline

posted @ 2014-03-09 13:38 laogao 阅读(12853) | 评论 (0)编辑 收藏

不久前入了个 Raspberry Pi 也就是大家说的树梅派(以下简称RPi),拿来做蓝牙测试,用的蓝牙dongle是ORICO的BTA-403-BL http://item.jd.com/980800.html 。这里简单记录下安装过程:

首先是操作系统。作为Arch重度用户,当然选Archlinux ARM了: http://archlinuxarm.org/platforms/armv6/raspberry-pi 下载img文件,用dd写到SD卡上:
dd bs=1M if=/path/to/archlinux-hf-*.img of=/dev/sdX

然后用GParted把SD卡上的分区拖满,充分利用空间。这样SD卡就准备好了,插到RPi上,接上Micro-USB的电源和网线,启动RPi,从路由器上找到RPi的IP地址(机器名默认是alarmpi),ssh上去(用户名root密码root),修改密码,创建非root账号,执行系统更新 sudo pacman -Syu ,这之后开始安装蓝牙相关工具:
sudo pacman -S bluez bluez-utils

确保蓝牙dongle插到RPi的USB接口,通过 hciconfig 确认蓝牙设备被识别,输出应该类似下面这个样子:
[sean@alarmpi]$ hciconfig
hci0:   Type: BR/EDR  Bus: USB
        BD Address: 84:A6:C8:DC:04:97  ACL MTU: 310:10  SCO MTU: 64:8
        DOWN 
        RX bytes:553 acl:0 sco:0 events:28 errors:0
        TX bytes:384 acl:0 sco:0 commands:27 errors:0

启动bluetooth:
sudo systemctl start bluetooth

完成以后,即可通过 bluetoothctl 命令打开蓝牙控制台,执行各项蓝牙相关操作,比如show、list、scan on、agent、info等等,这里不展开了。

如果想使用图形界面操作RPi,也很简单,基本步骤如下:
sudo pacman -S xorg xorg-xinit lxde
echo 'exec startlxde' > ~/.xinitrc
startx

Enjoy!

posted @ 2014-01-01 13:11 laogao 阅读(3444) | 评论 (1)编辑 收藏

第11页(练习):
在Scala REPL中键入3,然后按Tab键 应为 在Scala REPL中键入3.,然后按Tab键

第19页(正文):
util方法返回一个并不包含上限的区间 应为 until方法返回一个并不包含上限的区间

第19页(代码):
0 util s.length 应为 0 until s.length

第31页(正文):
util是RichInt类的方法 应为 until是RichInt类的方法

第34页(代码):
ArraryBuffer 应为 ArrayBuffer
b.sorted(_ < _) 应为 b.sorted
b.sorted(_ > _) 应为 b.sortWith(_ > _) 

第44页(代码):
scala.collections.immutable.SortedMap 应为 scala.collection.immutable.SortedMap

第53页(正文):
Scala对每个字端都提供getter和setter方法 应为 Scala对每个字段都提供getter和setter方法

第107页(代码):
val tokens = source.mkString.split("\\S+") 应为 val tokens = source.mkString.split("\\s+")

第341页(代码):
var count: (Int => Double) => null 应为 var count: (Int => Double) = null

// 本文仅作为信息发布窗口,如需讨论交流,请通过邮件 gaoyuxiang.scala@gmail.com 或 QQ群 132569382 。

posted @ 2012-11-15 15:56 laogao| 编辑 收藏

可能很多人不以为然,写作和编程能有什么关系。

首先,写作促进我们思考。程序员每天的工作,不论是学习新知识新技术、理解软件需求、阅读代码/文档、设计框架、还是实现业务逻辑,都离不开思考。相信很多人都有过这样的体验: 对于某个设计或知识点,你以为自己想清楚了,但真要让你解释给别人听,你又会觉得无从下手,几轮过后回想当初,之前所看到和相信的不过是错觉,当你完整的向其他人转述一遍之后,你才算是真正想明白了。其实这个道理和书桌上放一只橡皮鸭/填充玩偶(然后向它讲述你的想法)的做法是相通的,只不过写作本身不光整理了思路,还留下了文档,同时,写作的过程也是不断加深印象、提升信心的过程,可谓一举多得。

其次,和写作一样,编程的主要目的是与世界交流,不论这个世界是指的机器的世界还是人的世界。要有效地与机器世界交流,你编写的代码必须符合一定的语法和范式,必须逻辑上讲得通,这样才有意义。而基本的写作训练可以让我们养成主动留意错别字、格式、拼写错误、逻辑错误的习惯。如C. A. R. Haore所说,我们宁要明显无错误的代码,不要无明显错误的代码。这点洁癖是好程序员必须具备的修养。这也是为什么我看到有明显拼写错误的程序员简历时,会直接把他/她们拉黑。同样地,我一直坚持认为,如果程序员写不出结构优良的纯文本文档,那么我们也不必指望他/她能够写出优雅的代码。除此之外,我们还可以再稍微发散一下: 开源项目那么多,满足类似需要的往往不止一个,为什么有的很成功,有的却无人问津? 主创/灵魂人物的写作能力,不论是代码、文档、邮件还是PPT,是很重要的分野。我相信,改变世界、影响更多的人,是很多程序员梦寐以求的,而要做到这一点,离不开写作。

最后,写作通常是程序员的短板,亦即最容易低成本高产出的地方。我一直很不喜欢人为地给不同专业背景的人贴上文科和理科的标签,仿佛他们之间没有交集似的。这样做的最大问题在我看来是一方天然地觉得另一方的知识对自己没价值,以至于形成了类似"写作是文科生的菜"、"编程是理科才要学的东西"等谬误。就我的观察,计算机科班出身的同学,往往文字表达能力不够强,可能多少和这种心理暗示有关。如此明显的短板,如果能够引起广大程序员群体的重视,肯在写作上持续投入,效果一定是惊人的。

posted @ 2011-08-03 23:49 laogao 阅读(2056) | 评论 (1)编辑 收藏

今天远程支持同事在Windows环境调优Apache服务器性能,记录在此,供需要的朋友参考。

Java EE应用,同时部署在两个Tomcat(5.5.27)实例上,前面放了个Apache(httpd-2.2.19-win32-x86-no_ssl),通过mod_jk(1.2.32)做负载均衡,同一台物理服务器,操作系统为64位的Windows Server 2003 SP2。现象是60+客户端,平均每个客户端每秒请求数2次,单个请求正常响应时间在500ms以内,即每秒冲进来120个请求,并发量最多在60上下,Apache就已不堪"重"负,静态资源响应时间都超过10s,同时Tomcat和数据库服务器均正常。凭我的经验,同样的压力直接压到Tomcat也不至于这么难看。看来问题出在Apache。

首先修改httpd.conf配置文件,打开status模块:

LoadModule status_module modules/mod_status.so
<Location /status>
  SetHandler server-status
  Order deny,allow
  Deny from all
  Allow from 127.0.0.1 #需要的话也可放开为all
</Location>

这样我们就能通过/status页面查看服务器当前的状态信息,结果观察到worker(即线程)数仅为64!坑爹啊!难怪撑不住。我记得以前Windows下面的Apache默认线程数没这么小的。找准问题,接下来就好办了:

<IfModule mpm_winnt.c>
  ThreadsPerChild 300
  MaxRequestsPerChild 0
</IfModule>

稍微解释一下:mpm_winnt.c是Apache为Windows NT提供的MPM (Multi-Processing Module),对应到Linux环境下,则有prefork.c(多进程/每进程1个线程)和worker.c(多进程+多线程)两种MPM可选。Windows下面只会有父与子两个进程,因此单个子进程能同时起多少线程(ThreadsPerChild)就成了调优的关键。另一个参数MaxRequestsPerChild的含义是单个子进程累计最多处理到少个请求,超过该值则退出重启,这是出于防止内存泄露慢慢拖垮整个服务器而做的防御性措施,0表示不做此限制。

新配置上线后,客户端数量顺利冲上200+。Case closed.

posted @ 2011-08-02 21:04 laogao 阅读(4323) | 评论 (0)编辑 收藏


今天临时有个需求,那就是给某PDF文档切边,以方便在Kindle 3的6吋屏上阅读。

很久没碰Python了,不过我相信用Python一定有办法解决这个需求,于是经过简单的googling,便发现了这个pyPdf库 ( http://pybrary.net/pyPdf/ ) ,操作起来相当直接易懂,把代码贴在这儿,做个记录。

 1 from pyPdf import PdfFileWriter, PdfFileReader
 2 
 3 pdf = PdfFileReader(file('original.pdf''rb'))
 4 out = PdfFileWriter()
 5 
 6 for page in pdf.pages:
 7   page.mediaBox.upperRight = (580,800)
 8   page.mediaBox.lowerLeft = (128,232)
 9   out.addPage(page)
10 
11 ous = file('target.pdf''wb')
12 out.write(ous)
13 ous.close()

Enjoy!

posted @ 2011-07-26 22:25 laogao 阅读(12600) | 评论 (2)编辑 收藏


今天帮同事解决一个邮件乱码的问题,简记于此。

邮件正文就不贴了,有一段从上下文判断明显应该是"上海",却显示成了"涓...",于是自然而然的拿出"上"字和"涓"字来分析。

通过简单的Groovy脚本对这两个汉字分别按gbk和utf-8编码,并将得到的byte[]转换成二进制表示输出如下:

== 上 ==
11001001 11001111
11100100 10111000 10001010
== 涓 ==
11100100 10111000
11100110 10110110 10010011

注意"上"字的第2排前两组和"涓"字第1排的两组byte正好相同,于是问题迎刃而解,乱码是由于邮件以utf-8编码后被错误的以gbk解码(随后又重新编码成utf-8)造成的。

关键代码:

void showBytes(String input) {
  println("== " + input + " ==")
  b = input.getBytes("gbk")
  b.each { print Integer.toBinaryString(it).substring(24) + ' ' }
  println()
  b = input.getBytes("utf8")
  b.each { print Integer.toBinaryString(it).substring(24) + ' ' }
  println()
}

posted @ 2011-03-29 23:50 laogao 阅读(2605) | 评论 (0)编辑 收藏


问题起因: 帮同事排查一个SVN资源库导入后无法使用的问题,checkout时报错
  Expected FS format '2'; found format '3'
  期待文件系统(FS)格式 “2”;找到格式“3”

熟悉SVN的朋友应该知道,Subversion大版本更新时有可能会对其文件格式进行调整,因此内部有文件格式版本的说法,以上报错信息在网上搜一下就知道,版本2和版本3分别对应Subversion的1.4.x和1.5.x,于是问题归结为如何给资源库降级,从而得到与1.4兼容的dump文件。方法很简单,记录如下,供需要的朋友参考:

首先在1.5.x的Subversion环境下新建一个与1.4.x兼容的资源库
  svnadmin --pre-1.5-compatible create project01

然后将之前无法正常导入1.4.x的dump文件(dumpfile.old)导入
  svnadmin load project01 < dumpfile.old

最后再做一次导出即可
  svnadmin dump project01 > dumpfule.new

回到1.4.x的Subversion环境,新的dump文件(dumpfile.new)就可以正常导入和使用了。

posted @ 2011-02-16 19:34 laogao 阅读(2829) | 评论 (0)编辑 收藏


设想一下这样的场景: 你出差在外,或者生病在家,有个紧急的需求要处理,涉及到数个源代码文件的改动,你亲自修改需要10分钟,电话和在公司的同伴沟通然后由他/她来修改则需要1小时。公司svn服务仅支持svn://协议,且仅限内网访问,而你只有一个ssh账号可以远程登录到公司某台Linux/UNIX服务器。

你暗自庆幸,幸好管理员有先见之明,为你留了个ssh口子,这样至少你还可以ssh上去通过命令行的方式在服务器上做svn checkout,vim ...和svn commit。不过如果你认为这就是全部,那就太小瞧ssh了。

ssh有个命令行参数 -D [地址:]端口,含义是在某个本地地址的某个端口上开SOCKS服务进行监听,把这个端口的数据通信以加密形式转发到ssh的另一端。你说好,我有了一个SOCKS服务器,但我又不是要上网走代理,svn也并不天然支持SOCKS啊,有什么用呢? 嗯,这正是tsocks的用武之地,它能透明的让普通应用程序也走SOCKS,安装方法很简单: 主流的Linux发行版,如Debian、Archlinux等的默认软件仓库已经自带了tsocks,通常只需要apt-get install或pacman -S即可,Mac OS X下则可以利用MacPorts安装,然后修改配置文件/etc/tsocks.conf(MacPorts会安装到/opt/local/etc目录),可以在样本文件tsocks.conf.sample的基础上修改,通常只要配置server = 127.0.0.1即可,其他都可以默认。

有了这些打底,剩下的就很简单了: 首先 ssh -D 1080 -f -N 用户名@公司服务器的公网地址 在本机的1080端口开启SOCKS服务;然后按照你平时使用svn的习惯,只是在命令前加上tsocks,类似这样: tsocks svn up 或者 tsocks svn ci -m 'blahblahblah' 等等即可,本地的svn sandbox不需要任何修改。

这个例子可以说只是冰山一角,不论是ssh还是tsocks都还有更高级的用法,而这个通道一旦打通,它的效果就像是简化版的VPN,除了ping之类的少数命令外,几乎就跟你在公司做各种操作没有两样,所以,发挥你的想象力吧 :)

posted @ 2011-02-09 22:37 laogao 阅读(5333) | 评论 (5)编辑 收藏


和Swing应用的直接跨平台不同,SWT/RCP应用要想同时支持不同平台,需要做些特殊的配置,不过并不复杂,记录在此,希望能帮到有需要的朋友。目前win32、32位Linux、64位Linux和Mac OS X基本上就覆盖了所有主流的桌面操作系统,本文将以同时支持这四种OS为例来进行讲解。

首先是下载对应版本的RCP框架在不同操作系统的插件,将它们放在同一个plugins目录,比如你可以用win32为基础,然后添加针对其他平台的如下插件:

org.eclipse.core.filesystem
org.eclipse.core.filesystem.win32.x86
org.eclipse.core.filesystem.linux.x86
org.eclipse.core.filesystem.linux.x86_64
org.eclipse.core.filesystem.macosx

org.eclipse.core.net
org.eclipse.core.net.win32.x86
org.eclipse.core.net.linux.x86

org.eclipse.core.resources
org.eclipse.core.resources.win32.x86

org.eclipse.equinox.launcher
org.eclipse.equinox.launcher.win32.win32.x86
org.eclipse.equinox.launcher.gtk.linux.x86
org.eclipse.equinox.launcher.gtk.linux.x86_64
org.eclipse.equinox.launcher.carbon.macosx

org.eclipse.equinox.security
org.eclipse.equinox.security.win32.x86
org.eclipse.equinox.security.macosx

org.eclipse.swt
org.eclipse.swt.win32.win32.x86
org.eclipse.swt.gtk.linux.x86
org.eclipse.swt.gtk.linux.x86_64
org.eclipse.swt.carbon.macosx

接下来将不同平台下的eclipse可执行文件(Windows下面是eclipe.exe,Linux下是eclipse,Mac OS X下面是Eclipse.app)放到不同的子目录下,当然,如果你的RCP应用有别的名称,也可以重命名eclipse可执行文件,按照不同平台的规范更换图标,然后修改.ini文件让它的-startup和-startup.libraray参数指向相对路径中正确版本的插件即可。

最后分享一下我们软件部署的机制: 按照前面介绍的方式打包的应用程序,交到用户手里并不是很友好,因为需要他/她自己再做一次判断,当前的操作系统是什么,然后打开不同的目录去点击不同的可执行文件。我们的做法是单独提供一个Swing程序,在客户端自动判断OS,然后自动调用不同版本的可执行文件,同时,这个Swing程序被做成Java Web Start,把整个RCP客户端的下载和同步也处理掉,这样,对用户而言,整个过程就透明了,只需要一个JNLP,剩下的工作完全自动化。

posted @ 2011-01-30 12:17 laogao 阅读(4818) | 评论 (0)编辑 收藏


在Linux或其他UNIX和类UNIX环境下,ps命令想必大家都不陌生,我相信也有不少同学写过 ps aux | grep java | grep -v grep | awk '{print $2}' 这样的管道命令来找出Java进程的pid。常言道,Java并非真的"跨平台",它自己就是平台。作为平台,当然也有些基本的工具,让我们可以用更简单、更统一,同时又是非侵入的方式来查询进程相关信息。今天我们就来认识一下其中的两个。

jps

顾名思义,它对应到UNIX的ps命令。用法如下:

jps [ options ] [ hostid ]

其中,options可以用 -q (安静) -m (输出传递给main方法的参数) -l (显示完整路径) -v (显示传递给JVM的命令行参数) -V (显示通过flag文件传递给JVM的参数) -J (和其他Java工具类似用于传递参数给命令本身要调用的java进程);hostid是主机id,默认localhost。

jstat

用于输出给定java进程的统计信息。用法如下:

jstat -options 可以列出当前JVM版本支持的选项,常见的有 -class (类加载器) -compiler (JIT) -gc (GC堆状态) -gccapacity (各区大小) -gccause (最近一次GC统计和原因) -gcnew (新区统计) -gcnewcapacity (新区大小) -gcold (老区统计) -gcoldcapacity (老区大小) -gcpermcapacity (永久区大小) -gcutil (GC统计汇总) -printcompilation (HotSpot编译统计)

假定你要监控的Java进程号是12345,那么
jstat -gcutil -t 12345 200 300 即可每200毫秒连续打印300次带有时间戳的GC统计信息。

简单解释一下: -gcutil是传入的option;必选,-t是打印时间戳,是以目标JVM启动时间为起点计算的,可选;12345是vmid/pid,和我们从jps拿到的是一样的,必选;200是监控时间间隔,可选,不提供就意味着单次输出;300是最大输出次数,可选,不提供且监控时间间隔有值的话,就是无限期打印下去。

具体输出明细的解释请参考官方文档 http://download.oracle.com/javase/6/docs/technotes/tools/share/jstat.html

posted @ 2011-01-27 12:04 laogao 阅读(9452) | 评论 (0)编辑 收藏


在Vim中,我们可以通过set fencs=utf-8,gbk告诉它按照先utf-8后gbk的顺序自动识别打开文件的字符编码。Emacs也有一组字符编码相关指令,整理如下:

指令全名:set-buffer-file-coding-system
指令作用:改变当前buffer的编码
调用方法:(以目标编码gbk为例)
C-x <RET> f gbk <RET>
该指令还可以用于改变当前buffer的换行习惯(编码参数用dos或unix,对应\r\n或\n)。

指令全名:universal-coding-system-argument
指令作用:指定紧随其后的命令(如C-x C-f或C-x C-w等)所采用的编码
调用方法:(以目标编码gbk为例)
C-x <RET> c gbk <RET>

指令全名:revert-buffer-with-coding-system
指令作用:用指定编码重读当前buffer(如果打开时用错了编码)
调用方法:(以目标编码gbk为例)
C-x <RET> r gbk <RET>

指令全名:recode-region
指令作用:将以错误编码解码的选区以指定编码重新解码
调用方法:(以目标编码gbk为例)
M-x recode-region <RET> gbk <RET> utf-8 <RET>

除了这些操作外,还有一种方法,那就是在文件开始的部分给出如下形式的指令,直接告诉编辑器在打开和保存时应采用的编码:
-*- coding: gbk -*-
接触过Python的同学是不是觉得很眼熟?

[补充] 查看当前编码选择的命令为:
M-x describe-coding-system <RET> 或 C-h C <RET>
也可在回车前输入具体的编码名称(如gbk)以查看详细说明。

posted @ 2011-01-05 13:31 laogao 阅读(3582) | 评论 (0)编辑 收藏


为克服拖延症,在此列出2011年要做的事,给未来的自己监督:

1- 继续去年未完成的产品改造,换一种更稳妥的方式推进;
2- 积极参与社区交流活动,不论线上还是线下;
3- 深入学习Scala,辅以Clojure和Haskell;
4- 系统学习PostgreSQL;
5- 全面使用Emacs;
6- 开始读Linux源码;
7- 重读《红楼梦》;
8- 至少读两本英文原著;
9- 带儿子回一趟老家。

就这样。

posted @ 2011-01-02 20:08 laogao 阅读(1591) | 评论 (5)编辑 收藏


回想大学时代,我第一本从头到尾读完的英文小说是Arthur Hailey的《Airport》,是在大学门口的外研书店买的。当时的想法很单纯:要证明自己的英文阅读水准不差,光靠新闻、应用文和专业文献是不够的,小说占到native speaker们日常阅读相当大的比重。如果能够啃下一本真正原汁原味的长篇小说,至少说明他们读什么,我也能读、能欣赏。最终花了一个礼拜,利用课余时间读完了。

这个看似不起眼的"成就",对我自信心的建立至关重要。没有这个打底,后面恐怕也不会在知识"原始积累"的时候能有心有力去大量地阅读原版或影印版的书籍,并且往往能比别人更准确地把握原著要表达的意思。这个阅读小说原著的习惯一直延续到今天,量虽然不大,一直都有意识地在进行,比如前几年的《The Da Vinci Code》,这几年的《Animal Farm》、《1984》、《Twilight》等等。

就个人成长而言,光靠别人给你压力,给你找突破点是不够的。经验告诉我,影响自己最深远的,通常是那些自己给自己找的突破点。你能走多远,成为什么样的人,很大程度上取决于你自己。

posted @ 2011-01-01 21:09 laogao 阅读(637) | 评论 (1)编辑 收藏


相信大家对SOA这个词并不陌生,很多企业都在讲我们要上SOA,也有很多企业在呼应:我们能帮忙。但究竟什么是SOA,SOA能做什么,如何在企业中推行SOA,采用什么样的技术,这些都是摆在我们面前的现实问题。

我为什么会对这本书产生兴趣?这要从我的工作说起。我从2004年开始投身到企业软件开发当中,具体而言,就是医院管理信息系统(HIS)。我们的团队,一直都是扮演独立软件厂商(ISV)的角色,为国内大中型医院提供高品质的HIS产品和服务。

接触过医院信息化的朋友都知道,医院对软件的需求是多方面的,通常很难有一家厂商能够提供从ICU/CCU、LIS、RIS/PACS到财务软件的全线产品和服务。而HIS在所有这些系统中,管理着医院的核心运营,贯穿医院业务的各个环节,经常需要和第三方系统进行通信。如何能更好地集成医院的各类资产,为医院这个特殊的企业提供优质的服务,与医院一同成长,就成为我们关注的焦点。

作为独立软件厂商,同时也考虑到医院的实际承受能力,我们很难说服自己和医院接受那些闭源SOA大厂高昂的产品服务价格。同时,出于对灵活配置和伸缩性的要求,我们在一开始就把目光锁定在开源产品上。

SOA为我们提供了架构设计丰富的营养和施展拳脚的平台。这本书要带给大家的,正是如何用开源的产品实现完整的SOA。在这个过程中,作者为我们分析了SOA的方方面面,对每个环节采用的技术都做了大量翔实的评估和介绍,对每个关键点都给出了详细的说明和完整的源代码。

如果你是企业主管、业务专家,相信你读完本书,会对SOA有更清楚的认识,对SOA能为你的企业带来什么样的价值会有更深的理解和体会。

如果你是架构师或程序员,相信你也和我一样,在阅读完本书之后,能更明白SOA的本质,掌握实际开发SOA的技能,懂得如何在企业或现有系统中引入SOA的思想。

得知博文视点引进并准备翻译这本书时,网上传来了质疑的声音,认为开源加上SOA,受众太小。我却不这么看。中国的软件产业,并非只剩下互联网和外包,除了叫得出名字的大公司,有大量中小型的独立软件厂商在暗自努力,他们在网上的曝光率很低,但都在踏踏实实地做事。他们是可爱、可敬的一批人,做的是幕后支撑企业运营的重要产品和服务,这本书也是为他们准备的。

在这里,我要特别感谢武汉博文视点的周筠老师,给我翻译本书的机会,与她相识是我的荣幸。感谢莫锡昌、成硕为审稿付出的宝贵时间。感谢编辑卢鸫翔、刘唯一和其他所有幕后工作者的辛勤劳动。

我还要感谢在事业上给予我重要帮助的两个人:毛颖和林勇,是他们的信任和鼓励让我走到今天。

最后要感谢我的家人,为了让我安心翻译这本书,牺牲了太多的周末和假期,谢谢你们对我的包容和支持,无私的爱当然要用无私的爱来回报,我爱你们!

在本书的翻译过程中,译者虽已尽力确保专业术语符合中文读者的习惯,也尽力将原著的真实意图以符合中文习惯的方式呈现给大家,毕竟水平有限,书中的问题和疏漏之处在所难免,恳请各位读者朋友批评指正,联系邮箱:gaoyuxiang.soa@gmail.com。

高宇翔

2010年11月于上海

posted @ 2010-12-30 16:20 laogao 阅读(479) | 评论 (0)编辑 收藏

2010年即将过去,在这一年里,我做了什么?找到自我了吗?我问自己。

整个2010年,我大概有这么几件事值得一提:

    首先,我去年向公司争取的产品改造计划,执行到中段,可耻地失败了;
    其次,我有幸参与翻译了两本外版IT书:《Scala编程》《开源SOA》,目前两本书均已上架;
    再次,我下了很大的决心转行做出版,最终也可耻地失败了。

不过,我找到自我了吗?我想是的:命中注定做架构师。

这两天在读周国平的《人生哲思录》:

“古希腊哲人赫拉克利特说:‘一个人的性格就是他的命运。’这句话包含两层意思:一,对于每个人来说,性格是与生俱来、伴随终身的,永远不可摆脱,如同不可摆脱命运一样;二,性格决定了一个人在此生此世的命运……赫拉克利特的名言的真正含义是:一个人应该认清自己的天性,过最适合于他的天性的生活,而对他而言这就是最好的生活……为别人对你的好感、承认、报偿做的事,如果别人不承认,便等于零。为自己的良心、才能、生命做的事,即使没有一个人承认,也丝毫无损。”

我想,这就是为什么人在抉择时要追随自己的内心和天性,因为这才是对自己最合理的安排。

posted @ 2010-12-22 23:22 laogao 阅读(503) | 评论 (1)编辑 收藏


这篇日记写给自己,发散式+意识流,赶时间的朋友请放心略过。

进入2010年,头1个月,到今天是最后1天,家里的事暂不去提,这个月是我参加工作以来感觉最累的1个月。

加入现在的这支创业团队4年,我们的产品,从无到有(1.0),到现在的2.x,倾注了很多人的心血,我们的团队,在后面的这2年多,也经历和见证了很多伤感的离别,"元老"级的人物,已经屈指可数。万事不能尽如人意,能有今天的结果,也许应该庆幸而不是哀伤,至少产品还在,至少团队还在运转。但未来会如何,谁也无法预知,我也不敢多想,我只知道,工作带给我的幸福感,正在不停的创造新低。

创业型团队的一大特点,就是一个人要同时承担多个角色的职能,而且比其他团队更容易受到外部环境的冲击。为了生存,有时不得不做一些不相关的项目、不相关的事,活下来比什么都重要,你东西再好,技术再牛逼,没人要就是没人要,没资源就是没资源,哭爹喊娘,没人理你。

去年年底,我们的老板带着我们一起,并入了现在这家集团公司,一个比我们大得多的团队。按说这应该是好事,我们也不必像原来那样担惊受怕,但事实证明这个想法非常天真,外部环境的冲击比以前更加真实的发生在我们身边,无时无刻不在提醒我们它的存在。以前我们卖力做事,一狠心一咬牙一跺脚,创业嘛,为整个团队付出,咱认了;现在我们卖力做事,不知道是在为谁付出:累的是你自己,收获的是别人。从创业的角度来说,我们失败了,我们为创业比别人多付出的那些汗水,除了回忆,现在看,也只有回忆了。对我们这个小团队来说,情形依然是:为了生存,有时不得不做一些不相关的项目、不相关的事,活下来比什么都重要,你东西再好,技术再牛逼,没人要就是没人要,没资源就是没资源,哭爹喊娘,没人理你。

有人说,其实哪里都一样。这样想可能会让人更快乐,不那么痛苦,但我很清楚,这是精神毒药,如果事实果真如此,那就不仅仅是令人伤感苦闷,而是彻彻底底的让人绝望了。

物以类聚,人以群分。我的群在哪儿?


posted @ 2010-01-31 21:25 laogao 阅读(489) | 评论 (1)编辑 收藏


周二的时候拿到了新的T400s,安装Linux(64位Karmic)的过程比预想的要曲折,趁周末有时间,整理记录于此,希望对遇到同样问题的人有所帮助。

T400s送到之前,我先简单的在网上查了查基本的配置信息,同时也看到有很多网友十分顺利的安装了Linux,不论是Ubuntu Karmic还是Arch Linux,基本都是除了指纹都是out-of-box就可直接工作的,这也符合我的预期。于是,拿着amd64版的Karmic盘,开始在T400s上安装。

基本系统的安装很顺利,跟着提示一路走完,Karmic就能够boot并正常login了,so far so good。不过登录进去之后,无线网卡不工作,只有有线连接,这是怎么回事?用lspci一看:
  • 00:00.0 Host bridge: Intel Corporation Mobile 4 Series Chipset Memory Controller Hub (rev 07)
  • 00:02.0 VGA compatible controller: Intel Corporation Mobile 4 Series Chipset Integrated Graphics Controller (rev 07)
  • 00:02.1 Display controller: Intel Corporation Mobile 4 Series Chipset Integrated Graphics Controller (rev 07)
  • 00:03.0 Communication controller: Intel Corporation Mobile 4 Series Chipset MEI Controller (rev 07)
  • 00:03.3 Serial controller: Intel Corporation Mobile 4 Series Chipset AMT SOL Redirection (rev 07)
  • 00:19.0 Ethernet controller: Intel Corporation 82567LM Gigabit Network Connection (rev 03)
  • 00:1a.0 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #4 (rev 03)
  • 00:1a.1 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #5 (rev 03)
  • 00:1a.2 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #6 (rev 03)
  • 00:1a.7 USB Controller: Intel Corporation 82801I (ICH9 Family) USB2 EHCI Controller #2 (rev 03)
  • 00:1b.0 Audio device: Intel Corporation 82801I (ICH9 Family) HD Audio Controller (rev 03)
  • 00:1c.0 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 1 (rev 03)
  • 00:1c.1 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 2 (rev 03)
  • 00:1c.2 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 3 (rev 03)
  • 00:1c.3 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 4 (rev 03)
  • 00:1d.0 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #1 (rev 03)
  • 00:1d.1 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #2 (rev 03)
  • 00:1d.2 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #3 (rev 03)
  • 00:1d.7 USB Controller: Intel Corporation 82801I (ICH9 Family) USB2 EHCI Controller #1 (rev 03)
  • 00:1e.0 PCI bridge: Intel Corporation 82801 Mobile PCI Bridge (rev 93)
  • 00:1f.0 ISA bridge: Intel Corporation ICH9M-E LPC Interface Controller (rev 03)
  • 00:1f.2 SATA controller: Intel Corporation ICH9M/M-E SATA AHCI Controller (rev 03)
  • 00:1f.3 SMBus: Intel Corporation 82801I (ICH9 Family) SMBus Controller (rev 03)
  • 03:00.0 Network controller: Realtek Semiconductor Co., Ltd. Device 8172 (rev 10)
  • 04:00.0 Memory controller: Intel Corporation Turbo Memory Controller (rev 11)
  • 05:00.0 SD Host controller: Ricoh Co Ltd Device e822 (rev 01)
  • 05:00.1 System peripheral: Ricoh Co Ltd Device e230 (rev 01)
注意03:00.0这一行,竟然是Realtek的8172,对应Windows下的型号是8192,Lenovo什么时候把T400s原本的无线芯片配置(Intel WiMAX/WiFi Link 5xxx)换成了Realtek 8172的?难怪没有无线,这块网卡的驱动还没有被Linux内核直接支持,需要手工安装。网上搜到很多方案,比如ndiswrapper+win版驱动等等,但这个Ubuntu LaunchPad上的方案[1]看上去最靠谱,还等什么,开工吧。
  • 首先下载驱动: http://launchpadlibrarian.net/34090404/rtl8192se_linux_2.6.0010.1012.2009_64bit.tar.gz
  • 解压后进入rtl8192se_linux_2.6.0010.1020.2009_64bit子目录,make
  • 成功后在HAL/rtl8192下能够找到r8192se_pci.ko文件,cp至/lib/modules/`uname -r`/kernel/drivers/net/wireless/
  • 然后将固件相关文件,即firmware/RTL8192SE目录,cp至/lib/firmware/`uname -r`/
  • 执行命令depmod -a重新扫描module依赖关系
  • 执行命令modprobe r8192se_pci加载该module,这一步完成以后NetworkManager就可以搜到无线网络并进行连接了
好了,到此最大的拦路虎已经消灭,开始装别的软件吧。就在这时,新的问题出现了,dmesg可以看到重复出现的如下报错/警告信息:
  • [ 483.431670] DMA: Out of SW-IOMMU space for 9100 bytes at device 0000:0e:00.0
  • [ 483.435783] DMA: Out of SW-IOMMU space for 9100 bytes at device 0000:0e:00.0
  • [ 483.439867] DMA: Out of SW-IOMMU space for 9100 bytes at device 0000:0e:00.0
  • ...
通常经过数分钟的积累,系统就死机了,只剩下CapsLock键上的小灯不停闪烁,典型的kernel panic? 根据网友提供的线索[2],由于Intel的64位实现虽是参考AMD64但细节有差异,所以在实际内存大于等于4G的环境下,某些未考虑到该特性的代码会leak memory,怎么办?增加内核启动参数mem=4G iommu=off,一方面限定内存范围,另一方面关闭IOMMU。

经过测试,这样的配置下系统和无线网络都能够持续稳定运行。系统安装到此,一个大的里程碑达成,唯一的缺憾是每次kernel升级,可能还需要手工做一些工作,且暂时不能既开无线又开4G以上内存,不过这样总好过没有无线,或者缴枪投降,不是吗?本想多骂几句Lenovo,好好的Intel芯片不用,要换Realtek,但转念一想,这已是既成事实,而且看到很多其他型号的ThinkPad,如R500、SL400等,也有不少用上了Realtek的这款无线芯片,让我们一起期待稳定可靠的驱动最终被Linux内核支持的那一天吧。

参考链接:
[1] https://bugs.launchpad.net/ubuntu/+source/linux/+bug/401126
[2] http://lwn.net/Articles/91870/

posted @ 2009-12-26 11:14 laogao 阅读(1391) | 评论 (2)编辑 收藏

到处吹嘘Scala很长时间了,却一直没有在自己的blog上增加过任何相关内容,今天就来补一补。当然,Scala的基本特性就不多废话了,网上已经有相当多的资料,如果懒得google,只想看完本文,那么你只需要知道它是一门以JVM为目标运行环境的静态编程语言(当然,Scala官方也有.NET版,但已不是其重点),同时具备面向对象和函数式编程语言的特点。本文将通过一个简单的示例,展示Scala的FP能力,其中十分heavy的用到了implicit隐式转换和模式匹配。

代码是从guithub的gist上抄的,简单改了改,原始代码见: http://gist.github.com/66925

import scala.reflect.Manifest
  
def simpleName(m:Manifest[_]):String 
= {
  val name 
= m.toString
  name.substring(name.lastIndexOf(
'$')+1)
}
  
trait Num
final class Succ[Pre<:Num] extends Num
final class _1 extends Num
type _2 
= Succ[_1]
type _3 
= Succ[_2]
type _4 
= Succ[_3]
 
case class Move[N<:Num,A,B,C]()

implicit def move1[A,B,C](implicit a:Manifest[A], b:Manifest[B]) : Move[_1,A,B,C] 
= {
  System.out.println(
"Move from " + simpleName(a) + " to " + simpleName(b))
  
null
}
 
implicit def moveN[P
<:Num,A,B,C](implicit m1:Move[P,A,C,B], m2:Move[_1,A,B,C], m3:Move[P,C,B,A]) : Move[Succ[P],A,B,C] = null
  
def run[N
<:Num,A,B,C](implicit m:Move[N,A,B,C]) = null
  
case class Left()
case class Center()
case class Right()
  
run[_3,Left,Right,Center]

 

这段代码解决的是经典的汉诺塔问题,通过一根中柱,将左柱上64个大小依次叠加的圆盘全部移动到右柱,要求整个过程中每次只能移动一个圆盘,且每个圆盘只能独立占据一根柱子或是叠加在比自身更大的圆盘上。

简单分析一下就知道,这是一个递归问题(FP的英雄特长):

  • 当只有1个圆盘时,不用通过中柱,直接可以从左柱移动到右柱;
  • 当有2个圆盘时,将小盘移动到中柱,剩下的大盘移动到右柱,再从中柱把小盘移动到右柱;
  • 当有3个圆盘时,先移动2个圆盘到中柱,再移动大盘到右柱,再移动2个圆盘到右柱;
  • ...

很容易发现一个pattern,那就是移动N(N>1)个圆盘,可以通过以下三个步骤:

  1. 移动N-1个圆盘,从左柱到中柱;
  2. 移动剩下的1个圆盘,从左柱到右柱;
  3. 移动N-1个圆盘,从中柱到右柱。

在解释代码之前,先说说Scala的implicit隐式转换,这是一个非常powerful的idea,当Scala编译器发现类型不匹配,它不会直接fail,而是尝试从代码中指定的,在scope内的implicit转换定义,来替换问题对象或表达式以满足类型要求,当然,为了避免歧义,同一时刻Scala需要找到唯一的一个满足条件的implicit定义。

我们的代码首先定义了一个取得友好类名的方法,不去深究它,然后定义了一个正整数的序列,也不去深究它了,你只需要当作他们是正整数就好,接触过FP的同学应该对此类定义不陌生,接下来定义了如下3个支持implicit传入参数的方法:

  1. implicit def move1[A,B,C](implicit a:Manifest[A], b:Manifest[B]) : Move[_1,A,B,C]
  2. implicit def moveN[P<:Num,A,B,C]( implicit
    m1:Move[P,A,C,B],
    m2:Move[_1,A,B,C],
    m3:Move[P,C,B,A]
    ) : Move[Succ[P],A,B,C]
  3. def run[N<:Num,A,B,C](implicit m:Move[N,A,B,C])

含义分别是:

  1. 当需要Move[_1,A,B,C]值时,可以找我帮忙(我有个side-effect,那就是输出移动指令);
  2. 当需要Move[Succ[P],A,B,C]时,可以找我帮忙;
  3. 运行我,我接受Move[N,A,B,C]类型的参数。

简单说明:Scala用[]表示类型参数,区别于Java的<>,另外,Scala的类型声明在变量/函数定义之后。Move[_,A,B,C]的含义是通过C,从A移动圆盘到B。

我们来模拟运行一下,为了演示效果,用一个中等复杂的数目,3个圆盘,从Left移动到Right。

run[_3,Left,Right,Center],对应Move[Succ[_2],Left,Right,Center],于是展开成三个Move:

Move[_2,Left,Center,Right]即Move[Succ[_1],Left,Center,Right]
Move[_1,Left,Right,Center]
Move[_2,Center,Right,Left]即Move[Succ[_1],Center,Right,Left]

然后继续展开Move[_2,Left,Center,Right]和Move[_2,Center,Right,Left],得到:

Move[_1,Left,Right,Center]
Move[_1,Left,Center,Right]
Move[_1,Right,Center,Left]
--------------------------
Move[_1,Left,Right,Center]
--------------------------
Move[_1,Center,Left,Right]
Move[_1,Center,Right,Left]
Move[_1,Left,Right,Center]

这个时候已经全部都匹配Move[_1,A,B,C],于是我们很容易得到以下输出:

Move from Left to Right
Move from Left to Center
Move from Right to Center
Move from Left to Right
Move from Center to Left
Move from Center to Right
Move from Left to Right

希望本文能带给Scala初学者一些感性认识和启发。


posted @ 2009-11-23 19:20 laogao 阅读(2591) | 评论 (3)编辑 收藏


前两天看到网友关于铁观音泡法的留言,接受建议,收了只手绘青花瓷盖碗,和一只公杯:



家里还有些去年的秋茶存货,开始练习用盖碗,右手的拇指、食指和中指被烫到不行,据说烫出一层老茧就好了,我觉得应该不至于那么夸张,慢慢来,挺好玩的。

posted @ 2009-10-18 11:57 laogao 阅读(399) | 评论 (0)编辑 收藏


最近围观一本JavaScript的书籍引发的争论,一不小心碰到一篇讲编程语言类型系统划分的帖子,回想起当年还在公司内部的Tech Session上主讲过这个话题,不过只涉及到静态/动态、强类型/弱类型,远没有这位仁兄总结的那么全面。

原文链接
http://www.reddit.com/r/programming/comments/63tnv/bruce_eckel_33104_im_over_it_java/c02qx55

不多废话,直入正题:

[维度一] Static vs Dynamic Typing
静态类型和动态类型,区分的关键点为编译期或运行期确定类型:静态类型在编译期确定,动态类型在运行期确定。
静态类型代表 Java、Scala、Haskell
动态类型代表 Ruby、Python、Erlang

[维度二] Strong vs Weak Typing
强类型和弱类型,区分的关键点为运行时是否自动转换到与实际类型不符的类型:强类型要求手工类型转换,弱类型自动转换。
强类型代表 Java、Scala、Python
弱类型代表 C、Assembly、JavaScript

[维度三] Latent (Implicit) vs Manifest (Explicit) Typing
隐式类型和显式类型,区分的关键点为是否要在源码中声明类型:隐式类型不需要,显式类型需要。
隐式类型代表 Haskell、Erlang、Python
显式类型代表 C、C++、Java

[维度四] Nominal vs Structural Typing
名义类型和结构类型,区分的关键点为类型判定是根据标称还是根据内容:名义类型根据标称,结构类型根据内容。
名义类型代表 C、C++、Java
结构类型代表 Haskell、Erlang、Python

关于JavaScript书籍的争论,请移步如下网址:
1- 网友Hax的"炮轰"帖 http://www.javaeye.com/topic/474725
2- 周爱民(aimingoo)的MSN空间 http://aimingoo.spaces.live.com/blog/
3- 火星常驻JE办事处相关帖 http://mars.group.javaeye.com/group/topic/14325

posted @ 2009-09-28 19:19 laogao 阅读(1099) | 评论 (0)编辑 收藏


这个周末又去收了一只紫砂,这下除了龙井,我平常喝的所有品种的茶,都有了各自专用的壶。贴个"全家福":


从左到右依次为铁观音、高山乌龙、熟普洱和生普洱。目前只有第一只养成了,其余的三只还得多花些时间和心思呢。


posted @ 2009-08-30 11:58 laogao 阅读(479) | 评论 (1)编辑 收藏


我曾经一度是Twitter重度用户,直到上周五,@laogao这个账号,被Twitter无端禁言了。被禁时,我follow 133人,被241人follow,共2260历史推。

Follow我的推友们,以及我经常@的兄弟姐妹,抱歉了,尤其那些被我"忽悠"上Twitter的朋友。当你访问http://twitter.com/laogao时,暂时只能看到"该用户被suspend"的信息。这并非是因为我是一个spammer,或者有什么所谓的"strange behaviour",至于被封的具体原因,直到今天,Twitter仍没有给予正面答复。

作为一个喜欢Twitter的简单、直接的人,我从来都很认真的对待我的每一推,尊重他人的意见,善待每个@我的朋友,也在现实世界的朋友圈中推荐大家使用这个服务。但从今天开始,我将不再向人推荐Twitter,也无法确定什么时候@laogao这个账号能够被reinstate或者再次被suspend,各位关注我的朋友,请移步https://friendfeed.com/laogao

对那些仍然天真的以为Twitter封号肯定是用户自己的问题的朋友,我很理解你们的想法,当初我看到别人被封时,也是这么想的。

各位推友保重!


posted @ 2009-07-06 21:15 laogao 阅读(503) | 评论 (0)编辑 收藏


周末去败了只全新的紫砂回来,宜兴红泥的,专门用来泡台湾高山乌龙。用之前,当然少不了开壶的过程,虽然比较耗时,但也挺有趣,在这里做个记录。

首先将新买的紫砂壶用清水洗净,浸泡一整天,其间换水2~3次,去除掉残余的泥土、灰尘等。然后放入锅内,加入清水煮上1个小时,继续消毒。


接下来,放置一边,冷却后,取老豆腐半块,放入清水中,再煮1小时,去火气。


第三步,用清水洗净,根据今后用这个紫砂壶泡什么类型的茶,选用单次用量的2~4倍茶叶,加清水,煮沸后,待茶汁完全浸出,捞起茶叶残渣,继续用茶汤煮上1个小时。


出锅。


这是成品,可以正式开始享用了:


现在开始,从头养我的第二只紫砂,细细体味那份安静和从容,让每日忙碌和疲惫的身心,有一个休息和平复的空间。

posted @ 2009-06-08 22:07 laogao 阅读(494) | 评论 (1)编辑 收藏

各位童鞋们过节好啊,今天给大家带来的是在bash中DIY制表符键自动补全。

bash是大多数主流Linux发行版的默认shell,如果你用过bash,那么一定会接触到<tab>键自动补全的这个方便的功能,当你一个命令的头几个字符敲下去,按下<tab>,如果以此开头的命令只有1个, bash会直接帮你补全,如果有多个,则会有相应提示,而在后续的参数输入时,也会带有默认的自动补全文件路径的功能。当你习惯了<tab>,很难想象没有自动补全的日子会是什么样子。

bash默认支持常见的补全功能,如可执行命令、文件路径等,如果安装了bash-completion包,甚至连chown, man, svn, ssh这些也会带有相应的自动补全提示,而不是单纯的文件路径补全。好奇的你一定想知道是怎么实现的吧,其实很简单,我们举个例子来说:

假定你有一个命令,叫做abc,它又有自己的子命令,分别是build_all、compile和update,其中compile这个子命令需要的参数必须来自project.list这个文件中列出的值,怎么实现<tab>自动补全,让bash知道abc的合法子命令和compile子命令的合法参数列表呢?

在你的~/.bashrc或者任何一个启动bash时会被执行的文件中加入下面的代码:

function _abc() {
    COMPREPLY=()
    local cur=${COMP_WORDS[COMP_CWORD]};
    local com=${COMP_WORDS[COMP_CWORD-1]};
    case $com in
    'abc')
        COMPREPLY=($(compgen -W 'build_all compile update' -- $cur))
        ;;
    'compile')
        local pro=($(awk '{print $1}' project.list))
        COMPREPLY=($(compgen -W '${pro[@]}' -- $cur))
        ;;
    *)
        ;;
    esac
    return 0
}

complete -F _abc abc

手动载入一下,或者重启bash,再敲abc命令,即可自动补全子命令,如果子命令是compile,还能自动补全相应的参数值。我们来简单分析一下这段代码。首先我们定义一个function _abc,这个函数先清空自动补全列表,根据当前输入位置前一个token判断目前需要自动补全的语境,如果是abc,则将自动补全内容设置为'build_all'、'compile'和'update',如果是'compile',则将project.list文件内容输出到补全列表,当然,这里我们也可以换成其他任何必要的方式。最后我们通过complete -F _abc abc将这段自动补全逻辑注册到abc这个主词上。这样当我们敲abc时,后续内容就能自动补全了。

Enjoy!

posted @ 2009-06-01 00:11 laogao 阅读(4046) | 评论 (1)编辑 收藏


本来是手写的一张草稿,清理台面的时候,正要扔,发现内容还有点意思,干脆吧,开个随笔记录一下,备忘,说不定还能帮到别人。

在我们日常生活和工作中,尤其浏览含有中文的网站,时常会为乱码问题犯愁,一些天生Unicode支持不到位的编程语言和软件更是加重了这个现象。虽说已经是2009年了,我们时不时还是能碰到一些明显脑残的code,吐出一堆乱码,不论你用选什么字符集,似乎都无法还原最初的中文。比如"å·²",或者同一个页面,无法用同一个字符集显示,任何一种字符都至少有一部分显示不正确,不是这儿就是那儿。

首先科普一下UTF-8。UTF-8是Unicode所有字符编码实现中,应用范围最广的一个,最大的特点是兼容ASCII码,在此基础上,通过1..4个byte来表示每一个Unicode字符。它是怎么做到的?其实很简单,看首个byte:
00000000 ~ 01111111 : 0~127 (ASCII, 单个byte) 表示Unicode范围\u0000 ~ \u007F
11000000 ~ 11011111 : (2个1打头,所以2个byte) 表示Unicode范围\u0080 ~ \u07FF
11100000 ~ 11101111 : (3个1打头,所以3个byte) 表示Unicode范围\u0800 ~ \uFFFF
11110000 ~ 11110111 : (4个1打头,所以4个byte) 表示Unicode范围\u10000 ~ \u10FFFF

除了单个byte这个case,其他情况下,后续的byte均以10打头。这些打头的bit:10、110、1110、11110,都不作为具体编码的一部分参与真正Unicode编码的计算。所以1..4个byte,其有效位数分别为:7、11、16、21,因此才有了\u007F、\u07FF、\uFFFF这样的临界值,且4个byte的空间还有富余。

有了这个基础知识,我们就来具体看看这个"已"字,是怎么被UTF-8表示的,以及为什么处理不当的代码会最终输出"å·²"。

"已"字,用Unicode表示法,是\u5DF2,按照2个byte拆开成二进制表示:
01011101 11110010
如果用UTF-8编码,采用1110???? 10?????? 10??????这个格式,?号部分填入上述01011101 11110010,得到
11100101 10110111 10110010 这样3个byte。

好了,这个时候脑残代码出现,假如它不认识UTF-8,那么他会看到这样3个前后没有关联的byte,在西欧Latin-1字符集(即ISO 8859-1)中,它们分别表示"å"、"·"、"²"这3个字符。如果把它们分别再按照UTF-8编码,就成了:
11000011 10100101 11000010 10110111 11000010 10110010
完美的UTF-8编码,只不过,这完全是假象,只能通过非常规手段才能恢复它原本的样子。


posted @ 2009-05-05 19:24 laogao 阅读(1141) | 评论 (0)编辑 收藏


上周在北京参加QCon大会,回来以后一直没有成块的时间,把一些之前只是通过Twitter分享出来的信息汇总整理出来。已经有不少朋友都在各自的博客上记录了大会感闻,所以我还是抓紧些吧,不然真要成没有营养的废话了。

QCon这次是首次进入中国,我有幸得以抽身参加。大会为期三天,由InfoQ中文站组织策划,包括 @taiwen 在内InfoQ中文站只有3个人,这是我之前没有想到的,感谢他们和志愿者的辛勤劳动,使得这次大会得以顺利举行。大会嘉宾包括了国内外许多大名鼎鼎的牛人,比如前TSS和后来InfoQ的主创Floyd Marinescu、ThoughtWorks首席科学家Martin Fowler、Spring之父Rod Johnson、eBay架构师Randy Shoup、《硝烟中的Scrum和XP》作者Henrik Kniberg、《大道至简》作者周爱民、支付宝数据库架构师冯大辉 @Fenng 等。

大会第一天,上午和下午都安排了Martin Fowler的session,分别是DSL和Ruby,虽然内容算不上特别新,但幻灯片准备很到位,而大师就是大师,思路清晰,言简意赅,尺度分寸拿捏的很好。唯一感觉可能是大家都比较含蓄,或者热身不够,沟通和对话的环节显得不是很活跃,除了买书签名的,到后面Dojo的创始人Dylan Schiemann讲Open Web,气氛就开始暖和一些了。至于Amazon的Jeff Barr,不少朋友也都说了,基本上就是来打广告的,可惜QCon北京的赞助商中,没有发现Amazon。晚上的沙龙,国际讲师唱主角,分享关于软件开发趋势的见解。

大会第二天,可能是最精彩的一天,尤其是下午 @Fenng 主持的网站架构这个Track。上午的大戏是Rod Johnson,不过也许是大家期望比较高,反倒是没觉出特别出彩的地方,Rod特别强调Simplicity和Lean,同时通批了一顿Java EE,不过把Tomcat作为simplicity和lean的代表举例,似乎大家都不是特别买账。后来才知道原来Tomcat 90%的commit都来自SpringSource,而稍后SpringSource会在此基础上推出功能更丰富的Spring tc server,以及(我猜)Spring 3.0。接下来eBay的Randy Shoup,带来了一场颇为精彩的演讲。下午来自支付宝、豆瓣网、网易有道和优酷网的架构师们共同创造了本次QCon大会最受欢迎的半天,尤其是豆瓣的 @hongqn ,内容相当务实、精彩、有货。说到这,插句题外话,如果没记错, @hongqn 是这次大会中唯一一位使用Mac的国内讲师,国际讲师用Mac的好像也只有Martin Fowler (如果说的不对还请同学们指正)。到了这个时候,国际讲师们渐渐淡出,场子交给了国内的讲师们,会场气氛也更加热闹和随意起来,包括晚上的沙龙。

大会第三天,从日程上看,并没有特别重量级的session,似乎除了云还是云,不过如果因此选择不参加的话,可能就会错过了两场很不错的演讲,分别是高焕堂的"提高架构质量的10个观点"和周爱民的"我之于架构的主要观点"。高焕堂的演讲让人耳目一新,明显感觉来自台湾的专家,比大陆的专家,对中国传统文化,有更深的理解和思考,他的"序"、"容"、"易"三角,让人印象深刻,另外他还对目前我们软件产业的结构性问题提出了批评。而周爱民的演讲同样很有深度,尤其是后面说到架构师的决策作用时,很引起我的共鸣:"架构师不需要让所有人都理解你的每一个决定和这些决定最终要达成的目标,去做就是了。"(可能原话不是这么说的,但意思是这样) 也许有些朋友觉得这两个session虚幻的成分比较重,但对我来说,收益颇丰,因为很多观点,都能够在我之前经历的一些项目和设计中找到支撑。至于其他几讲,关于云计算的,确实提不起什么兴趣,尤其是Azure,干的要命(小插曲: 现场演示一段ASP.NET代码,至少修改和重编译了3次才搞定)。大公司带着推销产品/服务的目的来参加开发会议,有点浪费大家的时间和银子啊。

最后说说大会的组织相对还有待提高的地方:
1- 第一天入场时,志愿者的引导不是很到位,报到的地方和其他展台秩序稍显混乱。
2- 同声传译据说质量不高,白天没用,但是周围的朋友在用,耳机漏音比较严重,稍影响一些效果,晚上直接通过扩音设备翻译,就很明显的感觉到脱节了。
3- 午餐和沙龙的地方,显得还是小了些,而且中午所有人都集中在一个时间去,不论排队打饭还是找位置,都比较吃力,以至于第二天中午有一小撮脑筋比较活络的同学,提前下课去打饭吃。
4- 现场网络环境比较差,害我只能用手机上twittai。

总的来说,这次的QCon还是挺不错的,希望明年的QCon会继续在中国举办,更多的嘉宾,更丰富的内容,更有深度的主题,更加精彩。


posted @ 2009-04-17 00:36 laogao 阅读(598) | 评论 (0)编辑 收藏


其实很早就听说有这个东东,只是一直没玩过,最近公司调整PC服务器,正好找个空闲实战了一把。基本的配置步骤如下(时间有限,挑简单的说,假定你要Wake-on-LAN的机器是Windows,控制服务器是Linux):

[被控制方]
1- 正常开机进入BIOS设置
2- 找到Wake-on-LAN的选项enable它(如果是Dell的机器这个选项叫Remote Wake Up)
3- 进入OS,在需要配置Wake-on-LAN的网络端口的配置项中(网络连接属性->配置->电源管理),选择允许此设备使计算机脱离待机状态
4- 记录网卡的MAC地址
5- 正常关机
// 如果被控制方是Linux/Ubuntu,OS的配置方法参考链接[4]

[控制方]
1- 安装wakeonlan,可以选择(如果有的选) apt-get install wakeonlan,或者从链接[3]获取源码手工安装(是Perl写的)
2- 通过wakeonlan+MAC地址的命令行方式控制需要wake up的机器,如 wakeonlan 01:23:45:67:89:AB
// 更高级的用法包括编写脚本,添加到cron,以及通过-f指定一个包含多个MAC地址的文件同时操作等

[基本原理]

Wake-on-LAN的相关通信协议位于OSI七层模型中的数据链路层,比IP需要的网络层还要低一层,在局域网范围发送广播,数据包格式为:
FF FF FF FF FF FF $MAC*16
即 FF FF FF FF FF FF然后重复16次对方的MAC地址,被戏称为"magic packet"。

配置成功后,只要被控制方正常关机、挂起、休眠,且环境始终不掉电,任何时候在局域网中广播"magic packet",指定网卡的机器就可以被唤醒。

链接:

[1] http://en.wikipedia.org/wiki/Wake-on-LAN
[2] http://en.wikipedia.org/wiki/OSI_model
[3] http://gsd.di.uminho.pt/jpo/software/wakeonlan/
[4] http://ubuntuforums.org/showthread.php?t=234588


posted @ 2009-03-18 20:03 laogao 阅读(1111) | 评论 (0)编辑 收藏


周末花了一个下午和一个晚上把Scott Rosenberg的Dreaming in Code从头到尾看了一遍。最直接的感受是这本书把我之前很多记忆碎片串在了一起,成为一个生动而"完整"的故事,虽然书的内容本身组织的多少还是有点散。

dreaming_in_code.jpg

我本人对Chandler这个项目并不陌生:之前出于对Python/wxWidget和开源本身的兴趣,陆续用过几个0.x的版本,一开始并不是十分友好,性能上也有问题,甚至会莫名的吃掉我机器上的数百兆(或者上G?)空间。后来的版本在性能和可用性上确实提高了不少,但一直感觉这个项目缺少必要的、以及许多开源项目应有的momentum。Phillip J. Eby对Chandler开发人员不懂Python的批评,当时我的印象也很深。而项目中出现的人物,包括Mitchell Kapor、Ted Leung,也都在Chandler这个范畴之外follow过。其他细节包括:Chandler和Cosmo这两个名称的由来、Chandler项目组中女性成员相对高的比例、一些熟悉的人物及其观点(Alan Kay, Bill Joy, Frederick Brooks, Donald Knuth、Linus Torvalds, Ward Cunningham, Larry Wall, Guido van Rossum, Joel Spolsky, etc.)、一些公司的分分和和以及人员流动等等。感觉挺亲切的。

可能更重要、也更深刻的原因是:尽管书中一再提到"There's no such thing as a typical software project, every project is different",我仍然深深的感觉到,Chandler遇到的这些问题,其实也是我亲历的很多项目的种种问题的一个缩影。对这些问题,作者并没有给出解决方案,其实谁也没有标准答案。软件开发是一项非常具有挑战性的工作,也正是像我们这样有热情、有涵养的专业人士生存的空间和价值所在。

posted @ 2009-03-02 00:44 laogao 阅读(688) | 评论 (0)编辑 收藏


以下是一段视频,Ward Cunningham针对Debt Metaphor这个隐喻的由来和人们对它的一些误解进行了澄清:



我最感兴趣的是Burden这一段:Cunningham解释说,经常看到有些开发团队,他们快速的开发出软件产品推向市场,不断的往里面添加新的特性,在这个过程中,不断的学习,但从不把学到的东西、总结的经验教训应用回去,这就像是从银行借贷,但从不想着有一天需要偿还(是不是有点像是在说引发这次次贷危机的美国人的消费习惯和观念?),到最后,你所有的收入都将用于偿还利息,你的购买力也将降为零。映射回软件开发的语境,如果我们在一个较长的时间跨度内,开发一个软件,不断的增加feature,但从不回过头去整理和重构,把对这个软件和这些特性的新的理解和认知写回去,那么最终这个软件、这些feature将不再会有任何实际的价值,对它们做任何事,都将花费越来越多的时间和精力,开发进度也就因此下降为零。


posted @ 2009-02-22 17:50 laogao 阅读(370) | 评论 (0)编辑 收藏


经历了有史以来最忙碌的一周,当然要好好放松一下,除了听上乘的古典音乐,沏上一壶上等的乌龙细细品味,也是一种享受。乌龙茶和紫砂壶可是绝配,如果是安溪的铁观音,加上做工精良的宜兴紫砂壶,那滋味,唇齿留香,别提多惬意了。

好的紫砂壶是需要"养"的,今天专程去茶城败了一只回来,开始"喂"铁观音,哈哈。

DSC_1768s.JPG


posted @ 2009-02-21 22:49 laogao 阅读(571) | 评论 (5)编辑 收藏


先简单介绍一下问题的语境。

手头有个开发了3年的Spring+iBATIS应用(经典三层架构),最近尝试用Hibernate实现原有SQLMap版的部分CRUD操作。除开混合事务和其他一些底层配置细节(如TransactionAwareDataSource、禁用lazy-load等)之外,最大的一个"pattern-mismatch"是:Model层和持久层采用了dirty flag机制,即每次INSERT和UPDATE操作,都会根据每个字段的dirty与否决定是否参加INSERT/UPDATE,而这些dirty flag可以被外部重置,所以业务层的代码,经常可以看到类似这样的pattern:

1- new一个model类并setId() (或者在已有的model上重置dirty flag)
2- set需要update的字段(通常都只是部分字段)
3- 丢给DAO层去update

最终的效果是某张表某个ID的某条记录的某些字段被更新了,而其他字段不受影响,这就是我在标题中提到的所谓"暴力"update,虽不elegant,但却也简单实用,至少很"直接"。

为了让Hibernate版的DAO(默认除Trasient之外全体字段参加INSERT和UPDATE)继续支持这样的"use-pattern",除了按照Hibernate的习惯去配置映射和SessionFactory等之外,我们需要做一些额外的工作:

1- 在BO/Entity类上追加注解
@org.hibernate.annotations.Entity(dynamicInsert=true, dynamicUpdate=true)

2- 实现org.hibernate.Interceptor接口的findDirty()方法,Hibernate提供了一个EmptyInterceptor可以作为起点,方法签名如下:
public int[] findDirty(
    Object entity, 
    Serializable id, 
    Object[] currentState, 
    Object[] previousState, 
    String[] propertyNames, 
    Type[] types
);
返回的int[]包含所有应该被认为是dirty的字段索引,返回null表示默认处理,传入的entity是持久对象,字段列表会通过propertyNames参数传给你。

3- 注入到Spring的Application Context中,类似这样:
<bean id="findDirtyInterceptor" class="gao.sean.hybrid.interceptor.FindDirtyInterceptor"/>

<bean id="sessionFactory"
    class
="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    
    
<property name="entityInterceptor"><ref bean="findDirtyInterceptor"/></property>
    
</bean>

在这样的配置下,业务层的代码就可以继续"暴力"update了。

posted @ 2009-01-29 16:54 laogao 阅读(2820) | 评论 (4)编辑 收藏


如果你使用早前版本的Spring,又恰好采用了Annotation注解方式(而非传统XML方式)配置Hibernate对象关系映射,那么在通过org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean配置sessionFactory时,你一定对annotatedClasses、annotatedPackages有一种说不出的胸闷的感觉,如此以高配置性见长的Spring,怎么在这一个小小的环节上就不能做得再灵活些呢,一定要一个个手写Class路径么?

估计有不少人无奈选择了从AnnotationSessionFactoryBean继承一个自定义的子类,自己实现扫描逻辑,找出@Entity注解过的类清单配置进去。

Spring 2.5.6里有个不怎么起眼的改进,那就是在AnnotationSessionFactoryBean上增加了一个新的方法:
setPackagesToScan(String[] packagesToScan)

有了这个方法,我们不再需要自己动手去实现实体类的扫描了,直接在Spring配置文件中AnnotationSessionFactoryBean这个section上增加类似如下的一个property即可(假定你需要加载的实体类所在的包名match这个字符串"com.**.bo"):
<property name="packagesToScan" value="com.**.bo"/>

你也可以以清单的方式指定多于1条的匹配字串,如:
<property name="packagesToScan">
    
<list>
        
<value>com.abc.core.bo</value>
        
<value>com.abc.auditing.bo</value>
    
</list>
</property>

posted @ 2009-01-29 02:59 laogao 阅读(22695) | 评论 (2)编辑 收藏


Pylons是一个典型的MVC Web框架,在之前的几篇随笔中,我们一起了解了Pylons的安装、默认项目结构、Routes和controller("C")以及SQLAlchemy("M"),在这个系列的最后,我们一起来看看"V"。

在我们的controller代码中,每个action在return的时候,可以选择:
1- 直接return字符串
2- 通过render()函数将输出交给页面模板引擎处理
3- redirect_to()重定向到其他URL

直接return太简单,redirect_to也没有特别需要介绍的,重点看render()。如果你一直follow这个系列,那么在你的controllers/hello.py中,可以看到这样一行import:
from newapp.lib.base import BaseController, render

从lib.base引入了一个render函数,跟到lib/base代码里查看,我们会知道:
from pylons.templating import render_mako as render
其实我们用到的render()函数,是pylons.templating.render_mako的别名。

注: 这里假定你在paster create时选择了默认的mako,其他Pylons原生支持的页面模板引擎还有结构相对更层次化的Genshi和更接近Django实现的Jinja。

render_mako()函数签名如下:
render_mako(template_name, extra_vars=None, cache_key=None, cache_type=None, cache_expire=None)

最基本的用法是给出template文件名,然后通过extra_vars传入参数,Pylons默认查找页面模板文件是在项目的templates子目录,这个路径也可以在config/environment.py中修改。在Pylons中,被推荐的传参做法是使用tmpl_context,在生成controller的时候,已经自动import了tmpl_context并别名为c,这样,我们只需要在c上绑上我们需要传递给模板的数据,模板在解析时,也就能够通过c得到这些数据了。像这样:
c.name = u'Pylons n00b'
return render('hello.mako')

然后,在hello.mako中:
<h3>Hello <b>${c.name}</b>!</h3>

在模板代码中,有些Pylons系统变量/函数是可以直接访问的,包括:
tmpl_context (c) - 用于controller和template传递数据
config - 配置信息
app_globals (g) - 应用的全局变量
h - WebHelpers,包括h.form、h.link_to、h.url_for等等实用函数
request - 请求
response - 应答
session - 会话信息
translator、ungettext()、_()、N_() - 处理国际化

除了基本的${}变量替代语法之外,类似JSP,Mako还支持注释、if/else/for控制逻辑、代码片段、return、标签等,具体的可以扫一眼官方说明:
http://www.makotemplates.org/docs/syntax.html
很精简,也非常容易理解,这里就不详细说明了。

至此,我们已经了解了Pylons最核心的几个组件,足够我们搭建常规的Web应用了。其他值得大家继续挖掘的内容包括:国际化、表单验证(FormEncode)、用户验证和权限(AuthKit、repoze.who、repoze.what)、AJAX、Python 3.0、WSGI基础架构等。

本文是该系列最后一篇,希望通过简单的介绍和学习,大家能够喜欢并顺利的上手Pylons,也希望越来越多的人关注这个优秀的Python Web应用框架。

posted @ 2009-01-27 15:50 laogao 阅读(2200) | 评论 (0)编辑 收藏


在前面的4篇随笔中,我们简要的介绍了SQLAlchemy,不过SQLAlchemy如何被集成到Pylons应用中呢?

首先我们看一下自动生成代码中的model子目录,其中有两个文件__init__.py和meta.py,其中meta.py定义了engine、Session和metadata三个公用变量,而__init__.py提供了一个核心的init_model(engine)方法,该方法分别将数据库engine和经过sessionmaker和scoped_session包装的Session对象植入到meta中,像这样:
    sm = orm.sessionmaker(autoflush=True, autocommit=True, bind=engine)

    meta.engine 
= engine
    meta.Session 
= orm.scoped_session(sm)

这样一来,整个背后的"magic"就还剩下最后一块"拼图":谁来把engine初始化好并调用init_model方法呢?看看config/environment.py就清楚了:
 1 """Pylons environment configuration"""
 2 import os
 3 
 4 from mako.lookup import TemplateLookup
 5 from pylons.error import handle_mako_error
 6 from pylons import config
 7 from sqlalchemy import engine_from_config
 8 
 9 import newapp.lib.app_globals as app_globals
10 import newapp.lib.helpers
11 from newapp.config.routing import make_map
12 from newapp.model import init_model
13 
14 def load_environment(global_conf, app_conf):
15     """Configure the Pylons environment via the ``pylons.config``
16     object
17     """
18     # Pylons paths
19     root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
20     paths = dict(root=root,
21                  controllers=os.path.join(root, 'controllers'),
22                  static_files=os.path.join(root, 'public'),
23                  templates=[os.path.join(root, 'templates')])
24 
25     # Initialize config with the basic options
26     config.init_app(global_conf, app_conf, package='newapp', paths=paths)
27 
28     config['routes.map'= make_map()
29     config['pylons.app_globals'= app_globals.Globals()
30     config['pylons.h'= newapp.lib.helpers
31 
32     # Create the Mako TemplateLookup, with the default auto-escaping
33     config['pylons.app_globals'].mako_lookup = TemplateLookup(
34         directories=paths['templates'],
35         error_handler=handle_mako_error,
36         module_directory=os.path.join(app_conf['cache_dir'], 'templates'),
37         input_encoding='utf-8', output_encoding='utf-8',
38         imports=['from webhelpers.html import escape'],
39         default_filters=['escape'])
40     
41     # Setup SQLAlchemy database engine
42     engine = engine_from_config(config, 'sqlalchemy.')
43     init_model(engine)
44     
45     # CONFIGURATION OPTIONS HERE (note: all config options will override
46     # any Pylons config options)

注意第7行的import和第42、43行代码,是不是豁然开朗?Pylons在初始化运行环境时,从config中读取sqlalchemy相关的配置信息,然后通过这些配置信息创建数据库engine,并调用init_model()方法初始化SQLAlchemy功能的核心对象:metadata和Session。有了meta.Session,我们就可以方便的在代码中执行对model层/数据库的访问了。

posted @ 2009-01-27 14:00 laogao 阅读(1169) | 评论 (0)编辑 收藏


接着前面的例子说,我们定义了book_table和author_table,接下来:
 1 class Book(object):
 2     def __init__(self, title):
 3         self.title = title
 4     def __repr__(self):
 5         return "<Book('%s')>" % self.title
 6 
 7 class Author(object):
 8     def __init__(self, name):
 9         self.name = name
10     def __repr__(self):
11         return "<Author('%s')>" % self.name

这里我们定义两个类,继承自object,类似JavaBeans或者POJO,这里的__init__方法和__repr__方法不是必须的,只是为了创建对象和输出对象内容比较方便。然后就可以用SQLAlchemy的mapper和sessionmaker来建立映射关系并处理持久和查询等操作:
 1 from sqlalchemy.orm import mapper,sessionmaker
 2 
 3 mapper(Book, book_table)
 4 mapper(Author, author_table)
 5 
 6 Session = sessionmaker(bind=engine)
 7 session = Session()
 8 
 9 gia = Book(u'Groovy in Action')
10 ag = Author(u'Andrew Glover')
11 
12 session.add(gia)
13 session.add(ag)
14 session.add_all([Book('Hibernate in Action'), Author('Gavin King')])
15 s_gia = session.query(Book).filter_by(title=u'Groovy in Action').first()
16 s_gia.title =u'Groovy in Action Updated'
17 
18 print "[DIRTY]", session.dirty
19
20 session.commit() # or session.rollback()

如果你用过Hibernate,那么这些代码对你来说,理解起来应该没有任何难度。

假如我告诉你,每次都要像这样先定义Table(schema),再定义class,然后用mapper建立对照,是不是有点那啥?SQLAlchemy的开发者们也意识到这一点,所以从0.5开始,SQLAlchemy可以通过sqlalchemy.ext.declarative支持我们实现更紧凑的model/schema定义:
 1 from sqlalchemy.schema import Table, Column, ForeignKey, Sequence
 2 from sqlalchemy.types import *
 3 from sqlalchemy.orm import relation
 4 from sqlalchemy.ext.declarative import declarative_base
 5 
 6 Base = declarative_base()
 7 metadata = Base.metadata
 8 
 9 bookauthor_table = Table('bookauthor', metadata,
10     Column('book_id', Integer, ForeignKey('book.id'), nullable=False),
11     Column('author_id', Integer, ForeignKey('author.id'), nullable=False),
12 )
13 
14 class Book(Base):
15     __tablename__ = 'book'
16     id = Column(Integer, Sequence('seq_pk'), primary_key=True)
17     title = Column(Unicode(255), nullable=False)
18     authors = relation('Author', secondary=bookauthor_table)
19 
20 
21 class Author(Base):
22     __tablename__ = 'author'
23     id = Column(Integer, Sequence('seq_pk'), primary_key=True)
24     name = Column(Unicode(255), nullable=False)
25     books = relation('Book', secondary=bookauthor_table)

这里我们用到了many-to-many关系,其他的常见用法还包括many-to-one、one-to-many、JOIN、子查询、EXISTS、Lazy/Eager Load、Cascade (all/delete/delete-orphan)等等,大家可以根据需要查阅官方文档。

posted @ 2009-01-27 12:52 laogao 阅读(1674) | 评论 (0)编辑 收藏


在介绍SQLAlchemy最核心最有价值的ORM部分之前,我们再简单过一遍SQLAlchemy提供的SQL Expression Language用法,就从最基本的CRUD来举例说明吧(接着上一篇的示例):

 1 from sqlalchemy import select,update,delete
 2 
 3 conn = engine.connect()
 4 book_ins = book_table.insert(values=dict(title=u'Groovy in Action'))
 5 author_ins = author_table.insert(values=dict(name=u'Andrew Glover'))
 6 conn.execute(book_ins)
 7 conn.execute(author_ins)
 8 book = conn.execute(select([book_table], book_table.c.title.like(u'Groovy%'))).fetchone()
 9 author = conn.execute(select([author_table])).fetchone()
10 bookauthor_ins = bookauthor_table.insert(values=dict(book_id=book[0],author_id=author[0]))
11 conn.execute(bookauthor_ins)
12 conn.execute(update(book_table,book_table.c.title==u'Groovy in Action'), title=u'Groovy in Action (中文版)')
13 conn.execute(delete(bookauthor_table))
14 conn.close()

简单说明一下代码逻辑:
首先从engine建立连接,然后做两个insert动作,分别insert一条book记录(title为'Groovy in Action')和一条author记录(name为'Andrew Glover'),这之后分别再做两次select,得到刚insert的这两条记录,其中book记录的select用到了过滤条件,相当于"WHERE book.title like 'Groovy%'",然后构建一条新的insert语句,用于insert一条bookauthor关系记录,接下来,做一次update,将book.title为'Groovy in Action'的更新为'Groovy in Action (中文版)',最后,在关闭连接之前,做一次delete,删除bookauthor中的记录。

在指定WHERE条件时,.c是.columns的简写,所以book_table.c.title指代的就是book表的title列。更高级的用法是采用"&"、"|"、"!"三个符号,分别表示AND、OR和NOT,加上必要的"("和")"实现复杂的条件定义。由于传递给select()的第一个参数是个list,所以你应该已经猜到了,我们也可以多张表做关联查询。

posted @ 2009-01-26 23:40 laogao 阅读(1383) | 评论 (0)编辑 收藏


在sqlalchemy.schema和sqlalchemy.types这两个module中,包含了定义数据库schema所需要的所有类,如Table、Column、String、Text、Date、Time、Boolean等。还是来看一个例子:

 1 from sqlalchemy.engine import create_engine
 2 from sqlalchemy.schema import MetaData, Table, Column, ForeignKey, Sequence
 3 from sqlalchemy.types import *
 4 
 5 engine = create_engine('postgres://test:test@localhost/test', echo=True)
 6 
 7 metadata = MetaData()
 8 metadata.bind = engine
 9 
10 book_table = Table('book', metadata,
11     Column('id', Integer, Sequence('seq_pk'), primary_key=True),
12     Column('title', Unicode(255), nullable=False),
13 )
14 
15 author_table = Table('author', metadata,
16     Column('id', Integer, Sequence('seq_pk'), primary_key=True),
17     Column('name', Unicode(255), nullable=False),
18 )
19 
20 bookauthor_table = Table('bookauthor', metadata,
21    Column('book_id', Integer, ForeignKey('book.id'), nullable=False),
22    Column('author_id', Integer, ForeignKey('author.id'), nullable=False),
23)
24
25metadata.create_all(checkfirst=True)

首先我们还是create_engine,然后新建一个MetaData对象,把engine绑上去,接下来,开始在metadata中定义表结构(metadata由Table构造函数传入),我们这里定义了3张表,分别是book、author和bookauthor关系表(“多对多”),其中新建一个Sequence对象,专门处理主键生成。最后我们通过执行metadata.create_all()创建数据库表,参数checkfirst=True表示如果数据库相关对象已经存在,则不重复执行创建。

对于已经存在于数据库中的表,我们可以通过传入autoload=True参数到Table构造函数的方式来加载现有的表结构到metadata中,而不必挨个儿再写一遍Column清单。

看到这儿,你也许觉得挺麻烦,不是么?Django和RoR都是可以直接定义数据model类,顺带就把schema也定义了,而不是像这样单独去写表结构的schema,显得很"底层"。确实,这样用SQLAlchemy并不是最优化的,SQLAlchemy本身并不会自动的帮你做很多事,但它基础打得很牢。如果你感兴趣,也可以先去看一下SQLAlchemy的扩展模块Elixir,通过Elixir,你可以像Ruby on Rails那样定义出实体和关系("Active Record")。

在稍后的第4部分中,我们会去了解如何以声明方式来更紧凑的定义我们的model/schema(0.5新特性)。鉴于笔者倾向于更强的控制力,所以在这个系列中就不去介绍SQLAlchemy的其他扩展模块了,如Elixir、SQLSoup等,大家可以根据需要去找下官方文档。

posted @ 2009-01-26 22:14 laogao 阅读(2437) | 评论 (0)编辑 收藏


ORM是个大话题,大到可能好几本书都说不完。SQLAlchemy,别看它刚出到0.5.2,已然是Python世界ORM的事实标准,受到众多开发者和无数框架的青睐。

如果之前没有或很少接触SQLAlchemy,那么学习Pylons可能有相当一部分时间都会花在SQLAlchemy上。通常,人们选择Pylons或者TurboGears而不是Django,SQLAlchemy在这些决定的背后有着很重的分量。作为Pylons学习笔记的一部分,接下来我将分4篇随笔介绍SQLAlchemy,分别是Engine API、Schema Management (MetaData/Types)、SQL Expression Language和Object Relational Mapper。此文为第1篇,重点介绍Engine API。

类似Java的JDBC,Python也有一个类似的数据库访问接口规范,那就是DB-API(目前是2.0),不同的常见RDBMS都有符合DB-API标准的Python库,比如PostgreSQL有psycopg2,Oracle有cx_Oracle等。有了这个基础,SQLAlchemy也就得以方便的通过DB-API连接不同的数据库。

以PostgreSQL为例,通过SQLAlchemy的Engine API访问数据库的代码可以这样来写:
 1 from sqlalchemy.engine import create_engine
 2 
 3 engine = create_engine('postgres://user:pass@localhost/testdb')
 4 connection = engine.connect()
 5 connection.execute(
 6     """
 7     CREATE TABLE book
 8     (
 9       id serial NOT NULL,
10      title character varying(30) NOT NULL,
11      CONSTRAINT pk_book PRIMARY KEY (id)
12     );
13    """
14 )
15 connection.execute(
16     """
17     INSERT INTO book (title) VALUES (%s);
18     """,
19     "The Art of UNIX Programming"
20 )
21 rs = connection.execute("SELECT title FROM book")
22 for row in rs:
23     print "Book Title: ", row['title']
24 connection.close()

基本步骤就是create_engine、connect、execute和close,没有很特别的地方,不过SQLAlchemy的Engine API,并不是简单的DBAPI调用,而是包装了其他内容,如数据库连接池,我们可以在create_engine的时候指定连接池参数和其他额外配置,类似这样:
engine = create_engine('postgres://user:pass@localhost/testdb', pool_size=10, convert_unicode=True)

类似Spring的JdbcTemplate,更多的时候,统一使用SQLAlchemy的Engine API而不是DB-API能给我们带来更大的灵活性,通常也更方便、更安全。

posted @ 2009-01-26 20:46 laogao 阅读(2471) | 评论 (1)编辑 收藏


在开始之前,说点提外话,随着对Pylons了解的深入,你可能时不时需要看看相关组件/软件包是否有更新出来,方法也不复杂,通过"easy_install -U [组件名]"即可,在学习或者是开发过程中,最好是保持环境相对较新,直到出现相对大的release或者即将进入产品部署阶段。

继续介绍Pylons组件,先看个例子。首先用"paster controller hello"增加一个controller,路径中会增加出以下两个文件:
controllers/hello.py
tests/functional/test_hello.py

分别对应新增的controller类HelloController和功能测试类TestHelloController,它们分别继承自WSGIController->BaseController和TestCase->TestController。

我们主要看hello.py,默认内容如下:
 1 import logging
 2 
 3 from pylons import request, response, session, tmpl_context as c
 4 from pylons.controllers.util import abort, redirect_to
 5 
 6 from newapp.lib.base import BaseController, render
 7 #from newapp import model
 8 
 9 log = logging.getLogger(__name__)
10 
11 class HelloController(BaseController):
12 
13     def index(self):
14         # Return a rendered template
15         #   return render('/template.mako')
16         # or, Return a response
17         return 'Hello World'

如果你的服务器没有Ctrl-C停掉,那么这个时候你已经可以通过
http://127.0.0.1:5000/hello/index
看到该controller的处理结果了(Hello World)。

简单改造一下17行:
        from pylons import config
        
return '<br/>'.join(config.keys())

我们就可以在返回页面上显示出所有可以通过pylons.config访问到的参数列表。出了返回文本,也可以通过render()方法交给页面模板引擎生成页面,也可以通过redirect_to()跳转到其他URL。

Pylons是如何找到该请求应该由HelloController的index方法来处理的呢?这背后发生了什么?答案就是Routes。

Routes的作者是Ben Bangert,是Pylons框架三个主要作者/维护者之一,早期的版本主要是仿照Ruby on Rails的routes.rb开发的,有RoR经验的朋友可能一眼就能发现它们之间的相似之处。目前Routes的最新版是1.10.2。

Pylons应用中,routing的配置在config/routing.py,默认生成的内容如下:
 1 """Routes configuration
 2 
 3 The more specific and detailed routes should be defined first so they
 4 may take precedent over the more generic routes. For more information
 5 refer to the routes manual at http://routes.groovie.org/docs/
 6 """
 7 from pylons import config
 8 from routes import Mapper
 9 
10 def make_map():
11     """Create, configure and return the routes Mapper"""
12     map = Mapper(directory=config['pylons.paths']['controllers'],
13                  always_scan=config['debug'])
14     map.minimization = False
15     
16     # The ErrorController route (handles 404/500 error pages); it should
17     # likely stay at the top, ensuring it can always be resolved
18     map.connect('/error/{action}', controller='error')
19     map.connect('/error/{action}/{id}', controller='error')
20 
21     # CUSTOM ROUTES HERE
22 
23     map.connect('/{controller}/{action}')
24     map.connect('/{controller}/{action}/{id}')
25 
26     return map

在这个配置中,对我们刚才的实例起到决定性作用的是第23行,我们的输入URL为"http://127.0.0.1:5000/hello/index",其中"/hello/index"通过"/{controller}/{action}"这个表达式match出controller为hello而action为index的解析结果,从而在controllers目录找到hello.py,和其中HelloController的index方法,进行调用。

map.connect()在上面代码中体现出两种用法:
map.connect('pattern', key=value) - 指定默认的controller、action、id等
map.connect('pattern') - 直接指定pattern

pattern字符串允许通配符,通常在最后一个元素上,比如'/{controller}/{action}/{*url}',将后面的整个URL片段交给前面指定的controller/action处理。除此以外,map.connect()还支持

1- "路径别名",如:
map.connect('name', 'pattern', [_static=True])
如果_static设为"True",表示为"静态命名路径"。
2- 额外的匹配条件,如:
map.connect('/{controller}/{action}/{id}', requirements={'year': '\d+',})
map.connect('/{controller}/{action}/{id}', conditions=dict(method=['GET','POST']))

所有的route优先级为从上到下。Routes除了提供解析进来的URL的逻辑,在我们的controller和template代码中,我们还可以方便的通过WebHelpers的url_for()方法计算相应的URL。

Routes 1.x中的有一些仿routes.rb功能将会在2.0中被去掉,包括Route Minimization、Route Memory、Implicit Defaults等。如果有兴趣的话,可以参考一下官方文档,这里就不一一介绍了。为什么要去掉?当然主要的动机还是减少歧义,避免一些不必要的混淆。至于深层次的原因么,可以参考Tim Peters《The Zen of Python》中的一句经典的Python哲学:Explicit is better than implicit。什么?没有听说过?打开python命令行,输入"import this"后回车,慢慢体会其中的道理吧。:)


posted @ 2009-01-26 16:21 laogao 阅读(3955) | 评论 (0)编辑 收藏


大家新年好!

前一篇随笔中,大家了解了什么是Pylons,有哪些特点,今天笔者继续给介绍默认生成的项目结构。

通过Paste创建新的Pylons应用很简单,就是一句"paster create -t pylons [应用名]"命令,其中"-t pylons"或者全称"--template=pylons",用以告诉Paste我们新建的项目,将是一个Pylons应用,或者说,从一个预定义好的Pylons默认项目模板生成。如果你愿意,你也可以自己来制作新的模板以符合需要。"paster create --list-templates"可以查看当前可用的模板。

假定我们新建的Pylons项目名称为NewApp,那么执行"paster create -t pylons NewApp"后,我们将得到一个新的NewApp目录,其中包含一个docs目录(文档)、一个newapp目录(代码)、一个NewApp.egg-info目录(元数据)和一些顶级配置文件。

在开发过程中,我们经常会用到的是代码目录(这里是newapp)和位于项目根目录下的development.ini和test.ini文件了。注意这里newapp的大小写,Pylons在生成项目的时候,不论你指定的项目名称大小写是怎样,这里会自动.lower()转小写,只有项目顶级路径和egg信息会保留原始大小写,笔者认为这更加符合Web应用的nature。

代码目录下包括config、controllers、lib、model、public、templates和tests子目录,分别用于存放配置(如环境、中间件、路径查找逻辑)、控制器(处理请求)、全局辅助代码(全局变量、helpers等)、模型(后台数据访问)、静态页面/媒体文件、页面模板和测试代码。

最后说说ini文件:默认生成的development.ini和test.ini顾名思义分别对应开发和测试需要的基本配置,我们可以通过修改相应的参数配置来指定具体设定,如服务器IP和端口、数据库连接、日志等。看到这里你也许会问,那么产品环境呢?答案是默认没有生成,你可以从development.ini修改成需要的产品环境配置,也可以通过paster make-config newapp production.ini生成一个默认的产品环境典型配置。

以development.ini为例,Pylons的ini文件主要包括4个部分的内容:

1- 全局默认参数,如
[DEFAULT]
debug 
= true
# Uncomment and replace with the address which should receive any error reports
#email_to 
= you@yourdomain.com
smtp_server 
= localhost
error_email_from 
= paste@localhost



2- 服务器配置,如
[server:main]
use 
= egg:Paste#http
host 
= 127.0.0.1
port 
= 5000



3- 应用程序配置,如
[app:main]
use 
= egg:NewApp
full_stack 
= true

cache_dir 
= %(here)s/data
beaker.session.key 
= newapp
beaker.session.secret 
= somesecret

# If you'd like to fine-tune the individual locations of the cache data dirs
# for the Cache data
, or the Session saves, un-comment the desired settings
# here:
#beaker.cache.data_dir 
= %(here)s/data/cache
#beaker.session.data_dir 
= %(here)s/data/sessions

# SQLAlchemy database URL
sqlalchemy.url 
= sqlite:///%(here)s/development.db

# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*
# Debug mode will enable the interactive debugging tool
, allowing ANYONE to
# execute malicious code after an exception is raised.
#set debug 
= false
简单说明一下,这里的full_stack设置为true表示打开交互式调试和错误报告等功能,"%(here)s"会被替换成项目所在路径,类似相对路径url中的"."转绝对路径,而beaker.*为配置会话相关的设定,如缓存、cookie基本内容等。对于产品环境来说,比较重要的一个配置是"set debug=false",否则一旦出现异常,交互式调试将使得攻击者能够执行系统命令。

4- 日志,如
[loggers]
keys 
= root, routes, newapp, sqlalchemy

[handlers]
keys 
= console

[formatters]
keys 
= generic

[logger_root]
level 
= INFO
handlers 
= console

[logger_routes]
level 
= INFO
handlers 
=
qualname 
= routes.middleware
"level = DEBUG" logs the route matched and routing variables.

[logger_newapp]
level 
= DEBUG
handlers 
=
qualname 
= newapp

[logger_sqlalchemy]
level 
= INFO
handlers 
=
qualname 
= sqlalchemy.engine
"level = INFO" logs SQL queries.
"level = DEBUG" logs SQL queries and results.
"level = WARN" logs neither.  (Recommended for production systems.)

[handler_console]
class 
= StreamHandler
args 
= (sys.stderr,)
level 
= NOTSET
formatter 
= generic

[formatter_generic]
format 
= %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
datefmt 
= %H:%M:%S

OK,这一篇就先讲到这儿,下一篇将介绍Routes和controller。


posted @ 2009-01-26 12:33 laogao 阅读(961) | 评论 (0)编辑 收藏


Pylons是一个Python语言的Web应用程序框架,如果你简单了解过Ruby on Rails和Django,你大概会问,Pylons有什么不一样呢?Pylons最大的特点是模块化,将处理Web应用环境下不同领域、不同问题的软件包集成在一起,形成一个整体,在提供一揽子解决方案的同时,不阻碍你选择别的替代组件。另外,Pylons是目前对WSGI标准支持最好的框架之一,未来的TurboGears 2.0也会基于Pylons构建。

Pylons从Ruby on Rails借鉴了不少东西,比如Routes,比如WebHelpers,从表面看更像是Python版的RoR,不过底下的架构应该说更加轻量和灵活,因为你可以灵活选择自己熟悉或者更贴和具体应用实际的组件,从ORM到页面模板,Pylons只是推荐一些大家普遍比较认可的选项,但并不强制你使用它们。

说完和Ruby on Rails的异同,当然也要回过头来说说同样是Python编写的Django。如果你只是想迅速的构建一个可以支撑大量访问的Web应用,Django是个不错的选择,但和RoR一样,你在很大程度上被限制在一定的pattern中:如果你按照Django的思路去实现你的应用,你会很happy;但一旦你觉得某个组件你不喜欢、不符合某个实际要求,想要来点定制,你就会觉得有些伸不开拳脚,或者工程浩大。目前感觉Django比较不爽的地方有:页面模板较弱,表现力有些不足,也有人说够用了;ORM目前是自己的一套,暂时没有成熟的SQLAlchemy支持,需要第三方包或者自己做;从架构上,Django对MVC的解读是MTV(Model-Template-View),大家都叫作controller的东东,在Django的世界里是view,以至于每次和别人解释,都要多费一番口舌。

Pylons目前版本是0.9.7(rc4),主要用到的第三方/独立组件有Paste、Routes、Beaker、Mako、FormEncode、WebHelpers和SQLAlchemy。安装方法如下:

首先你必须有Python(2.3+),然后你可以选择直接easy_install Pylons或者新建一个Virtual Environment,和系统中的Python环境隔离开,依赖的包可以独立升级。这里我们按照后一种方式,如果你是第一次使用Pylons,建议你也在独立Python virtualenv中安装。

1- easy_install virtualenv (这将安装Python虚拟环境工具)
2- python virtualenv.py ENV (创建新的虚拟环境。这里的ENV是你新建虚拟环境的路径,如"mydevenv")
3- source ENV/bin/activate (激活虚拟环境。如果是Windows的话,这里需要执行ENV\bin\activate.bat)
4- easy_install Pylons (这里使用的是虚拟环境的easy_install安装)

如果你觉得上面的步骤麻烦,Pylons开发团队提供了一个脚本来处理安装过程,下载后用Python执行即可:
http://www.pylonshq.com/download/0.9.7/go-pylons.py

如果需要SQLAlchemy,则再执行一下
easy_install SQLAlchemy

安装成功后,通过
paster create -t pylons [应用名]
即可新建Web应用主框架,然后cd到应用下,通过
paster serve --reload development.ini
启动Web服务,默认地址在
http://127.0.0.1:5000/

更详细的信息,可参考Pylons项目主页:
http://pylonshq.com/

随着使用的深入,笔者还会陆续对Pylons和其他相关组件进行进一步的介绍。祝各位农历新年快乐!


posted @ 2009-01-25 20:05 laogao 阅读(2001) | 评论 (2)编辑 收藏


在Unix环境下,命令行或者shell中sleep和kill是常见的动作,在Windows的.bat文件中处理类似的任务就不那么直接了,备忘如下:

[sleep]
ping 127.0.0.1 -n 需要的秒数+1 -w 1000 > nul

[kill]
taskkill /f /im "进程名(如notepad.exe)"
taskkill /f /fi "WINDOWTITLE eq notepad*"

其中/f表示强制,/im表示image镜像名(可执行文件名),/fi表示filter,后面跟表达式,比如这里的"窗体标题等于notepad*",支持wildcast通配符。


posted @ 2009-01-23 19:36 laogao 阅读(2206) | 评论 (0)编辑 收藏


有时我们需要动态的确定当前采用的Python运行时环境对应的site-packages目录,在Python代码中,可以这样做:

from distutils.sysconfig import get_python_lib
print get_python_lib()

备忘。

posted @ 2009-01-23 19:25 laogao 阅读(2567) | 评论 (0)编辑 收藏


从某种意义上讲,easyb就是Groovy版的RSpec,是一个基于"BDD: Behavior-Driven Development"思维方式的测试框架。其作者Andrew Glover是《Groovy in Action》一书的合著者之一。项目的主页在:

http://easyb.org/

不多废话了,上代码,一个story大概长成这个样子(为了方便大家理解,举一个无比弱智的例子):
scenario '1+1应该等于2', {
    given 
'a和b分别等于1', {
      a 
= 1
      b 
= 1
    }
    when 
'c是a+b的和', {
      c 
= a + b
    }
    then 
'c应该等于2', {
      c.shouldBe 
2
    }
}

如何在Eclipse环境下跑这段story脚本?请参考官方文档:
http://code.google.com/p/easyb/wiki/ConfiguringEclipseToRunEasyb

最后你的输出应该类似:
Running first easyb story (FirstEasybStory.groovy)
Scenarios run: 
1, Failures: 0, Pending: 0, Time Elapsed: 0.629 sec

1 behavior run with no failures


posted @ 2009-01-04 22:28 laogao 阅读(348) | 评论 (0)编辑 收藏


1年多以前的2007年11月,著名的钢琴家Alfred Brendel对外宣布了告别演出的日期和地点:2008年12月18日,维也纳金色大厅。瞧我这记性,今天才想起来。

brendel-farewell.jpg

有趣的一个细节是,告别演出上,Brendel的选曲是Mozart的9号降E大调钢琴协奏曲,"Jeunehomme" ("Young Man")。

最近听得最多的,是Brendel演绎的Brahms的1号钢琴协奏曲,虽然不是他最最擅长的Beethoven、Schubert和Mozart,但已经相当精湛传神。

4天以后是大师78岁诞辰,按照中国习俗,提前祝贺一声,生日快乐!大师走好,我们会想你的。

posted @ 2009-01-01 17:25 laogao 阅读(364) | 评论 (0)编辑 收藏


老家有个俗语,叫"嗲言",大致的意思接近"矫情的文字和语言",2008年就要过去了,有些按捺不住,要发点"嗲言"。

08年发生了很多大事,不论国内还是整个世界而言,都是"多事"的一年。对我来说,最大的一件事,应该就是Tony的降生:经过大半年的期盼,和最后半个月全家紧绷的神经,小家伙终于呱呱坠地了,我也名正言顺的升级为老爸。

回顾过去一年的学习和工作,几乎想不出有什么亮点,感觉自己的时间被各种事务瓜分的七零八落,原本的学习计划和想要做的"大事",也都很难一一实现。公司原有团队核心人员从07年下半年到08年不断的流失,而从产品的角度,也到了一个平台期,之前冲刺赶工带来的各种深层次问题,都逐渐浮现。团队要建设,产品要腾飞,都是费劲的事儿,更何况还有来自项目现场的压力。很多时候,我不得不退化成SCM专员和搬运工,代码、版本、分支、补丁、发布环境、脚本、新特性……还好我很久以前就学会了细心、耐心和苦中作乐,不然我早该崩溃了。

09年,人生的第30个年头,该做点什么呢?我想,我必须从SCM这样琐碎的事务和需求的海洋中走出来,去做更有意义的事,对团队对个人都更有价值的事,去学习更多新的知识和解决问题的方法,帮助自己和身边的人走向成功。


posted @ 2008-12-31 20:31 laogao 阅读(364) | 评论 (2)编辑 收藏


本篇是上一期《摆脱iTunes》的续篇。

话说通过openSUSE 11.1下的Banshee播放器重建iPod的iTunesDB后,Podcast和Artwork丢失。后来试用中还发现一个问题,那就是Banshee不能很好的支持修改iPod上现有媒体的元信息。不甘心,找来gtkpod,版本0.99.12,发现还真的是Banshee自己的问题:在gtkpod下,可以很完美的对iPod现有媒体文件进行修改,比如更改专辑名称、艺术家信息等,甚至连封面artwork都能编辑了,呵呵,爽。

希望能给有类似困惑的朋友一个参考。


posted @ 2008-12-30 23:57 laogao 阅读(249) | 评论 (0)编辑 收藏


总算逃出iTunes的魔掌了,叹口气,感慨一下。

自从去年(07年)购进一台iPod Classic开始,iTunes就成了我生命中无法割舍的一部分,不是因为它好,而是没办法,离开iTunes,我无法给我的iPod添加和删除媒体文件。用过iTunes你就知道,很多东西虽然看上去比较眩,但操作起来,蹩脚的让人难以忍受,视频播放性能也很差,兼容度不够不说,自己的格式经常也是卡卡的。

如果说上面的这些问题都还能够克服,让我最不能接受的是,iTunes没有for Linux的版本。这一年多以来,辗转于Ubuntu、Arch Linux、openSUSE,一直都被Apple/iTunes歧视。看到这里你也许会问,既然是Linux的fans,为什么要买Apple的东西?其实这个问题也不难回答,因为iPod是当时市面上能够买到的综合质量最好的便携式mp3播放器。

非iTunes同步iPod最大的障碍,在于iTunes对iPod存储文件的目录结构的处理,除了把文件名称改的面目全非,然后在一个很晦涩的文件(iTunesDB)中定义出最终的专辑、艺术家、曲目到具体文件的"链接",而且(较新版本的iPod)会根据设备ID对这些数据进行hash,以至于非iTunes工具一不小心就容易把iTunesDB破坏,从而造成iPod无法正确读取具体的媒体文件,如果操作无法恢复,那么你的整个iPod资源库能否找回,就要看运气了。当然,高级用户可能知道,其实媒体文件是存放在iPod_Control文件夹下的,虽然目录和文件名称被改掉了,但从文件属性元数据中,还是能够恢复出类似专辑名称等,但如何重建iTunesDB,可能唯一可靠的方式,就是重新从iTunes导入了。

经过一番折腾,终于在Linux环境搞定了iPod的媒体同步,当然,也是冒了些风险。首先需要安装libgpod和gtkpod,虽然它们的最新版发布也有挺长时间,但与之配合的"前端",如Banshee,Rythmbox当时还没能很好的处理设备ID读取和使用,而gtkpod本身document也还不是非常完善,于是相对新的iPod Classic还是无法正常处理媒体库读取和重建。前不久装上了openSUSE 11.1,自带的Banshee 1.4.1号称是支持iPod Classic的同步的。而我又不想太过激进去装Rockbox固件,软件方式的媒体同步就成了最合理的方式。打开Banshee,连上iPod,果然无法正确识别现有的媒体内容(全部划到"其他"),要想看到,只能"重建"。豁出去了,做好必要的备份后,开始探险之旅... 经过十几分钟的等待,wohoo! 成功了!除了Podcast和Artwork,所有媒体都完整的出现在Banshee界面中,断开以后,iPod自身也能够识别这些媒体列表,总算功德圆满,可以和iTunes说拜拜了。


posted @ 2008-12-27 23:28 laogao 阅读(945) | 评论 (2)编辑 收藏


周末花时间看了Rick Evans在London Spring User Group (LSUG)关于Spring 3.0介绍的视频,地址在这里:
http://java.dzone.com/videos/a-look-forward-spring-30

根据Rick的介绍,Spring 3.0将于明年2月中旬正式发布,其中比较重要的两个亮点是:

1- JDK 5将成为Spring 3.0的最低要求,因此很多遗留代码得以重构,更加清晰;
2- 引入了新的Spring Expression Language (SPEL)用于描述XML和Annotation中的配置信息。
(Rick还用了大量篇幅介绍Spring 3.0如何在API和配置层面支持REST,不过这不在我兴趣范围内)

除了上述两大亮点,还有如下一些值得一提的变化:

1- 去掉了Commons Attributes,减少了很多相关依赖;
2- 不再支持Struts 1.x;
3- 全面转向Listener-style的context加载方式;
4- 源码组织更加模块化,每个子模块都是独立项目;
5- 构建环境抛弃Maven,转为使用ANT+Ivy; (笔者非常赞成的一个变化)
6- 源码库由CVS全面转向Subversion。("逃离"CVS是大势所趋?)


posted @ 2008-12-27 17:55 laogao 阅读(2753) | 评论 (2)编辑 收藏


今年发生了太多的事,圣诞节是年底前最后一个重要节日了,公司置办了一棵圣诞树,下班的时候,路过教堂,看见里面很多的人,心想,真的是过节了,是不是应该开心些才对。最近也不知道怎么回事,总是有些郁郁寡欢,身心疲惫,没有所谓的节目,也没有所谓的心情,只有不断的学习和工作。有时候想想,一个人如果要求太高,其实也挺累的,自己累,别人也累,不是么?问题是,多高才是"太"高呢?

如果你和我一样,这个时候还对着电脑,试试对自己说:停下来,喘口气,收拾一下疲惫的心灵,要准备迎接明年的挑战喽!


posted @ 2008-12-24 22:22 laogao 阅读(289) | 评论 (0)编辑 收藏


和11.0一样的问题,当你在openSUSE 11.1中配置好Packman资源库后,就能直接通过YaST2安装w32codec-all和MPlayer,不过这样并不能正常播放常见的rmvb格式视频,MPlayer报告找不到匹配的video解码包,声音能听到,但图像出不来。

解决方法是:

去Real的官方网站(选US站、免费播放器下载、Unix版)下载最新的RealPlayer 11安装包,文件名RealPlayer11GOLD.bin,到本地后chmod u+x,执行该文件进行安装,按照提示,安装路径指定为/usr/lib/RealPlayer10 (注意这里是MPlayer提示的路径,不是笔误)。完成安装后再次使用MPlayer即可正常播放。


posted @ 2008-12-20 08:11 laogao 阅读(1869) | 评论 (1)编辑 收藏


就在数分钟之前,openSUSE 11.1正式release了,主要的新特性包括:

Linux Kernel 2.6.27.8rc1
GCC 4.3.2
glibc 2.9
X.Org 7.4
Virtual Box 2.0.6
PostgreSQL 8.3.5
MySQL 5.0.67
Eclipse 3.4
gtk+ 2.14.4
Python 2.6.0
Ruby 1.8.7
Perl 5.10.0
Mono 2.0.1
Qt 4.4.3
PHP 5.2.6
openJDK 1,2b11
KDE 4.1.3 + 3.5.10
Firefox 3.0.4
OpenOffice 3.0
KOffice 1.6.3
Mono 2.0.1
GIMP 2.6.2
...

更多内容
openSUSE主页: http://www.opensuse.org/en/
11.1功能清单: http://en.opensuse.org/Featurelist_11.1
下载页: http://software.opensuse.org/


posted @ 2008-12-18 22:23 laogao 阅读(502) | 评论 (0)编辑 收藏


初学PostgreSQL的朋友可能会有这样的疑惑:如何重命名已经建好的数据库?因为PostgreSQL默认的客户端pgAdmin III并没有地方可以让我们去修改某个现有的数据库的名称。遇到这个情况,可能不少人选择了backup -> drop -> create -> restore的方法,其实大可不必。

首先,确保没有用户连接到需要改名的数据库,包括你自己。你可能会问,我不连上去,怎么执行更名的命令呢?其实连到其他数据库,比如默认的postgres维护数据库即可。
然后,执行下面的语句,假定你要更名的数据库现在的名称为abc,希望更改成cba:

ALTER DATABASE abc RENAME TO cba;

That's it.


posted @ 2008-12-17 18:33 laogao 阅读(4238) | 评论 (0)编辑 收藏


提示: 流水账+非技术贴,赶时间的朋友请跳过。

最近一段时间以来,家里的PC(平时也就是给老爸老妈玩玩游戏看看股票什么的)开机状态下声音狂响,运行一些高CPU消耗的程序时有死机(直接跳掉关机)。实在不胜其扰,今天终于下定决心给它来个体检。

根据鄙人并不丰富的经验,噪音肯定是来自风扇,而时有发生的自动关机现象,怀疑是风扇问题引发的散热不足导致CPU或者其他核心组件过热。观察下来CPU温度并不是很离谱,更加重了疑虑,准备开箱检查。简单的用螺丝刀把手压停风扇的办法,很快找到了问题风扇:确实不是CPU,也不是显卡,而是北桥芯片上的那个!关机后,手工尝试拨动叶片,也能感觉到引起噪音阻力,看来确定是它无疑了。

怎么办呢?不知道是nForce芯片组的特点,还是GIGABYTE这个系列的特点(手头这块主板型号是GA-M55SLI-S4),北桥芯片上除了散热片,还在散热片上集成了一个风扇,看来这个芯片组发热蛮厉害的,要命的是这块散热片+风扇(也就是北桥芯片)的位置正好在PCI-E插槽的末端,也就是说正好被显卡挡在下面,空间十分狭小,如果要更换散热片/风扇,也只能是找最薄最小的那种,还不能保证插孔间距是标准的。

GA-M55SLI-S4.jpg

不过既然都到这份儿上了,索性做到底,试试换一个吧。从一个废弃的老显卡上拆下来一块散热片带风扇,目测和主板上的那块长方形散热片卡口间距一致。由于这个散热片的特殊位置,害得我只有把主板卸下来才得以拆除,不过新的问题又来了,间距并不标准!至少和我之前卸下来的显卡风扇间距不一致,要宽那么一点点。我无语了,只好闷着头回去看看出问题的散热风扇还有没有什么补救的措施。经过一番敲敲弄弄,"手测"风扇叶片,感觉比先前顺了很多,赶紧接上电源,居然就这样奇迹般的不响了。

Google了一下,网友对这块主板的噪音(貌似都是北桥芯片上这块风扇的事儿)也多有抱怨,看来偶遇到的不是个案啊。不管怎么说,撞大运也好,对症下药也好,问题总算是解决了,功夫没白费:"整个世界安静了"。


posted @ 2008-12-17 00:51 laogao 阅读(1364) | 评论 (0)编辑 收藏


Python 2.6发布两个月后,Python 3.0正式release了。

Download: http://www.python.org/download/releases/3.0/
What's New:http://docs.python.org/whatsnew/2.6.html#python-3-0


posted @ 2008-12-04 19:30 laogao 阅读(265) | 评论 (0)编辑 收藏


算下来,今天已经是我家宝宝出生第20天了,可能由于是比预计的日期有所提前,至今我仍在寻找当爹的感觉,至少这种感觉还没有他还在妈妈肚子里的时候那么强烈:仿佛突然之间,就有一个小生命被塞到了你的怀里,奇妙的让人不可思议。

宝宝的名字倒是很早就想好了:海桐,英文名Tony(似乎预感就是男孩儿,女孩儿英文名压根就没想过)。

海桐(Pittosporum tobira)是一种植物,为亚热带树种,喜温暖湿润的海洋性气候,喜光,亦较耐荫。对土壤要求不严,粘土、沙土、偏碱性土及中性土均能适应,萌芽力强,耐修剪。取这个名字,一方面宝宝出生在上海,另外也借此寓意希望他健康成长,拥有旺盛、顽强的生命力。


posted @ 2008-11-25 12:45 laogao 阅读(256) | 评论 (1)编辑 收藏


实在受不了在中文Windows下Java(Swing)程序默认的字体,那叫一个难看。如果你和我一样,那么希望下面的小贴士可以帮到你(以JDK 1.5.0为例):

1- 找到JRE目录,如果你安装的是JDK,那么在JDK的目录下可以找到jre子目录,就是它了;如果你安装的JRE,那么默认应该在Program Files\Java\jre1.5.0_...。
2- 进入JRE目录下的lib文件夹,你应该可以看到很多fontconfig开头的文件,找到fontconfig.properties.src,拷贝一份,重命名为fontconfig.properties。
3- 打开fontconfig.properties,你会看到一大堆字体相关的配置,找到allfonts.chinese-ms936这一条(通常在最前面),可以看到默认设置为SimSun,修改这个配置,选填你需要的字体名称即可,如"Courier New"、"Consolas"等。

更详细的配置,参考:
http://java.sun.com/j2se/1.5.0/docs/guide/intl/fontconfig.html


posted @ 2008-10-24 11:36 laogao 阅读(3473) | 评论 (0)编辑 收藏

     摘要: 由于工作需要,今天简单的看了一下Java生成PDF的相关资料。综合看下来,除了使用报表平台和OOo的附带工具,目前使用较为普遍的有两个途径:iText和Apache的FOP。从实际出发,我们分别看看两者处理带有中文的PDF的具体用法吧。  阅读全文

posted @ 2008-10-05 23:28 laogao 阅读(13634) | 评论 (11)编辑 收藏


就在国庆大假这几天,Python 2.6 (final)悄然发布了,作为为Python 3000 (3.0)铺路的2.x更新版,2.6的发布颇具有里程碑式的意义。

Download: http://www.python.org/download/releases/2.6/
What's New: http://docs.python.org/whatsnew/2.6.html


posted @ 2008-10-04 21:29 laogao 阅读(445) | 评论 (0)编辑 收藏


动机

FX - 全幅当然是最大的动机
7 - 幸运数字 (D70s、G7、D700)
宝宝出生 - 要为宝宝准备拍摄工具
29岁生日 - 是啊,马上奔3了
反转冲印麻烦,越来越少,越来越贵 - 上海已经涨到25/卷(单冲),且各家风格、质量参差不齐
入门/业余 -> 高级发烧   - 原本玩EOS 5和Sigma EX系的人,怎么能停留在D70s
没有DX头负担 - 之前有兼容FM3A的考虑,所以手头没有DX头,FX可以无缝升级
双机双镜  - 其实加上小三是3机3镜(不含GR1S和G7)
手动头测光 - 其实手头只有一个35/2AIS是手动,不过今后会不会淘其他手动头玩呢?会不会ZF呢?呵呵
闪光灯同步终端 - "一代神灯"SB-16终于可以从热靴上解放了

感受

结实 - 之前有摸过D300,不意外,但仍然觉得够份量,外拍1天明显感觉手酸
色彩 - 饱满,还原真实,LCD预览已经很讨人喜欢
直出 - JPEG直出已经有很高质量,包括高ISO下的片子
对焦 - 坚决,很少出现"拉风箱",暗光条件下同样表现出色
顶极 - "N家顶极机身三大特性"占了两项 (机顶左侧拨盘、圆取景器)

总体来说D700很让人放心,有了它,不用再想D3了。


posted @ 2008-10-03 22:39 laogao 阅读(438) | 评论 (0)编辑 收藏


Uma Thurman一直是我比较欣赏的女演员之一,10年前的一部影片The Avengers中和Ralph Fiennes演对手戏,让人印象深刻。"The Life Before Her Eyes" (豆瓣) 是Uma出演的新片,讲述的是美国某中学一次校园枪击事件背景下,一个"问题少女"对生命、亲情、友情的反思、觉醒和抉择。

整个影片节奏张驰有度,看似随意的蒙太奇式的镜头切换,在影片结尾你终于明白整个故事时,变得完全顺理成章,完美的交织在一起。画面和语言的处理也十分见功力,是一部唯美而略带伤感的片子。在当下这个充斥着铜锈气味的电影大环境下,如此精雕细琢的作品,实在不多见,适合静下心来观看和回味。


posted @ 2008-09-07 23:09 laogao 阅读(382) | 评论 (0)编辑 收藏


通过Groovy实现邮件通知(其实是转发到ANT)十分容易,先上代码:

 1 ant = new AntBuilder()
 2 
 3 def mail(subject, body, attachment = [dir:".",files:[]]) {
 4     ant.mail(mailhost:"mail.com", mailport:"1025", user:"mailer", password:"123", subject:"${subject}") {
 5         from(address:"nobody@mail.com")
 6         to(address:"nobody@mail.com")
 7         message("${body}")
 8         attachments() {
 9             if (attachment.files) {
10                 fileset(dir:"${attachment.dir}") {
11                     attachment.files.each {
12                         include(name:it)
13                     }
14                 }
15             }
16         }
17     }
18 }
19 
20 attachment = [dir:"/tmp", files:["some.properties","some.sql"]]
21 mail("Test mail message at ${new Date()}""This is a test message.", attachment)
22 

这个简单的例子很好的展示了如下Groovy特性:
1- Groovy脚本可以不需要定义任何class,方法定义和实际调用也可以混在一起,十分顺手。
2- 定义变量不需要指定类型,只要赋值即可,不过运行期依然是强类型。
3- 方法参数可以有默认值。
4- List和Map的构建直接在语义层面提供支持,如[a:1,b:2]和[1,2]。
5- GString使得我们可以方便的在String中引用变量甚至是表达式,如"${a.b.c}"或"${new Date()}"。
6- 逻辑判断在true/false基础上有所扩展,[](0个元素的List)和null均做false处理。
7- Closure支持,方便我们在外围代码处“当场”指定处理逻辑,省去了大多数在Java中需要匿名内部类来处理的麻烦,如attachment.files.each { .... },只有一个传入参数时,可直接用it指代。
8- 与ANT的无缝集成,以及对Builder模式的良好支持,使得我们可以写出上述初看上去有些不可思议的代码。

P.S. 虽然Groovy自己已经bundle了ANT,可以直接使用其中的绝大多数功能,不过为了调用ANT的mail task,还需要将ANT发行版中带有的ant-javamail.jar以及JavaMail API对应的jar包(可以从Sun网站下载)加到classpath。如果你的JDK版本低于6.0,还需要activation.jar。


posted @ 2008-08-27 18:55 laogao 阅读(727) | 评论 (0)编辑 收藏


前一篇随笔提到目前计划系统学习Python和Groovy,有什么比实际使用更好的学习途径呢?1年多以前,我曾经在另一篇随笔提到:当ANT不够用时,可以用JRuby+Antwrap,这是一个可行的方案,并且经过了长期实战的考验。不过Groovy可以做的更好(感兴趣的朋友可以和Antwrap版对照一下):

 1 #!/usr/bin/env groovy
 2 
 3 ant = new AntBuilder()
 4 root = ":pserver:cvsuser:password@10.10.10.1/cvsrepo/SampleProduct"
 5 
 6 def checkout() {
 7     ant.cvs(cvsroot:root,command:"checkout -A","package":".",dest:"cvsoriginal",compressionlevel:"9")
 8 }
 9 
10 def update() {
11     ant.cvs(cvsroot:root,command:"update -A -d","package":".",dest:"cvsoriginal",compressionlevel:"9")
12 }
13 
14 def compile(project) {
15     ant.javac(srcdir:"cvsoriginal/$project/src",destdir:"cvsoriginal/$project",target:"1.5",encoding:"GBK")
16     ant.copy(todir:"cvsoriginal/$project") {
17         fileset(dir:"cvsoriginal/$project/src") {
18             exclude(name:"**/*.java")
19         }
20     }
21     ant.jar(destfile:"build/$project.jar",basedir:"cvsoriginal/$project",manifest:"MANIFEST.MF") {
22         exclude(name:"src/**")
23     }
24 }
25 
26 // to actually call your target
27 checkout root
28 

代码更紧凑,与Java的集成更无缝。只需要简单的培训,有Java基础的朋友就能上手,不必再额外学习和习惯Ruby的语法,不用gem install,也不用去monkey-patch个别文件来集成和打包Ant、Antwrap和JRuby,只需要一个groovy-all-x.x.x.jar加上自己的脚本即可轻松搞定。

[2008-08-26 19:25:00 更新] 经过实际环境测试,原来JRuby(1.1)+Antwrap需要24分钟完成的构建,改用Groovy(1.5.6)后,仅需要16分钟,对于需要经常处理构建的项目和产品来说,这8分钟还是相当可观的。


posted @ 2008-08-25 19:38 laogao 阅读(324) | 评论 (0)编辑 收藏


从开始专心学习Java到现在,已经7年了,非常幸运的,在这7年中,除了1年的“半工半读”和1年的.NET项目,累积有5年都是从事的Java为主的应用开发,应该说,Java伴随我走过了从入行到站稳脚跟最关键的几年。从某种意义上讲,我应该感谢Java。

然而,随着时间的推移,接触到的不同的东西越来越多,自己对不同问题的看法和解决问题的思路越来越成熟,Java虽然是全能型的语言,也变得越来越无法满足日常工作和娱乐的需要,在一些特定的场合,也越发别扭,有时我甚至会怀念学生时代的Pascal/Delphi和后来的C/C++。回过头去看自己,从刚入行时的Java fanboi,到现在这样一个pragmatist和purist的结合体,是多么有趣的转变。

在过去的2年多,除了Java和.NET,陆陆续续接触到并有过简单使用经历的编程语言,有bash、PL/SQL、JavaScript、PHP、Perl、Ruby/JRuby、Scala、Python/Jython、Groovy等等,不过都没有系统的学习过,基本就是拿来主义,什么好用用什么,解决手里的问题为主。

也许是工作性质的原因,日常要处理的非技术性任务越来越多,留给具体编程的时间现在一天比一天少,编程带来的乐趣和解决技术问题带来的快感,就显得十分珍贵。所以我下定决心一定要系统的学习1~2种和Java/.NET不同的编程语言。一开始这个选择并不容易,我曾经还半调侃式的和一个朋友讲:“Python, Ruby, Scala, Groovy, 一个都不能少”,经过一段时间的权衡之后,还是比较自然的作出了最后的选择:Python和Groovy。

Python这个选择其实并不难,留意Python这门语言,其实说起来也有差不多3年了,它完全符合“和Java/.NET不同的编程语言”这个条件,而且应用面很广,也十分成熟,功能也非常强大,加上大量现成的类库,能够胜任很多不同类型的编程任务。基本上这是一个不用任何思想斗争的选择。

Groovy这个选择相对没有那么直接,至少在我真正用Groovy上手做一些东西之前,对它并没有特别的感觉,甚至质疑它存在的价值,因为有Jython和JRuby的选择,为什么一定要Groovy呢?到最近开始接触Groovy,才逐渐了解到它的出身(Groovy的作者受到Python的启发,不过后来Groovy发展的越来越接近Ruby),和它在“兼容”Java代码的前提下为Java语言带来的巨大的表达力提升。对于有Java基础的人而言,Groovy十分容易上手,而且可以帮助我们简化很多繁杂的任务,比如自动构建和自动化测试,而这正是我目前需要处理的。

最后简单说说其他几个落选的原因(除了时间有限之外):
bash - 目前掌握的基本够用,发现不够时,完全可以用Python代替。
PL/SQL - 基本很少使用了,偶尔需要维护,今后深入用的机会也不多。
JavaScript - 对“网页”版的编程语言可能有天生的偏见,尤其是作为Java fanboi,当然对它“盗用”Java这个名字是有意见的。
PHP - 用的机会很少,而且过于quick&dirty,不是我喜欢的风格。
Perl - 虽然功能强大,但是感觉语法有些terse,不是很适应,能处理的任务,基本上Python也可以。
Ruby - 语法和设计理念还是有一些认同,但是对Unicode的支持和部署环境的支持都还不是很让人信服,另外,拿孟岩的话说,Ruby是一门魔幻语言,我不喜欢过于魔幻的东西,而更习惯具体直接的代码。
Scala - 也是一门和Java平台关系密切的语言,不过有些“学院派”,函数式编程固然是亮点,但短期内看不到太多的学习价值。

所以,综上所述,最后再点一下题,08年秋季的学习计划是:系统学习Python和Groovy。


posted @ 2008-08-20 00:33 laogao 阅读(824) | 评论 (0)编辑 收藏


在前两天刚结束的OSCON 2008上,MySQL AB的Brian Aker对外传达了一个很重要的信息:新的MySQL分支,代号Drizzle,将在现有MySQL基础上进行大刀阔斧式的改造,使之更模块化、更加适应新时代的计算环境,同时裁减掉现有很多“企业级”功能,如存储过程(对,你没有听错)、视图、触发器,构建出简单、可靠、易于管理的数据库管理软件。给人一种感觉,那就是Drizzle将更加亲近Web,而与“企业”运算渐行渐远,这似乎更贴合MySQL最初的vision和受众。

据悉Drizzle已经得到了不少MySQL核心开发人员的认可和支持。

我们大概还依稀记得当初Sun收购MySQL时,曾经信誓旦旦的要将MySQL从一个以支撑Web应用为主的市场慢慢渗透到“企业级”应用中,如今一支名叫Drizzle的fork版本横空出世,不知道这个“麻雀变凤凰”的美丽故事接下来还将如何演绎,让我们拭目以待。


posted @ 2008-07-30 22:24 laogao 阅读(356) | 评论 (1)编辑 收藏


Firefox不久前推出了3.0.x系列的第一个升级版3.0.1。周末的时候对系统做了一次升级,我用的Arch Linux完整只需要一个命令,方便的没话说,顺便也就把Firefox也升级到了3.0.1。

说点题外话,由于Mozilla对Firefox的分发有着很严格的要求,很多Linux发行版都有自己的命名,最有名的当然是Debian的"Iceweasel",一个"Firefox",一个"Iceweasel",倒也相得益彰。其余大大小小的Linux发行版则更多的使用另外一套可自由分发的代号:1.5是"Deer Park",2.0是"Bon Echo",3.0则是"Gran Paradiso",3.0刚出的时候,也用过非正式的代号"Minefield"。

升级很顺利,再次打开Firefox,已经是3.0.1版。不过这个时候有个小小的麻烦出现了:经常使用的MySocial 24x7插件(用它可以方便的查看和更新FriendFeed)和3.0.1不兼容,被disable掉了。呵呵,不过这可难不倒我,拿到官方的MySocial的xpi包,简单的检查了一下,便发现了问题所在:其实是MySocial插件本身打包的时候,指定了很具体的3.0.0.x这个最高版本,而我现在更新后的Firefox是3.0.1,难怪会报不兼容。1.5~3.0.0.x都是兼容的,3.0.1肯定没啥问题啦,所以就DIY一下吧,轻松搞定。

具体方法如下,供各位爱好者参考:
xpi格式其实就是一个压缩文件,打开以后,找到install.rdf文件,其中有一段
        em:minVersion="1.5"
        em:maxVersion="3.0.0.*"
修改em:maxVersion为"3.0.*.*",重新打包即可用来安装。

其实不光MySocial,其他插件如果遇到类似问题,也可以参照处理。如果你碰巧需要,又不想去DIY,这里是做好的版本,供下载使用,版本0.5,修改扩展名.zip为.xpi即可。


posted @ 2008-07-28 22:12 laogao 阅读(809) | 评论 (0)编辑 收藏


不知不觉已经1个多月没有更新了:工作占据了大量的时间和精力,没时间写随笔,没时间看Google Reader,甚至连Twitter、FriendFeed等快餐式的文字也被压缩掉了,真想好好喘口气。题外话先说这么多,和大家聊一件鸡毛蒜皮的“小事”。

上个周末的时候,我家所在的小区统一进行天然气改造,其实具体到每一户,并不是很大的工程,无非是热水器和炉具的燃气喷嘴需要更换。不过由于生产厂家采用的工艺配件等各不相同,这次改造首先是登记了各户的热水器和炉具的品牌,然后安排联系厂家在统一的时段上门进行改装。正好我家两样东西分别来自一家本土企业和一家外企,于是就有了下面的简单比较(“本”代表本土企业,“外”代表外企):

[进门]
本:你家是XXX室吧?我来换XX的。然后就进来了,赤脚。根本来不及说的。
外:您好,您家的XX是XX品牌的吗?我是XX的工程师,负责帮您更换XX。然后从自己包里拿出准备好的鞋套,在我的示意下进入厨房。

[改造过程]
本:你家这个怎么是这样装的?这样不好的,有什么问题不方便检修,如此云云。然后不管是喷什么除锈剂,还是需要敲打什么的,根本不管你家是否有小孩、孕妇、老人什么的,直接上手就干。甚至我开个窗他也要管:这个只是除锈剂,又没毒的。。一副不耐烦的样子。
外:整个过程都很注意安静,时不时还跟我讲解这次改造需要注意的一些事项,只要是和他们产品相关的,都一一介绍到。

[签收]
本:改装完了之后,大楼的天然气还没有通,于是就告诉我,等天然气来了,试试这样做,如果火不够大,就动一下这个机关,就好了,说着就拿出一个沾满油渍的本子,放在餐桌上,让我签字,然后就匆忙离开了。
外:改装完以后,由于大楼还没有开始供气,于是就先离开了一下,等到供气开始再回来检查是否能够正常使用,以及是否存在漏气的情况,所有这些做完之后,才拿出保修卡让我签收,并且介绍保修的细节。

如果换作是你,你更喜欢哪个工程师呢?这次也许是个特例,但也从一个侧面反映出本土企业和外企相比的一个具有普遍性的差距:这不仅仅是专业程度上的差异,甚至可能从专业角度,那个本土企业的工程师,效率还相对更高一些。我想更重要更核心的还是企业的服务意识,尤其是一线员工的服务意识。外企通常宁可多花些代价在细节上,比如培训、比如配套的奖金/晋升制度,而中国的很多本土企业,则更加强调成本控制和所谓的“规模效应”,殊不知这样杀鸡取卵、一味追求成本和规模的方式,从长远看,肯定是要付出代价的。

为什么相当数量的本土企业会在竞争中输给硬件实力相当、甚至不如自己的外企?为什么许多人对不少洋品牌会形成强烈的信任感,甚至近乎崇拜的心理,而对国货却总有那么多不屑和排斥,完全不管洋品牌的定价存在多大的暴利?不知道像这样的学费,我们还需要付多少,还需要用多少代人的青春去换。


posted @ 2008-07-24 00:31 laogao 阅读(559) | 评论 (4)编辑 收藏


刚看完法国对意大利的比赛,准备下载Firefox 3,结果你猜怎么着?Mozilla英文官网上提供的链接,到现在仍然是2.0.0.14,尽管图标已经更新成了Firefox 3,而Mozilla中文官网,干脆就连不上了。(实际上是mozilla.org.cn连不上,不过貌似中文官网不知什么时候已经改成了mozillaonline.com,但提供的仍然是RC3。)

其实在昨天,就已经有人对Mozilla选择在PDT 10:00 AM开始Download Day提出了异议,因为既然Firefox是面向全球的粉丝,这次下载活动也是全球范围内进行,为什么要选择在大半个欧洲都处于当天深夜,大半个个亚洲都已是第二天凌晨的时候启动呢?

好吧,我们尊重Mozilla的选择,但是看来好事多磨,在PDT 10:00 AM,也就是北京时间凌晨1点过去4个多小时后,仍然没法顺利下载到正式版。

来自CNET的跟踪报道:
http://news.cnet.com/8301-10784_3-9970628-7.html

[更新|2008-06-18 06:15:00]
决定DIY一下,不等官网刷新了:
http://download.mozilla.org/?product=firefox-3.0&os=linux&lang=en-US
注意后面的参数,根据需要,os可以选择linux/osx/win,lang可以选择en-US/zh-CN等等。


posted @ 2008-06-18 05:30 laogao 阅读(776) | 评论 (1)编辑 收藏


或许多少和Python/Django这个社区的人们比较内敛、慢条斯理、喜欢埋头做事有关,Django一直以来版本号更新都很保守,到现在还是0.96。什么时候才有1.0这个问题被人提起无数次,这让很多对它有兴趣的朋友处于长期的观望之中。眼睁睁看着隔壁Rails如火如荼的都出到了2.1.0,Django终于要有动作了:

http://code.djangoproject.com/wiki/VersionOneRoadmap

根据这份线路图,今年7月,Django会推出1.0的第一个alpha版本,接下来在8月会有两次beta和一次rc,如果一切顺利的话,让许多人望眼欲穿的Django 1.0将有望于今年9月正式同大家见面。


posted @ 2008-06-17 18:14 laogao 阅读(708) | 评论 (0)编辑 收藏


JVM下的Ruby语言实现JRuby发布1.1版的第二个升级版1.1.2,这个版本最主要关注的仍然是性能,值得一提的包括:
1- 启动时间大大缩短。
2- YAML标记解析速度提高100x以上。
3- 方法调用在性能、线程和栈深度等方面的增强。
4- 其他bug。

主页: http://jruby.codehaus.org/
下载: http://dist.codehaus.org/jruby/


posted @ 2008-05-28 12:08 laogao 阅读(1499) | 评论 (1)编辑 收藏


最近在家休息,想来Ubuntu新的LTS版本8.04已经出来一周多了,试试看吧,正好想给家里的服务器来一次升级,未曾想这一试让我彻底和Ubuntu说了bye bye。

我的主打机器是一台T43,在3月下旬,这台ThinkPad就彻底从Ubuntu变脸成了Arch Linux,运行至今,十分稳定,要速度有速度,要功能有功能,简单而强大,让人爱不释手。我家里有一台"老"机器,AMD Athlon 2500+ / 512M,先后装过SuSE、Fedora、CentOS、Debian、Ubuntu 7.10,由于很长一段时间以来都比较忙,没时间去折腾,在最后这次开刀之前,定格在了Gusty Gibbon。

说回这次开刀。趁休假有时间,我打算再整理/升级一下这台服务器,正好Ubuntu 8.04 LTS出来,冲着省事(平时难有时间去折腾)和LTS,我想这应该还是比较自然的一个选择。安装过程很顺利,该找到的硬件都找到,一切都还像是Ubuntu在7.10基础上正常的一次升级版,谁知刚配置完几个我常用的应用程序/服务,就遇到了严重的问题:系统会随机(通常几分钟时间)锁住,没有反应,键盘灯和鼠标灯还有反应,但是屏幕定格,Ctrl-Alt-Backspace或者Ctrl-Alt-F1等等,都不管用了,什么提示都没有。硬件问题?不像啊,之前的Gusty跑得很好。网上一搜,好家伙,还是普遍现象:

http://ubuntuforums.org/showthread.php?t=768200

没想到拿LTS的正式ISO安装,还是无奈的做了一次小白鼠,对Ubuntu印象因此大打折扣。算了吧,装回熟悉的Debian,一切又恢复安静。从今天起,我的Linux推荐榜调整为:公司服务器 - CentOS、个人服务器 - Debian、个人桌面 - Arch Linux。

So long, Ubuntu!


posted @ 2008-05-02 17:35 laogao 阅读(785) | 评论 (3)编辑 收藏


JVM下的Ruby语言实现JRuby正式发布1.1版,这个版本最主要关注的是性能,除此之外,值得一提的包括:
1- 支持将Ruby代码编译成Java Bytecode。
2- 将Oniguruma这个Ruby 1.9标配的正则库移植到Java。
3- 重构过的IO实现。
4- 更低的内存消耗。
5- 修复大量其他兼容性问题。

主页: http://jruby.codehaus.org/
下载: http://dist.codehaus.org/jruby/


posted @ 2008-04-05 23:01 laogao 阅读(1387) | 评论 (0)编辑 收藏


一篇关于目前开发中的KDE 4.1最新进展介绍
http://polishlinux.org/kde/kde-41-visual-changelog-rev-783000/

看上去挺不错的,有了KDE 4的基础,从4.1开始,一些之前来不及polish的地方开始逐渐被弥补。


posted @ 2008-03-12 00:27 laogao 阅读(657) | 评论 (0)编辑 收藏


最近尝试把一个Oracle数据库,连同构建在这个数据库上的Java应用移植到PostgreSQL环境。在移植过程中,总结了一些要点,一方面作为笔记备忘,一方面也给有类似任务需要处理而又无从下手的朋友作为参考。

1- 首先是准备PostgreSQL环境。有条件的话,最好是找一台空闲的PC机作为测试服务器,安装Linux或BSD,然后从源码编译最新的PostgreSQL 8.3.0。编译时,通过configure指定--with-perl和--with-python以支持PL/Perl和PL/Python。因为绝大多数Linux发行版都已自带Perl和Python,不必额外安装。

2- 如果是Windows环境,又需要Perl和Python,则必须额外安装,Python的话,可以方便的找到2.5 for Windows的安装包,Perl的话,推荐ActivePerl,相对麻烦一点,为了后面用到的一些便利的功能顺利加载,Perl版本尽量选5.8.8。

3- 创建数据库和用户。通过initdb初始化数据目录,配置postgresql.conf指定主机IP、端口等等信息,配置pg_hba.conf指定访问权限,通过pg_ctl -D <数据目录> -l <日志文件> start启动postmaster,然后createdb、createuser创建数据库和用户。数据库建好之后,就可以createlang -d <数据库名> [plperl|plperlu|plpython|plpythonu]开启PL/Perl和PL/Python。具体命令行参数可通过各命令加--help查看。

4- 安装PostgreSQL客户端pgAdminIII,最新版是1.8.2,有条件的话,也可以下载源码自己编译。

5- 安装Oracle客户端,需要在PostgreSQL同一台机器,以便Perl用于连接数据库的DBI和Oracle驱动DBD::Oracle模块顺利安装。如果是Windows上的ActivePerl,则可以通过ppm install DBD-Oracle,如果是Linux/BSD,则可以通过CPAN来安装,如perl -MCPAN -e shell进入CPAN Shell,通过install <模块名>或force install <模块名>安装DBI和DBD::Oracle。

6- 数据库的移植,可以选择ora2pg来帮忙,目前的版本是4.7。ora2pg是一个用于读取Oracle数据库schema、数据,并生成PostgreSQL脚本或直接导入PostgreSQL数据库的Perl工具。用法很简单,就是通过.conf文件指定数据库连接信息包括NLS_LANG、需要导出导入的schema、table、view、data等等,然后执行一个pl脚本。这是目前相对比较成熟的一个方案,但是遇到schema复杂、约束较强的数据库,需要手工处理的地方还是不少。建议不要直接写入PostgreSQL,而是生成SQL脚本,验证无误后再执行。ora2pg默认会把Oracle中名称的大写转换成小写,因为PostgreSQL在解析SQL时,除非""括起来,默认都是转成小写。schema、table、view、sequence、data等等,基本用ora2pg,加上一些手工调整即可搞定。至于function、stored procedure等,还是手工移吧,偷不得懒。除了ora2pg,其实也可以配置DBI-Link,将Oracle数据库挂到PostgreSQL数据库作为一组独立的"schema",然后用create table xxx as select ... from ...这样的语法来倒表和数据。PostgreSQL的contrib包也附带有一个dblink,不过是连接其他PostgreSQL数据库的,如果需要连接非PostgreSQL, 还是考虑DBI-Link,任何可以通过Perl的DBI接口访问的数据库,都能link进PostgreSQL。

7- 接下来就是Java应用本身了,我这次移的这个应用是Spring+iBatis架构的,很多SQL语句都是明文,好在DAO层的基础部分(CRUD)的SQLMap是工具自动生成,且都是符合ANSI SQL92标准的,不需要修改即可使用。其余的高级查询SQL,需要调整的地方不少,一些常见的修改列举如下:

i. SELECT出来的column(包括子查询),如果有别名,必须加AS,比如 select null as some_column from some_table;
ii. PostgreSQL没有dual表,类似select 0 from dual的语句,写成select 0即可;
iii. DECODE函数需要重构成(case when some_column = 'some_value' then 'some_other_value' when ... then ... else 'some_default_value' end ) as some_column;
iv. NVL()函数,PostgreSQL中相对应的是coalesce(),其实几乎所有主流DBMS都支持coalesce,包括Oracle,这才是标准写法;
v. 比较日期,在PostgreSQL中,建议使用date_trunc('day', SOME_DATE) = date_trunc('day', #enteredDate#)这样的写法,其中'day'位置可选字段包括有year、month、week、hour、minute、second等等;
vi. SYSDATE,对应到PostgreSQL是current_timestamp,可以根据需要使用current_date;
vii. ROWNUM,通常我们用ROWNUM都是为了限制查询出来的记录数,PostgreSQL没有这个关键字,需要改成在SELECT语句最后添加 LIMIT语句,如LIMIT 100;
viii. (+)这样的外连接写法需要调整为SQL标准的 table1 [LEFT|RIGHT|FULL] OUTER JOIN table2 ON (...);
ix. CONNECT BY ... START WITH ... 递归查询可以参考 http: //www.postgresql.org/docs/8.3/static/tablefunc.html 的connectby()函数.

最后再多提一点,PostgreSQL自带的过程语言是PL/pgSQL,在PostgreSQL上写function,除了用plpqsql,还支持sql、plperl(u)、plpython(u)等等。如果你对SQL天生过敏,看类似PL/pgSQL的代码都很吃力,别说是写了,你完全可以用你喜欢的语言来表达函数和存储过程的逻辑。有了PL/Python,你还怕什么呢?你几乎能做任何事。

[更新 20080313] 把JDBC驱动的部分漏掉了,移植Java应用时,除了改SQL,还需要拿PostgreSQL的JDBC驱动放到classpath下面,如WEB-INF/lib,然后修改数据库连接URL,改成jdbc:postgresql://<ip>:<port>/<dbname>即可。

[更新 20080323] 移植schema和数据时,比ora2pg更方便的一种方式是利用EnterpriseDB的Migration Tool,将Oracle的JDBC驱动ojdbc14.jar拷贝到EnterpriseDB安装路径下的jre/lib/ext下后,启动Developer Studio即可建立Oracle连接,选中schema后,可以通过右键Online Migration将schema、数据、函数包等等一次性通通导入EnterpriseDB。如果要继续往"纯"PostgreSQL移,从EDB做backup,然后到PostgreSQL下做restore,这样会丢掉函数包,因为毕竟EDB在PostgreSQL基础上做了相当改造以和Oracle兼容,不过函数包之类还是手工移比较稳妥。


posted @ 2008-03-11 23:04 laogao 阅读(2789) | 评论 (0)编辑 收藏


啥也不说了,开心!


posted @ 2008-03-05 05:39 laogao 阅读(635) | 评论 (0)编辑 收藏


在JRuby得到Sun的认可并成功发布1.0,已经向1.1迈进之时,比Ruby应用更广、更早出现JVM运行版本的Python也终于得到了Sun的重视:

http://www.eweek.com/c/a/Application-Development/Sun-Hires-Python-Experts/

尽管Sun官方的说法是他们会更多的应用和扶持native版的Python,相信一直饱受冷落的Jython,也多少会从中受益吧。


posted @ 2008-03-05 00:07 laogao 阅读(458) | 评论 (0)编辑 收藏


就在2月的最后一天,Apache Harmony发布了5.0的第5个milestone: http://harmony.apache.org/

为默默耕耘的人鼓掌。


posted @ 2008-02-29 23:28 laogao 阅读(416) | 评论 (0)编辑 收藏


本赛季状态渐佳,外号"禁区之狐"的阿森纳小将Eduardo在英超客场对阵Birmingham City中惨遭暗害:

(由于实在太过血腥,不忍心放在首页,请点击查看)

在此强烈谴责Martin Taylor这次不负责任的野蛮铲球,只给你红牌实在太轻了。让我们共同为Eduardo祈祷,祝愿他早日康复!也希望绿茵场上不要再发生类似的惨剧。足球应该是给人带来快乐的,不是人身伤害。


posted @ 2008-02-24 13:22 laogao 阅读(635) | 评论 (0)编辑 收藏


Eduardo_0.jpg

Eduardo_1.jpg

Eduardo_2.jpg

Eduardo_3.jpg

Eduardo_4.jpg



posted @ 2008-02-24 13:16 laogao 阅读(316) | 评论 (0)编辑 收藏


春节期间真是好事不断啊,继PostgreSQL 8.3正式release后,Grails也如约发布1.0版。作为受到Ruby on Rails启发开动的"Groovy版Rails"项目,它在设计哲学上和Rails,包括JRuby版的Rails,有着很大的不同,Rails是从头开始用Ruby完整实现从表现层到ORM所有功能,而Grails则是利用Java社区现有的成熟开源框架,如Spring、Hibernate等,在此基础上整合出一套完整的Web应用框架,有点类似Pylons和Django的区别。

之前一篇随笔也提到过,和其它在JVM中运行的动态语言如Jython、JRuby不同的是,Groovy对于有Java基础的人们来说,学习曲线几乎是平的,上手很快,如果你同时也熟悉Spring和Hibernate等,那么Grails更是不二之选。

官网: http://grails.codehaus.org/
Release Notes: http://grails.org/1.0+Release+Notes
下载: http://grails.codehaus.org/Download


posted @ 2008-02-07 10:47 laogao 阅读(722) | 评论 (1)编辑 收藏


经过1月3日和1月18日两轮RC后,PostgreSQL 8.3终于在本月初正式发布了。该版本有很多功能和性能上的重大提升,包括全文搜索、新的数据类型(XML、ENUM、UUID等)、并发autovacuum、异步提交等等,以及对Windows平台更好的支持,如SSPI和VC++等。

官方声明: http://www.postgresql.org/about/news.918
Release Notes: http://www.postgresql.org/docs/8.3/static/release-8-3.html
各版本功能对照: http://www.postgresql.org/about/featurematrix
下载: http://www.postgresql.org/ftp/


posted @ 2008-02-07 10:04 laogao 阅读(766) | 评论 (0)编辑 收藏


如果你有一定的Java基础,想快速的尝尝动态语言的味道,Groovy是个自然的过渡选择。今天无意中看到一篇介绍Groovy的文章,很短,也很有趣,从一个典型的Java程序开始,一步一步"Groovy化",最终改造成一个完整的Groovy程序:

http://java.dzone.com/news/java-groovy-few-easy-steps


如果你对当下动态语言的现状有所了解,那你多半已经知道能在JVM中运行的动态语言,远不止Groovy一种,那么什么理由会让你选择Groovy而非Jython、JRuby或者其他类似的语言呢?笔者认为主要还是编码习惯和风格,Groovy是这些语言中最接近Java的。Jython和JRuby都是从其他成功的动态语言"移植"过来,带有明显的Python、Ruby语法特征和习惯。选择Jython或者JRuby的朋友,我想大都是原本就有Python或者Ruby的基础,舍不得Python和Ruby的一些很方便的语法和编码风格/习惯/哲学,或者干脆就是为了将Python和Ruby世界的一些框架引入到Java中,或者说是让Python/Ruby应用能够更好的利用Java平台已有的资源。如果你在动态语言上没有这方面的需求,只是为了让你的Java应用更动态,选择Jython或者JRuby只能是凭空增加学习难度。要知道,Python和Ruby都是很有特点、很有个性的语言(其实Java又何尝不是),要从Java的思维和哲学,转向Python/Ruby的思维和哲学,并不是那么容易做到和做好的。


posted @ 2008-01-27 17:14 laogao 阅读(1291) | 评论 (2)编辑 收藏


使用Linux很便利的一个地方,就是它把所有资源都按照文件的方式抽象出来,于是我们在读写任何外部资源时,都像是操作本地普通文件一样。访问Windows共享,除了在Nautilus/Konquerer使用smb://,或者命令行使用smbclient之外,当然还有更cool的方式,那就是smbmount。

在Ubuntu下使用smbmount,需要安装smbfs包,通过sudo apt-get install smbfs即可。调用方法如下,新建/share目录后:
$ [sudo] smbmount //10.10.10.10/share /share -o username=<user_name>,password=<password>,codepage=cp936,iocharset=ut8

注意最后两个参数,Linux默认是UTF-8编码,中文Windows则是GBK,按codepage划分,也就是cp936。如果你的环境和上述不一致,则需要相应的修改codepage和iocharset参数。成功以后,我们就可以通过熟悉的ls, cp, cat, less, more, mv, zip, tar, rm, rename, nano, vi等等我们在Linux下已经习以为常的方式来操作了,就和本地文件夹一样。

如果想在Linux启动时自动把Windows共享挂进来,则可以修改/etc/fstab,增加如下内容:
//10.10.10.10/share /share smbfs username=<user_name>,password=<password>,codepage=cp936,iocharset=ut8,umask=000 0 0


posted @ 2008-01-18 12:54 laogao 阅读(1696) | 评论 (0)编辑 收藏


不知不觉中,从我在BlogJava第一篇随笔至今,BlogJava已经伴随我走过了三个年头。不由得感慨:时间过得真快。

前不久刚看完Coen兄弟的新片 No Country for Old Men (豆瓣),挺打动我的。我们每天都在变老,世界也似乎注定会有一天变成我们不认识、也无力改变的样子,没有原因,没有目的。从混沌中来,还得回到混沌中去。


posted @ 2008-01-13 16:58 laogao 阅读(422) | 评论 (1)编辑 收藏


http://it.slashdot.org/article.pl?sid=08/01/01/137257
(来自Slashdot社区的文章链接)

M$ Office 2003 SP3将取消对一部分老Office文件格式的支持,官方的说法是这些文件格式不够安全。本来就是二进制格式的文件了,隔几年你就搞个新的不兼容的格式,这是要存用户的数据还是你的数据啊?逼(诱?)大家升级?

我本人不用M$ Office,但我周围许多人在用,而且大都很热衷于尝试新的版本。我想问问还在继续使用M$ Office的朋友,如果10年后,你今天写下的文档,再无法用市面上找的到的工具打开,你还会继续放心的使用今天这个工具吗?

如果工具有bug、不安全,那你就做个没bug、安全的工具,别老拿文件格式当幌子,这不是祸祸人么?


另一篇挺有趣的文章:
Why I hate Microsoft


posted @ 2008-01-02 21:33 laogao 阅读(493) | 评论 (3)编辑 收藏


"Gloomy Sunday"原本是一首钢琴曲的名字,"忧郁的星期天",据说N多人听过之后选择了在这首曲子的陪伴下结束自己的生命。而今天要向大家推荐的,是一部由匈牙利、法国和德国联合拍摄的电影: 《Gloomy Sunday - Ein Lied von Liebe und Tod (忧郁星期天 - 爱与死之歌)》。故事有关爱情、自由、尊严,讲述的是二战大背景下发生在布达佩斯的一段凄美的故事,情节饱满、张驰有度,是一部近年来难得一见的佳作。



影片一开始,映入大家眼帘的,是美丽的布达佩斯和流经这里的多瑙河:镜头从Budavári palota(城堡山)、Erzsébet híd(伊丽莎白桥)一直拍到Gellért hegy(盖雷尔特山)脚下的Szabadság híd(自由桥),德国大使馆的车队正从这里经过。Szabó餐厅内的人们正在紧张的准备晚宴,今天他们的客人,是半个世纪以前,在布达佩斯从纳粹手下"解救"了上千名匈牙利犹太人的前德国军官Hans Wieck,今天是他80岁生日,带着他的妻子故地重游,重温当年的记忆。晚餐开始,插着80岁标签的肉卷上桌,Hans招呼一旁的小提琴手,让他表演那首名曲,也就是"Gloomy Sunday",一桌人一边用餐一边欣赏着动听的音乐。这时Hans的目光集中到了摆放在钢琴上的一张黑白照片,照片上是一位端庄美丽的女人,似乎想起了什么,突然表情僵硬,倒在地板上猝死,故事由此展开。


posted @ 2007-12-30 17:36 laogao 阅读(466) | 评论 (0)编辑 收藏


前段时间工作比较忙,想来Gusty Gibbon也已经出来2个月了,还没来得及好好把玩,这周终于有点时间和精力把它下载下来安装到本本上。

这个版本用下来最直接的感受有两点:
1- 默认的中文字体支持更好了,一方面字体的处理更加协调一致,不像之前默认时经常中文字符一大一小的,默认采用英文字体时对中文的显示也做的不错。
2- Compiz和Beryl复和之后,成了Ubuntu新的标配,省得大家费力折腾从其他的apt源或者源码安装了。

当然了,其他细微的改进还有很多,比如Pidgin、默认的ntfs-3g、keyring的处理、闭源的驱动和codecs等等。总的来说,Gusty Gibbon在Feisty Fawn基础上,更加成熟,也让我们对明年4月的Hardy Heron这个在6.06之后第二个LTS版本有了更多的期待。

这里有一个截图,很多东东还没有装,基本上也没花太多时间去hack,感觉就已经挺漂亮,也挺好用的了,呵呵:
screenshot_20071222.png

BTW,AWN(Avant Window Navigator)已经确认会包含在明年8.04(Hardy Heron)默认的apt源中,这对AWN fans们,以及所有喜欢"eye candy"但又不愿花时间去折腾的朋友们来说,无疑是个好消息。


posted @ 2007-12-22 23:57 laogao 阅读(491) | 评论 (0)编辑 收藏


算到现在,已经有将近半年没有写过技术文章了,手痒痒,于是拿Django来说事,希望最终的产出能够做成一个简短易懂的Django快速起步,让初次接触Django的朋友能够在最短的时间内了解Django的基本概念和结构。

Django是使用Python实现的一个基于MVC的web应用框架,类似Ruby世界的Ruby on Rails。如果你是通过Google搜到这篇文章,那么说明你已经对Django有所耳闻,并且愿意了解更多Django相关的信息。我在这里就不多废 话Ruby vs Python或者Rails vs Django,直奔主题。

在写这篇文章时,最新的CPython版本为2.5.1,Django版本为0.96,如无特别说明,本文所有介绍和示例均以此环境为准。

0- 在开始之前,首先当然是安装一个基本能用的开发环境。

如果你的操作系统是Linux或者其他类Unix系统,很可能已经预装了Python,可以在命令行执行python -V查看Python版本。如果你是Windows操作系统,或者想尝试不同版本的Python,那么可以到http://www.python.org/下载相应的安装包进行安装。

有了Python以后,到http://www.djangoproject.com/下载Django,解压以后,cd到解压出来的目录,执行python setup.py install。

为了能够做出一个基本的多层web应用,还需要安装一个数据库,如果没有特别喜好和偏向,推荐PostgreSQL,可以在http://www.postgresql.org/找到合适的版本下载和安装。

我们还缺少一个数据库驱动,在http://www.initd.org/pub/software/psycopg/可以找到用于连接PostgreSQL的psycopg2,安装方法类似Django。

1- django-admin.py startproject

所有环境OK以后,我们开始动手把玩Django,首先找一个干净的目录,执行
$ python django-admin.py startproject hello

上面这行命令会新建一个hello子目录,包含以下文件:
__init.py__: 表示该目录存放Python程序
manage.py: 提供Django项目相关的管理操作
settings.py: 相当于该Django项目的全局设置
urls.py: 用于配置URL映射,基本上就是通过正则表达式指定不同URL由相应的view方法相应

2- manage.py runserver

至此我们已经搭起了一个基本的Django项目框架,执行
$ python manage.py runserver
命令行会提示在8000端口运行一个开发用的web server,转到浏览器的http://localhost:8000/即可看到It worked!的提示信息。你也可以指定端口号,方法是python manage.py runserver XXXX。

3- settings.py

接下来我们做一个完整的从model/数据库到view/template的例子。修改settings.py:
DATABASE_ENGINE = 'postgresql_psycopg2'
DATABASE_NAME 
= 'hello' # Your db name
DATABASE_USER = 'postgres' # Your db user
DATABASE_PASSWORD = '********' # Your db password
DATABASE_HOST = ''
DATABASE_PORT 
= ''

INSTALLED_APPS 
= (
    
'django.contrib.auth',
    
'django.contrib.contenttypes',
    
'django.contrib.sessions',
    
'django.contrib.sites',
    
'hello'# Our new project

4- models.py

新建models.py:
from datetime import datetime
from django.db import models

class Book(models.Model):
    isbn        
= models.SlugField(maxlength=20)
    title       
= models.CharField(maxlength=200)
    author      
= models.CharField(maxlength=200)
    description 
= models.TextField(blank=True,null=True)
    published   
= models.DateTimeField(default=datetime.now)
这里我们从django.db.models.Model继承我们的model类Book,同时还用到了models中现成的字段类,如 SlugField、CharField、TextField、DateTimeField等。大家比较陌生的恐怕是SlugField,这个基本上类似 CharField,不过增加了其内容需要符合URL要求的限制条件。

执行下面的命令测试数据库脚本的生成:
$ python manage.py sql hello
应该看到如下输出结果:
BEGIN;
CREATE TABLE "hello_book" (
"id" serial NOT NULL PRIMARY KEY,
"isbn" varchar(20) NOT NULL,
"title" varchar(200) NOT NULL,
"author" varchar(200) NOT NULL,
"description" text NULL,
"published" timestamp with time zone NOT NULL
);
COMMIT;

确认无误后可以通过下面的命令提交到数据库:
$ python manage.py syncdb
其间会要求我们创建一个管理员账号,如果暂时不打算做admin页面,可以跳过。

5- views.py

model有了之后,接下来我们就可以开始画视图了。由于篇幅和时间有限,我仅简单介绍一下Django的template,然后实现一个最基本的图书清单页面。

首先定义图书清单的URL,在urls.py中:
from django.conf.urls.defaults import *

urlpatterns 
= patterns('hello.views',
    (r
'^hello/books/$''book_list'),
)
含义为hello/books/这个URI资源对应的相应view方法为hello.views.book_list。

新建templates目录,然后新建books.html:
<html  xmlns="http://www.w3.org/1999/xhtml" lang="zh-cn" xml:lang="zh-cn">
<head>
<title>{{ title|escape }}</title>
</head>
<body>
<h2>{{ title }}</h2>
<table border="1">
  
<tr><th>ISBN</th><th>书名</th><th>作者</th><th>出版日期</th></tr>
  {% for book in books %}
  
<tr>
    
<td>{{ book.isbn }}</td>
    
<td>{{ book.title }}</td>
    
<td>{{ book.author }}</td>
    
<td>{{ book.published }}</td>
  
</tr>
  {% endfor %}
</table>
</body>
</html>
Django模板的语法是{{}}表示引用,{%%}表示代码,使用起来也很直观,甚至支持UNIX风格的filter,如这里的{{ title|escape }}。

新建views.py:
from hello.models import *
from django.shortcuts import render_to_response

def book_list(request):
    title 
= 'Book List'
    books 
= Book.objects.all()
    
return render_to_response('books.html', {'title' : title, 'books' : books})
最终页面上的内容,通过title和books两个参数传递给tempate(books.html)处理。

修改settings.py:
TEMPLATE_DIRS = (
    
'/opt/PROJECTS/Django/hello/templates/',
)
指定templates目录位置,注意需要使用绝对路径和'/',无论是Unix还是Windows系统。

我们手工造一些数据之后,就可以通过http://localhost:8000/hello/books/访问我们用Django实现的这个简单页面了。

6- What's next

通过上面的简单介绍,相信哪怕是初次接触Django的朋友,也能够对Django有一个初步的认识。其实Django并不难学,并且随着学习的深入,你一定能发现更多的惊喜,不论是来自Django本身,还是Python及其庞大的第三方类库。

如果有时间,建议尝试一下Django的admin pages,即为我们的model提供自动化、网页化的增删改查操作。启用方法如下:

修改models.py (增加class Admin):
from datetime import datetime
from django.db import models

class Book(models.Model):
    isbn        
= models.SlugField(maxlength=20)
    title       
= models.CharField(maxlength=200)
    author      
= models.CharField(maxlength=200)
    description 
= models.TextField(blank=True,null=True)
    published   
= models.DateTimeField(default=datetime.now)
    
class Admin:
        
pass

修改settings.py和urls.py,加入admin支持:
[settings.py]
INSTALLED_APPS = (
    
'django.contrib.auth',
    
'django.contrib.contenttypes',
    
'django.contrib.sessions',
    
'django.contrib.sites',
    
'django.contrib.admin',
    
'hello',
)
[urls.py]
urlpatterns = patterns('hello.views',
    (r
'^hello/books/$''book_list'),
    (r
'^hello/admin/', include('django.contrib.admin.urls')),
)

Note:
# 为了成功运行admin pages,需要首先执行python manage.py syncdb admin以创建django_admin_log表。
# 如果前面跳过了创建管理员步骤,简单的方法可以删掉auth_user表,然后python manage.py syncdb重建。

按照我们urls.py的配置,admin pages可以通过http://localhost:8000/hello/admin/访问。Enjoy!


posted @ 2007-11-28 00:57 laogao 阅读(744) | 评论 (0)编辑 收藏


最近这段时间,Roger Federer这个名字,"出镜率"相当的高,尤其是在上海:先是地铁中铺天盖地的剃须产品广告(广告中出现的三位主角,恰好都是我喜欢和欣赏的),其次当然就是大师杯。

2007上海网球大师杯最后两天的比赛多少让人有些意想不到:费天王的粉丝们当然很开心,费天王虽然首场比赛失利,但后面的每场比赛都展现着他的独有风 范,赢得干净漂亮;相对中立的球迷们可能就要抱怨比赛不够精彩和跌宕起伏了,原本被寄予厚望的巅峰对决:Federer和Nadal,以及最后的决赛,都 呈现出"一边倒"的态势,纳豆和今年大师杯的黑马Ferrer这两位西班牙选手,面对天王的出色发挥,都显得有些"找不着北"。

是什么成就了费天王今天的辉煌?技术层面的东西我不想说太多,除去网球这项运动本身的技术细节,Federer身上的一些冠军特质,也是值得我们好好品味:

首先,热爱自己从事的工作。Federer对网球的热爱,只要你看过他的比赛,就不会质疑。
其次,尊重自己的工作/事业和对手。正是这种尊重,为费天王赢来所有人,包括手下败将在内的尊敬。
再次,对胜利的渴望。看Federer的比赛,尤其是大赛,你能够明显感觉到他对胜利的渴望,每个关键球都透露出一种狠劲。
再有,内敛和对自己情绪的控制。Federer刚出道时其实脾气很暴躁,发挥也不稳定,但是随着时间的推移,他身上逐渐成长出一种特有的内敛和自信。
最后,超乎寻常的稳定和跑位。为什么看Federer打球总觉得他是那么"轻松"而"优雅",而对手总是陷入被动?除了善于观察和控制对手之外,他总能保持超高的稳定性和预判,保证自己出球落点的同时,已经在为下一步回击做准备了,比赛起来,当然游刃有余。

Herzlichen Glückwunsch an Roger Federer!


posted @ 2007-11-18 23:38 laogao 阅读(374) | 评论 (0)编辑 收藏


V8来了,经不住诱惑,造型、做工、Linux核心......
十一来了,不想出门,因为到处是人......
Bug来了,操刀杀虫,一天不行两天,两天不行三天......
罗莎来了,这个没有"正面袭击"上海的家伙,却比"正面袭击"上海的韦帕来得更加生猛......
老妈来了,一起来的,还有蹄花,和家乡的味道......


posted @ 2007-10-08 21:51 laogao 阅读(378) | 评论 (0)编辑 收藏


过去的一段时间几乎没什么时间看RSS,周末在家打开Google Reader,发现Google Reader界面上的一个小小调整:

原先最多能显示出100+,当某项RSS或分类超过100条的时候,看不到具体的数值,只能看到"100+"的字样,经常是都已经浏览完了,左边还是显示 100+,必须Refresh一下才能纠正过来,加上我的胃口比较大,超过100的情况简直是家常便饭,一直对这个100+颇为不爽。现在这个上限提高到 了1000,能够直观的看到各个类别的具体未读条目数,一下子清晰了不少,至少对我来说这个改进很实用。

希望Google Reader能越做越好。


posted @ 2007-09-09 22:34 laogao 阅读(626) | 评论 (2)编辑 收藏


据外电报道,继Dell发布预装Ubuntu的PC和笔记本电脑之后,联想也宣布将于今年第四季度开始发售预装SuSE Linux Enterprise Desktop 10的ThinkPad笔记本电脑,硬件和操作系统均由联想向客户提供支持,操作系统升级则由Novell提供。值得注意的是,与Dell面向Linux 爱好者和个人用户不同,联想这次更多的是针对企业用户。

对于广大Linux爱好者来说,这可是个不错的消息哦。

详见:
http://www.reghardware.co.uk/2007/08/06/lenovo_linux/


posted @ 2007-08-07 21:09 laogao 阅读(652) | 评论 (1)编辑 收藏


详见:
http://www.worldofwarcraft.com/wrath/

回过头来看看魔兽世界中国大陆的代理商九城,到现在连第一部资料片The Burning Crusade还没有推出,唉。


posted @ 2007-08-04 10:37 laogao 阅读(526) | 评论 (0)编辑 收藏


巴萨与邓迪联的热身赛精彩回放:

http://www.youtube.com/watch?v=8Ljp2kwJv0g

亨利点球绝杀:

http://www.youtube.com/watch?v=P5gPeNdYYwc


posted @ 2007-07-28 13:19 laogao 阅读(491) | 评论 (0)编辑 收藏


来自PC World的报道:
http://www.pcworld.com/article/id,134381-c,databases/article.html


posted @ 2007-07-14 12:31 laogao 阅读(633) | 评论 (0)编辑 收藏


http://www.thesun.co.uk/article/0,,2002390000-2007281078,00.html

No more *free* EPL in mainland China + Henry leaves Arsenal for Barcelona, coincidence?

This seems to be another reason for me to embrace La Liga and FC Barcelona. All my best wishes for Henry to start a new legend at Camp Nou.


posted @ 2007-06-24 22:18 laogao 阅读(442) | 评论 (0)编辑 收藏


随着项目越来越大,你的ANT脚本变得越来越臃肿,越来越依赖antcontrib来实现构建逻辑?不想放弃对构建过程和产出做精细的控制?恨不得自己写ANT Task?

等一等,在你考虑转向Maven或者真正卷起袖子开始研究ANT Task的API之前,先听我向你推荐Ruby/JRuby。相信我,也许这才是你真正需要的。

在我看来构建脚本最主要的要求是表达能力和控制能力,表达能力是我们应该能够很方便的告诉它我们要它做什么,而控制能力是我们告诉它如何去做,除了必要的 构建命令的参数、依赖关系之外,它应该能够理解我们其他一些特殊要求。在项目相对简单时,ANT的XML格式的"脚本语言"能够比较好的表达构建者的要 求,至少比纯Java的方式更加简单清晰,于是几乎从它诞生之日就成为Java领域当仁不让的头号构建工具。但是ANT也有它不够用的时候,尤其在控制能 力上,为了实现实际使用中越来越复杂越来越精细的对构建过程和产出的要求,ANT的使用者们开始对ANT进行扩展,最具影响力的"非官方"扩展可能就是 antcontrib了,很多实际Java项目的构建文件中我们都能够找到它的影子。但是一堆taskdef和之类的夹杂在ANT脚本里,怎么看怎么觉得别扭,也严重影响构建脚本的可读性。

我发现我需要的是一个具有完整功能脚本语言来写我的构建逻辑:一方面它要足够简单,我需要清晰的表达我的意图,另一方面当我需要的时候它要足够强大来帮我实现精细的控制。我自然而然想到Ruby。

由于Ruby是一个功能完整的工具,完全自己写Ruby脚本来调用Java自己的构建工具如javac、jar等等并非不可能,但是既然已经有人做了轮 子,我们拿来用就是了,大不了自己再改装一下,也少走些弯路。时下比较流行的解决方案有Buildr、Raven、Rant和Antwrap,它们各有特 点,大家可以根据需要进行选择。

我最终选了其中最"轻量"的Antwrap,原因嘛,我不想学新的API,我已经熟悉ANT常用的Task,而且我希望尽可能多的自己控制构建的过程和产 出。Antwrap最能够满足我的需要。而前不久JRuby刚刚发布了1.0版,这样一来Ruby和Java的跨界引用变得更加容易,Ruby的实现自然 就选择了JRuby。

安装JRuby和Antwrap相当容易,只要把下载的jruby-bin-1.0.tar.gz/.zip解压到本地,确保JAVA_HOME和 CLASSPATH的配置,然后gem install Antwrap (选择Java版) 即可。为了顺利加载Antwrap,需要在CLASSPATH中包含ANT的ant.jar和ant-launcher.jar。(当然,如果想更加方便 的share你的成果,可以把ant的文件拷贝到jruby目录下,在jruby的启动脚本加入必要的export/set命令,然后打包,这样别人只要 从你提供的zip包解压出来即可使用。)

为了给大家一个直观的感觉,举个简单的例子(貌似BlogJava没有提供对Ruby代码的默认支持,大家将就看吧):
 1 require 'rubygems'
 2 gem 'Antwrap'
 3 require 'antwrap'
 4 
 5 @ant=AntProject.new(:name=>"SampleAntwrapBuild", :basedir=>".")
 6 @cvsroot=":pserver:cvsuser:password@10.10.10.1/cvsrepo/SampleProduct"
 7 
 8 def cvscheckout
 9     @ant.cvs(
10         :cvsroot=>"#{@cvsroot}"
11         :command=>"checkout -A"
12         :package=>"."
13         :dest=>"cvsoriginal"
14         :compressionlevel=>"9")
15 end
16 
17 def cvsupdate
18     @ant.cvs(
19         :cvsroot=>"#{@cvsroot}"
20         :command=>"update -A -d"
21         :package=>"."
22         :dest=>"cvsoriginal"
23         :compressionlevel=>"9")
24 end
25 
26 def compile(project_name)
27     @ant.javac(
28         :srcdir=>"cvsoriginal/#{project_name}/src"
29         :destdir=>"cvsoriginal/#{project_name}"
30         :target=>"1.5"
31         :encoding=>"GBK")
32     @ant.copy(    :todir=>"cvsoriginal/#{project_name}"do
33         fileset(:dir=>"cvsoriginal/#{project_name}/src"do
34             exclude(:name=>"**/*.java")
35         end
36     end
37     @ant.jar(
38         :destfile=>"build/#{project_name}.jar"
39         :basedir=>"cvsoriginal/#{project_name}"
40         :manifest=>"MANIFEST.MF"do
41         exclude(:name=>"src/**")
42     end
43 end
44 
45 # to actually call your target
46 if ARGV.empty?
47     puts "Usage: jruby #{$0} [target]"
48 else
49     eval ARGV[0]
50 end
51 

可以看到几乎都是我们熟悉的ANT Task,只是更加紧凑更加灵活,一旦掌握了最最基本的Ruby语法,用它写出功能强大的构建脚本可以说是分分钟搞定。


posted @ 2007-06-18 00:39 laogao 阅读(672) | 评论 (0)编辑 收藏


如果你在Windows和Linux两个平台下都使用过Eclipse,那么你一定注意到Windows下Eclipse项目列表的显示要比Linux下 紧凑许多。对于做开发的朋友来讲,在屏幕上同时看到的信息总是希望尽可能多,尽可能全,在这一点上目前的GNOME并不能让我们十分满意,它的GTK+控 件本身和控件之间的间隙占掉了不少本来就很有限的屏幕空间,尤其当屏幕分辨率不是特别高的时候。

Linux版的Eclipse默认使用GTK+2.0的控件,所以在默认的情况下,会和其他GTK应用程序(如OpenOffice.org)一样给人一 种不够密实的感觉。当然,这和GNOME的设计哲学不无关系,不过这不是本文主旨,就不深入讨论了,进入正题讲讲如何调整Eclipse树状列表的显示密 度。

基于GTK+2.0的程序在启动时会到用户的home目录找GTK+2.0的配置文件,即~/.gtkrc-2.0,Ubuntu下默认没有这个文件,需要我们自己创建。打开你习惯的编辑器,加入如下代码:

style "eclipse" {
  font_name="Sans 8"
  GtkTreeView::vertical-separator=0
  GtkTreeView::horizontal-separator=0
}
class "GtkTreeView" style "eclipse"

重启Eclipse应该就能看到效果了。如果你想做得更彻底,对所有常用的GTK+2.0控件都开刀的话,可以这样写:

style "gtkcompact" {
  font_name="Sans 8"
  GtkButton::default_border={0,0,0,0}
  GtkButton::default_outside_border={0,0,0,0}
  GtkButtonBox::child_min_width=0
  GtkButtonBox::child_min_heigth=0
  GtkButtonBox::child_internal_pad_x=0
  GtkButtonBox::child_internal_pad_y=0
  GtkMenu::vertical-padding=1
  GtkMenuBar::internal_padding=0
  GtkMenuItem::horizontal_padding=4
  GtkOptionMenu::indicator_size=0
  GtkOptionMenu::indicator_spacing=0
  GtkPaned::handle_size=4
  GtkRange::trough_border=0
  GtkRange::stepper_spacing=0
  GtkScale::value_spacing=0
  GtkScrolledWindow::scrollbar_spacing=0
  GtkExpander::expander_size=10
  GtkExpander::expander_spacing=0
  GtkTreeView::vertical-separator=0
  GtkTreeView::horizontal-separator=0
  GtkTreeView::expander-size=8
  GtkTreeView::fixed-height-mode=TRUE
  GtkWidget::focus_padding=0
}
class "GtkWidget" style "gtkcompact"


posted @ 2007-06-09 22:46 laogao 阅读(1387) | 评论 (1)编辑 收藏


Linux下面使用Oracle的SQL*Plus工具有个挺恼人的问题:通过sqlplus命令进入到SQL*Plus控制台后,我们在Bash中已经 习以为常的上下左右键突然变成了^[[A^[[B^[[D^[[C这样的"乱码"。熟悉ksh的朋友肯定要说我们这是大惊小怪了,不过对于从 Windows平台转过来的一般用户而言,不小心按错一下就是4个错误的字符,而且历史命令也无法方便的回查了,确实挺郁闷的。

别着急,如果你的Linux是Debian或者Ubuntu/Kubuntu,直接sudo apt-get install rlwrap安装这个小巧的readline扩展,然后就可以以rlwrap sqlplus的方式进入方向键"正常"的SQL*Plus了。当然,如果嫌每次敲rlwrap不爽,可以在/etc/profile或者自己的 ~/.bashrc里面添加alias sqlplus='rlwrap sqlplus'。其他发行版的朋友可以选择rpm包或者干脆从源码自己编译。

posted @ 2007-06-07 22:13 laogao 阅读(936) | 评论 (0)编辑 收藏


不知道大家注意到没有,Ubuntu Feisty自带的nm-applet有一个小毛病:一旦你通过它连上某个无线网络之后,不管你是不是点错了,或者说是不是真的需要保留这个连接的信息,它都会记录下这个网络ID,今后如果检测到这个网络,根据它自己排的优先级(最后一次成功连接,但有时候不准,或者说有可能在来回切换时不小心被弄乱),如果它排在前面,就会自动连上去,就算你手动选择另一个,它还是不依不饶的切回它认定的那一个。

遇到这个情况,我想许多朋友大概和我一样,在它提供的上下文菜单找,不过GNOME的界面哲学使得界面菜单直接提供的信息和高级功能很有限,或者到类似 /etc/*、~/.*/之类的地方找相关配置文件,但是实际上它也不是那么"传统",因为nm-applet使用GConf来记录配置信息:

在命令行输入gconf-editor,打开GConf编辑器,定位到system -> networking -> wireless -> networks,这个目录下记录了所有nm-applet使用的无线网络ID和相关配置信息,如果有不希望保留的配置,直接进到相关目录,右键逐个点击右面的key-value条目,Unset Key,完成以后就可以让nm-applet"忘掉"这个无线网络连接。当然,通过这个小工具,你也可以手工对某组具体的key-value做修改。

这件事也让我联想起Linus Torvalds不止一次(也包括不少KDE的死忠)对GNOME的微词:尽可能让用户自己掌控,还是尽可能帮用户拿主意?这是个问题。


posted @ 2007-05-13 23:34 laogao 阅读(3156) | 评论 (2)编辑 收藏


时下类似小i这样的IM机器人越来越多,今天又发现一个有趣的Dictman,也挺实用:



使用方法是在MSN中添加dictman@hotmail.com,用Gtalk的朋友可以加dictman@gmail.com,成功后直接输入要查的单词即可,支持英汉或汉英。


posted @ 2007-05-07 17:31 laogao 阅读(686) | 评论 (2)编辑 收藏


http://www.eweek.com/article2/0,1759,2124025,00.asp

相信大家都听说了Dell将在部分产品型号的PC和Laptop中预装Linux操作系统而非Windows,据eWeek的报道,该Linux操作系统将会是Ubuntu。


posted @ 2007-05-01 17:19 laogao 阅读(493) | 评论 (0)编辑 收藏


上个周末的时候安装了最新的Ubuntu Feisty Fawn,给用了很久的Dapper来了一次彻底升级。第一印象是眼前一亮,打开默认自带的Compiz,对用惯了传统桌面系统的用户而言,毫不夸张的说,是全新的桌面体验。

花了个把小时样子简单调整了更新源、中文输入法、字体、区域选项等等,还上了比Compiz更强的Beryl,开始全面试用。经过一周的使用,包括工作和其他应用,感觉确实比6.06进步不少,尤其在桌面方面,比较明显的改善有:

1- 默认就支持Compiz,同时安装Beryl也非常容易。
2- Shell中敲命令,如果出现尚未安装的常见软件包,会提示安装信息。
3- Gaim默认增加了QQ支持。
4- 新的NetworkManager Applet 0.6.4使得无线连接管理变得简单、直观、而且相当方便。
5- OpenOffice.org更加完善,对中文支持更加友好,尤其是在中文字体宽度计算上的问题得到了解决。

总的来说,已经足够胜任日常工作的需要,而且十分简单易用。当然了,有些遗憾的是默认的邮件客户端Evolution并不能让人满意:

我原本一直使用Thunderbird,这次想给Evolution一次机会表现一下,它却不那么争气。本以为Novell和MS的东西集成应该不错,但是除了对日历、会议邀请的支持还算是亮点之外,并没有发现什么过人之处,而对TNEF的支持就有点贻笑大方了,Thunderbird都能正确处理的Winmail.dat附件,在Evolution下基本就是一个字:挂,连另存然后外部tnef处理都无法搞定,因为出来的东西已经不是tnef格式,搞不懂Evolution为什么要做这一层额外的处理。

于是准备切回Thunderbird,更令人感到困惑的事情出现了:在Evolution下辛辛苦苦录入的联系人信息,居然无法导出一个简简单单的CSV,而只能是vCard。界面上没有其他选项,命令行倒是有一个导出工具可以指定--format=csv,不过很不幸,上来就是core dump,晕倒。本来简简单单的东西,何必复杂化。还好vCard本身还是文本,处理一下也不难,但感觉怪怪的,心中难免不爽,对Evolution和Novell的印象大打折扣。

顺便表扬一下SWT/Eclipse,在Ubuntu Feisty下跑起来真的是无缝,界面风格完全就是一个native的应用程序,开启Beryl效果之后,连Tooltip都跟着"炫"了起来,让人越看越喜欢,Evolution带来的不愉快也就自然而然抛在脑后了。

今天,你Feisty了吗?


posted @ 2007-04-27 22:25 laogao 阅读(2881) | 评论 (15)编辑 收藏


读到一篇廷有意思的文章,来自Weiqi Gao:
http://www.weiqigao.com/blog/2007/04/12/java_the_third_fork_from_sun.html

近几年Sun的日子似乎并不好过:和微软先是不欢散后来虽然和解但貌合神离,微软不买Sun的账,干脆自己搞个.NET;对IBM更是气不打一处来,但是不管怎么说SWT/Eclipse这朵花确实开得太艳,甚至盖过了Sun的光芒;现在Sun又和Apache铆上了

这三次不和,背后的原因几乎都是Sun不愿意大胆革新Java,或者放弃对Java的控制权(Sun的JDK开源并不能改变Sun对Java的实际控制)。


posted @ 2007-04-14 15:20 laogao 阅读(600) | 评论 (0)编辑 收藏


昨天(周五)大家下班后,一个人留在公司,把核心产品开发团队使用了整整1年的CVS资源库从CVSNT移到了Linux平台下,原本以为会很简单很顺利,因为之前类似的移植并不是没有做过,所以预估的时间包括验证在内是1~2个小时,不过最终却花掉4个小时。怎么回事呢?且听我慢慢道来。

经过1年的积累,资源库有400多M,大大小小的Java项目有206个之多。按照最初的计划,移植只需要原封不动的把资源库目录整个从CVSNT服务器拷贝到Linux服务器即可,所以资源库大小和项目多少本来不是啥大问题,但谁料半路却杀出个程咬金:.jar文件在新的资源库checkout到本地后无法正常使用,这还了得?

仔细一看,乖乖,原本"Binary"的文件,在新的资源库下,却变成了"ASCII -kkv",不仅是.jar,其他的二进制文件如.jpg, .exe之类的也是同样的问题。第一反应是CVSNT和Unix经典的CVS在处理RCS文件时还是有些不同,以至于原本在CVSNT下文件类别的标记信息如"Binary"在移植过程中丢失了,变成默认的文本类型。之前有朋友提醒的.doc文件移植后无法打开应该也是同样问题。怎么办?一个文件一个文件的改?肯定不现实。

一种方案是把所有出现的二进制文件类型/后缀名找出来,然后在服务器端批量删除(Linux下写个脚本来做这件事并不难),客户端这边从原资源库checkout最新版本,重定向资源库URL到新的资源库,同步,提交。这招比较狠,但最终没有用,因为在浏览现有资源库时,发现还有不少其他问题,如classes文件夹被加到版本控制中,类似还有.settings文件夹,甚至Thumbs.db,不一而足。时间有限,与其每个Java项目去找一遍,整理出需要删除的文件(夹)清单,然后写脚本,然后强行资源库重定向,不如一步一个脚印把现有资源库的所有Java项目捋一遍,至少心里踏实。于是一狠心、一咬牙,有洁癖的我开始了漫长的"愚公移山":一个项目接一个项目,遇到Binary文件,服务器删之,客户端checkout后从原来的地方拷贝过来,必要的地方加上.cvsignore,再添加提交。*

经过4个小时的努力,终于大功告成:自动编译脚本正确运行,构建成功,客户端IDE(Eclipse)从新的资源库checkout,编译通过,没有红叉。

后记:自己认为计划得再好的事情,真正去做的时候,总还是会遇到这样那样的问题和意想不到的状况,这件事也告诉我自己其实我的前期准备远不够充分,算是自食其果吧。有没有更好的办法,我觉得肯定有,但是在特定的情况下(时间/效率/目标),我相信我的方法还是能够让我自己满意的。还有一点提醒所有CVS的用户,不该提交的文件,最好第一时间加到.cvsignore。子曾经曰过:“纠正错误,时间最早,代价越小”。

* 请勿不假思索的模仿,这样做会丢失掉这些文件的历史版本信息,如果删除的时候不小心,同时还会把历史上存在过的同类型文件删掉。我这里之所以可以这么做,是因为我们的实际情况对这些二进制文件不需要保留历史信息。


posted @ 2007-04-14 14:54 laogao 阅读(1694) | 评论 (3)编辑 收藏


大家期待已久的Debian重要升级4.0,代号"etch",终于正式发布。请看官方声明:
http://www.debian.org/News/2007/20070408


posted @ 2007-04-08 22:50 laogao 阅读(567) | 评论 (0)编辑 收藏


版本号1.6.0_01。

详见:
http://java.sun.com/javase/6/webnotes/ReleaseNotes.html


posted @ 2007-04-01 22:49 laogao 阅读(647) | 评论 (0)编辑 收藏


如果你使用非Outlook软件来处理来自Outlook以及Exchange Server的E-mail,你很可能会遇到附件为winmail.dat的邮件,而你完全不知道这个附件如何打开,甚至更惨的是原本附件在邮件中的文件也不幸被这个winmail.dat吃掉了。你也许会询问这封邮件的发件人,这个时候对方多半也是一头雾水,因为人家用Outlook用的好好的,从来没有听说过这个问题,说得直白一点,就是完全不知道你在说什么。

那到底这个winmail.dat是什么呢?是MS的工具在编码打包你的邮件进行发送时,如果按照默认指定的RTF格式,会把格式信息按照MS自己的一套标准存放在邮件体中,造成非Outlook客户端不认识,无法正确解析。Well done, Redmond.

怎么办呢?两个方案:
1- 如果可能,向发件人建议不要使用Outlook或者至少让他/她发送邮件时不要使用RTF格式,纯文本或HTML均可。(注意如果修改全局设置没有效果的话,可能还需要单独修改每一个存在通讯录里的联系人。)
2- 如果没办法让邮件的发送人对他/她使用的邮件客户端作任何调整,你也可以下载winmail.dat阅读器,如http://www.kopf.com.br/winmail/winmail-reader-setup.exe ,或者通过Google寻找其他类似工具。

强烈呼吁大家使用符合open standards的工具,尤其是在日常交流中日益重要的E-mail上,这是对你邮件的接收者最基本、也最直接的尊重。


posted @ 2007-03-26 00:24 laogao 阅读(36579) | 评论 (48)编辑 收藏


http://www.markshuttleworth.com/archives/99

Ubuntu创始人Mark Shuttleworth正式宣布加入今年1月由Linux业界两大组织OSDL和FSG合并成立的Linux Foundation。


posted @ 2007-03-14 23:56 laogao 阅读(478) | 评论 (0)编辑 收藏


由于工作需要,最近在Linux服务器上试用Subversion,如果一切顺利,全公司的文档都将交给Subversion管理。我承认我对Subversion一直存在偏见,但为了给大家一个交代,还是硬着头皮小试了一下。结果运行数天以后,终于还是回到了CVS的老路上。

Subversion的优点就不在这里重复了,网上很多介绍文章,也有很多忠实粉丝,不过没办法,我还是更喜欢CVS的简单和直接。熟悉Unix和类Unix系统的朋友一定有同感,CVS更加符合Unix的思维和解决问题的方式。
让我们最终放弃Subversion主要有以下大大小小的原因:
1- 一个新建的几乎是空的资源库,打包后大小即有39MB上下; << 经核实错怪SVN了,实测完全空白的资源库124K,向大家道歉!
2- 资源库几乎是以一种完全不透明的方式存储用户资源库文件;
3- 没有一个官方的、安全可靠的方式彻底删除一个误提交的文件,一旦提交上去,你的资源库将永远背着这个包袱; << 这一条实在让我无法忍受。

对于最后一条,官方说法是提供了一个svndumpfilter的方式,先把资源库dump出来,然后pipe到svndumpfilter过滤掉匹配的文件,最后再load回去。这几乎就是给我们判了死刑:dump文件动辄就会是好几个G,且随着时间增长,或者错误提交持续出现在超大型文件上,要完成这个dump和filter,以及周期性的备份,将要吃掉多少资源,不敢想象;svndumpfilter不支持wildcast,且这个字符串匹配由于是整个dump文件pipe到svndumpfilter,无法保证精确制导,尤其在生产环境,敏感文件被上传、有效文件被误删或者资源库遭到破坏的后果是很严重滴。


posted @ 2007-03-14 23:07 laogao 阅读(690) | 评论 (0)编辑 收藏


http://www.rssowl.org/node/210

RSSOwl终于有了2.0版的消息,RSSOwl 2.0最大的变化是
1- 采用Eclipse RCP;
2- 可以在本地保存feed。


posted @ 2007-03-01 08:25 laogao 阅读(503) | 评论 (0)编辑 收藏


http://www.artima.com/forums/flat.jsp?forum=106&thread=196922

Alberto Savoia在Artima上发表了一篇关于所谓Developer Testing Masters这个软件开发中的新角色的文章,把这个新的角色类比为脑外科医生。

不知道大家在各自的项目中是如何处理QA和开发人员单元测试之间的平衡呢?是让QA提高自身的技术水平,越来越多的参与白盒测试,还是“逼”着开发工程师们做他们不情愿、通常也做不好的单元测试?这篇文章提供了另一种思路。


posted @ 2007-02-28 13:14 laogao 阅读(473) | 评论 (0)编辑 收藏


http://www.ohshare.com/

文件大小限制在80M,没什么特别的要求,直接上传即可,据称超过30天没有下载的文件可能被删除,不过对于一般性的临时网络硬盘使用,已经足够了。

我试用了一下,速度还可以,大家可以试试下面这个下载链接:

http://dl8.ohshare.com/d/9417066/1172241028/ruby_1.8.5_p12.tar.gz


posted @ 2007-02-24 02:36 laogao 阅读(771) | 评论 (1)编辑 收藏


http://www.linux-watch.com/news/NS6401388051.html

Linux-Watch上刚发布了一篇关于最近Eric S. Raymond (ESR)“受够了”Fedora,“转投”Ubuntu的文章,挺有趣的。

Note: Eric S. Raymond可以说是Unix大牛和开源运动的鼻祖之一,他最有名的著作为"The Cathedral and the Bazaar"(中译“大教堂与市集”)和"The Art of UNIX Programming"(中译“UNIX编程艺术”)。


posted @ 2007-02-22 04:49 laogao 阅读(641) | 评论 (0)编辑 收藏


以下是一组相互关联、按时间先后排列的3篇blog文章,主要探讨是Swing存在的问题以及动态语言如JRuby/Groovy能否帮我们解决Swing的问题:

JRuby can save Swing
JRuby cannot save Swing
Groovy can save Swing

挺有趣的,推荐大家有空读一读。


posted @ 2007-02-21 20:03 laogao 阅读(590) | 评论 (0)编辑 收藏


http://www-128.ibm.com/developerworks/java/library/x-xjavaforum1.html

真正让XML发光的用途是什么?写配置文件?数据交换?数据存储?


posted @ 2007-02-21 14:31 laogao 阅读(419) | 评论 (0)编辑 收藏


原文链接: [URL]

Antonio Cangiano刚刚在他的blog发布了他在AMD Athlon 64 3500+, 1GB RAM的机器上做的目前常见的Ruby实现的非官方评测,包括
  • Ruby 1.8.5-p12 stable on Linux
  • Ruby 1.8.5-p12 stable on Windows Vista
  • Ruby 1.9 (Yarv) on Linux
  • JRuby on Linux
  • Rubinius on Linux
  • Cardinal on Linux
  • Gardens Point Ruby .NET on Windows Vista
几张有趣的报表:

http://www.antoniocangiano.com/files/rubyvms_in_seconds.png
http://www.antoniocangiano.com/files/average_and_median.png
http://www.antoniocangiano.com/files/rubyvms_times.png


posted @ 2007-02-19 17:57 laogao 阅读(494) | 评论 (0)编辑 收藏


http://jroller.com/page/rolsen?entry=building_a_software_team_wrong

关注这个Russ Olsen的blog有一段时间了,他最近的几篇blog贴子都和项目管理团队管理有关。我觉得相比成功的经验,有时失败带给我们的收获会更多。这篇最新的blog中Russ Olsen和我们分享关于他的一个失败的项目,以及他如何向团队承认自己的失误。

当一个项目失败的时候,也许承认错误、承认失败是件尴尬的事,但作为项目负责人的PM,如果他的某个决定造成了整个团队的失败,就应该拿出勇气去承担。

"It goes against something in us, especially as we get into management jobs, to admit that we were wrong. But when you are wrong, especially when you are wrong in a way that causes the whole team to fail, you gotta own up. Not that 'mistakes were made'. Not that 'it could have been done better'. Not even 'I did the best I could'. No, it has to be 'I was wrong'."


posted @ 2007-02-18 18:35 laogao 阅读(365) | 评论 (0)编辑 收藏


http://www.extremeplanner.com/blog/2007/02/managing-distributed-software-teams.html

这篇blog文章讲的是如何管理分布式的软件开发团队。现如今许许多多的软件开发团队都面临跨办公室、跨楼层、甚至是跨地域、跨时区的协同合作开发,一个完整的团队被拆散成2个或者更多的小团队,如何管理好这样的“分布式”团队,值得我们思考。

这篇blog的作者给我们开了个好头,他整理了如下几点:
1- 让开发人员结对完成设计和编码,让组员保持沟通;
2- 让项目的信息可以在线看到;
3- 周期性的让组员面对面交流;
4- 每天都开会,会议不必很正式很长,主要目的是让所有人都对项目现状、自己的工作和组员们遇到的困难有所了解;
5- 使用多种沟通和交流的工具/平台,如电话、IM、blog、Wiki。

我觉得尤为重要的是:
1- 把项目信息放在一个方便的、大家都能看到的地方,并保持更新,这个可以通过Wiki来做,关键是需要专人维护,Wiki是死的人是活的,Wiki有多大价值完全在于维护它的人给它多少信息如何组织这些信息;
2- 保持沟通的畅通,随时掌握团队其他人的现状和遇到的问题,也让他人掌握自己的进展和困难,这就体现出daily meeting的重要。


posted @ 2007-02-17 16:59 laogao 阅读(406) | 评论 (0)编辑 收藏


http://www.nytimes.com/2007/02/15/business/worldbusiness/15toyota.html

来自纽约时报的文章: "The ‘Toyota Way’ Is Translated for a New Generation of Foreign Managers"。在丰田全球扩张的过程中,在全球各地都建立了分支机构和生产工厂,雇佣了大量当地的工人和管理人员,如何将丰田多年积累的所谓“丰田模式”贯彻到所有海外工厂的日常管理,成为了一项颇具挑战的工作。

丰田模式,如果我的理解没有错,其最核心最基本的概念是“集体思考”,强调可视性和持续改进。展开来说,比较有趣的几点:
1- 问题是大家共同的,有问题大家一起解决。
2- 在出现问题的现场解决问题而不是在办公桌。
3- 任何人都可以指手画脚,发现质量问题,工人有权直接停掉生产线。
4- 持续发现问题并解决。
5- 建立共识。
6- 对人,尤其是一线工人的尊重。
7- 危机意识。

“丰田模式”有很多概念来自日本本土文化,并不能简单的复制。如今很多生产企业已经在活学活用丰田模式,把适用的部分应用到日常的开发工作中。那么对于软件开发的企业和团队,有什么可以借鉴的经验?

对于一个团队的软件产品或者项目组产出的代码/文档等提交件,首先是共同拥有,功劳是大家的,出现的问题也是大家的;其次是大家需要一个很方便很直接的途径看到团队的目标和当前的问题;对于发现的问题,团队任何人都有权指手画脚,甚至叫停整个开发来解决这些问题。

只有共同拥有和担当,才能最大化团队所有人的责任感和成就感;只有大家都清楚的看到共同的目标,看到需要面对的困难和问题,才能有目的的工作;当有人发现团队出现问题,遇到困难,必须有一个合理的途径报告和解决。并且一个团队应该有这种鼓励和包容“指手画脚”的文化,鼓励大家发现问题,持续改进。

这里面可能最难被接受的一点就是任何人都可以对发现的问题指手画脚并不惜停掉整个开发。这一开始看上去有些过激,但是细想起来则很有深意:叫停的权力带来的最直接的好处是最终产品和提交件的质量,可能有不少人认为软件质量并没有那么严重,或者觉得为了一点点质量问题影响整个进度不值得,但是叫停的权力的真正威力来自它隐含的东西。当所有人都明白质量的重要性,也都明白一旦停产,带来的严重后果就是整个进度的delay,整个团队的效率和产出都会受到牵连,大家就会很小心的遵守开发的规范,大家对待自己的产出也更加有责任感,让“坏分子”和“懒惰”无处容身。一旦叫停的权力成为团队文化的一部分,团队也就自然而然走上了持续改进的道路。


posted @ 2007-02-16 17:39 laogao 阅读(783) | 评论 (0)编辑 收藏


http://www.antoniocangiano.com/articles/2007/02/10/top-10-ruby-on-rails-performance-tips

这是一篇关于提高RoR应用性能的文章,提高RoR性能有两个途径,一个是服务器端配置,一个是在Rails这一块的调整,此文侧重于后者。主要的内容包括:

1- 在Ruby代码级别采用更优的方案;
2- 充分利用缓存;
3- 充分挖掘数据库潜力;
4- 合理使用finder查找函数;
5- 合并数据库事务;
6- 控制好你的控制器,不要滥用filters和实例变量;
7- 不要过度使用helpers,考虑HTML;
8- 合理配置日志;
9- 给你的Ruby GC打补丁;
10- 不鼓吹"premature optimization",但是尽可能带有性能考虑来进行编码。

大家觉得对于RoR的应用,上述这些说到点子上了吗?感觉RoR在性能调优上我们积累的经验还不是很多,我有点担心,虽然上面有很多好的点子可以借鉴,文中提到的某些"强心剂"是否真的值得推广?尤其是针对数据库的那些"quick-and-dirty"的做法。

posted @ 2007-02-11 12:55 laogao 阅读(509) | 评论 (0)编辑 收藏


JBoss的创始人Marc Fleury选择离开去年4月成功并购JBoss的Red Hat。网上大大小小的报道已经铺天盖地,不过我推荐大家读这一篇来自Linux-Watch的Steven J. Vaughan Nichols的文章:

We haven't heard the last of Marc Fleury

离开Red Hat的Marc Fleury会从大家的视线中消失吗?Steven J. Vaughan Nichols大胆的预测Marc Fleury将重操开源软件的旧业,不过不会是JBoss的克隆,而是一家Ruby on Rails的公司。


posted @ 2007-02-10 13:53 laogao 阅读(552) | 评论 (0)编辑 收藏


自从笔者在BlogJava开blog以来,承蒙大家的支持和鼓励,两年的时间内随笔已经接近400篇,当然也要感谢dudu为大家无偿的提供了包括博客园在内的人气blog空间。

为了更好的服务于我的读者,与更多热爱Java热爱技术的朋友分享我的心得体会、交流经验,我已在JavaEye开通分号,从现在起,我的这两个blog将同步更新。欢迎大家bookmark我的新地址:http://readsean.javaeye.com/[rss]。


posted @ 2007-02-10 13:19 laogao 阅读(421) | 评论 (1)编辑 收藏


很多开源框架的官方下载都会提供MD5的验证码,用于验证下载的完整性,确保用户下载的版本和发布者期望的版本是一致的,防止有人恶意篡改,尤其是存在很多镜像站点的时候。使用Unix系统的朋友可以通过命令行直接md5 + 文件名,或者md5sum + 文件名取得本地文件的md5验证码。使用Windows的朋友也能在网上找到不止一个提供MD5的工具。

不过既然Ruby在Unix/Windows/Mac上都能跑,那Ruby有没有提供MD5的功能让我们可以以一致的方式取得MD5 checksum呢?答案是有。
  1. #!/usr/bin/env ruby  
  2. require 'digest/md5'  
  3. ARGV.each do |f|  
  4.     checksum = Digest::MD5.hexdigest(File.read(f))  
  5.     puts "#{f}:\t#{checksum}"  
  6. end  

比如我们到http://struts.apahce.org/下载1.2.9版本Struts的源码,下载到本地后,可以用上面的脚本获取相应的MD5码,输出为:

struts-1.2.9-src.tar.gz   63ff6e570410876412f8fd97749b2415

拿后面这个63ff6e570410876412f8fd97749b2415和官方网站上相应的MD5 checksum作比对看是否一致,即可认定下载到本地的版本是否完整。


posted @ 2007-02-10 12:53 laogao 阅读(2615) | 评论 (0)编辑 收藏


今天在ZDNet上看到一篇挺有意思的blog,为什么Windows比Linux更难实现系统安全。文章举例Windows+IIS和Linux+Apache处理同样一个简单的带有图片的网页,在后台的系统调用图表大不一样。系统调用越多,层次结构越复杂,就越难实现安全性。

http://blogs.zdnet.com/threatchaos/?p=311

posted @ 2007-02-08 08:29 laogao 阅读(498) | 评论 (0)编辑 收藏


昨天试用一个WebService,需要确定是否正确安装配置,用Ruby来做真的很方便,一个本来在Java中颇为麻烦的事,到了Ruby(irb)里面,变得很简单。你要做的,就是打开irb,依次敲入以下代码:
  1. require 'soap/wsdlDriver'    
  2. URL = 'http://somedomain/someapp/somewsdl'    
  3. soap_client = SOAP::WSDLDriverFactory.new(URL).create_rpc_driver  

接下来就可以直接通过soap_client访问这个WebService的方法了,如:
  1. soap_client.version  
  2. soap_client.get_user_roles('user')  

如果你指定
  1. soap_client.wiredump_file_base = 'log_file'  

系统还能帮你记录在使用WebService接口时所有发出和收到的xml消息。

posted @ 2007-02-08 08:29 laogao 阅读(1116) | 评论 (0)编辑 收藏


"Management is doing things right, leadership is doing the right things."
- Peter Drucker

这是管理大师德鲁克的名言,”管理是(要)把事情做对,而领导是(要)做对的事情“。

posted @ 2007-02-08 08:29 laogao 阅读(446) | 评论 (0)编辑 收藏


Apache旗下的ActiveMQ日前正式"毕业"成为Apache的顶级项目之一。官方主页也从http://incubator.apache.org/activemq/改为http://activemq.apache.org/


posted @ 2007-02-07 00:28 laogao 阅读(927) | 评论 (0)编辑 收藏


春节快到了,现在按农历应该是六九吧?可这哪像是冬天?上海昨天白天气温竟高达21摄氏度,甚至有报道说今天达到了历史性的23度!近两年我们时不时就能看到世界各地越来越多的出现反常的天气状况的报道,这究竟是不是全球气候变暖在作祟,科学家们目前似乎还并不能给出一个一致的肯定或否定的答案。但我觉得,如果硬要说这个天气纯属自然规律,和人类活动一点关系都没有,多少有些牵强,至少有点不负责任。来看News.com提供的一组图片(含文字说明):

http://news.com.com/2300-11395_3-6156279-1.html

其中第五张是NASA航拍的马尔代夫群岛(拍的真漂亮),平均海拔在1米左右,如果真如部分科学家预言的那样,本世纪海平面上升7~23英寸(1英寸约合25.4毫米),这样一个美丽的旅游度假胜地会变成什么样子?(按照预期,2400年海平面平均将上升1米。)


posted @ 2007-02-06 23:48 laogao 阅读(625) | 评论 (0)编辑 收藏


"The truth is more important than the facts."
- Frank Lloyd Wright

Frank Lloyd Wright是美国著名的建筑大师,坐落于曼哈顿的纽约古根海姆博物馆即是出自Wright之手。这句话说的是:真理比事实更加重要,你可以罗列出一大推甚至无数的事实,但不管这些事实有多少,也比不上一个朴实无华的真理来得更有价值。这有点像我们现在面临的信息爆炸,不管这些信息是否都是事实,如果无法从海量的信息中得到有价值的部分,不论信息获取多么便捷简单,也没什么用。或者再换个例子,我们很多企业级的应用中每天都在产生记录企业活动的数据,如果没有一个强大的BI (Business Intelligence)对这些数据进行分析和挖掘,这些数据可能永远都是一堆0和1,无人问津,最后被所有人遗忘。




posted @ 2007-02-02 23:30 laogao 阅读(619) | 评论 (0)编辑 收藏


几乎每次下班回家,都能在轨道交通站台的广告牌上看到这一句出自姚明的话,以至于不用费心回想便可以脱口而出。我不喜欢篮球,也不是姚明的"粉丝",但我对这句话印象十分深刻。我想我之所以能够如此清晰的记住这句话,还有更深层次的原因,那就是这句话引起了我内心的共鸣。

有人说我是一个自视甚高、自命不凡的人,对待他人也是冷漠多过热情。不知道这个能不能和"不合群"划等号,但确实反映了我个性的一个方面。我追求完美,喜欢条理,希望得到认可,注重实际,对自己高标准严要求,对别人也有很高的期望。我自己并没有觉得什么不对,可能有时候有些锋芒毕露、吹毛求疵吧,别人并不一定能够接受。说真的,夹起尾巴做人也许被很多人奉为职场上需要恪守的原则,我也可以低调再低调,但是我认为该说的、该做的,我也会去说、去做。我曾经尝试退缩,尝试回避一些表达自己想法和不满的念头,但最终不但没有收到任何积极的效果,反倒是让我后悔没有第一时间说出来。

我喜欢什么事大家都挑明了说,如果谁觉得我有什么地方做得不好,可以提出来,我虚心接受,有则改之无则加勉;同样,我认为谁有什么地方值得改进,我也希望可以向他/她提出,而不必担心被他/她误解或者造成不必要的不愉快。有人提意见,至少代表他/她还care,如果有一天,大家都不提意见了,也就意味着大家对别人,对周围发生的事不再care,别人怎样,对他/她已经没有所谓。如果这个"别人"和这个"周围发生的事"和一个团队有关,那么也就意味着这个团队出现了沟通和信任上的危机,至少是失去了本可以更加健康发展的动力。

我可以谦卑而虚心,但我不能什么都不说。


posted @ 2007-02-02 01:13 laogao 阅读(868) | 评论 (2)编辑 收藏


一直误以为CVSNT和Linux下的CVS不兼容,至少没那么"无缝",事实证明一切真的很简单,以下就是从CVSNT迁出一个资源库到Ubuntu下的全部步骤:

1- 通过Samba或者其他方式将CVSNT资源库整个目录,包括CVSROOT子目录,拷贝到Ubuntu文件系统中,chown,chmod。
2- 在Ubuntu下编辑/etc/xinetd.d/cvspserver,在cvsargs增加--allow-root [YOUR CVS PATH],每一个资源库均写在这里,以空格分隔。
3- 命令行执行sudo /etc/init.d/xinetd restart。

迁移后的资源库即可使用了,包括历史修订记录、标签等等信息均完整保留,并不要求新的资源库用户和老资源库用户一致。这就是CVS值得我们叫好的地方,一切都那么简单、直接、好用。可能需要注意一下的是encoding,如果两边的encoding不一致,而文件名或目录名出现非ASCII字符的话,可能出现无法同步或者部分文件丢失的现象,文件内容出现非ASCII字符则不影响。

See Also: [Tips] 在Ubuntu Linux 6.06 LTS (Dapper Drake)上安装CVS服务


posted @ 2007-02-02 00:24 laogao 阅读(1188) | 评论 (0)编辑 收藏


最近拿到的.rar格式的文件越来越多,不论是网上还是工作中,在Ubuntu下倒是好办,sudo apt-get install rar即可搞定,但是切回Windows就有点惨,我没有WinRAR的license,也不想安装试用版什么的,于是一直在Linux下面做解压,再不就是让别人帮我解压好给我。现在不必了,用上了传说中的7-Zip[^],开源而且免费,总算可以和WinRAR彻底bye-bye了。


posted @ 2007-02-02 00:04 laogao 阅读(918) | 评论 (0)编辑 收藏


IDG旗下的Computerworld今天发表了一篇关于Vista的文章,作者Scot Finnie是从2003年便开始测试Vista的beta tester,文章的标题是: "The Trouble with Vista",以下是原文链接:

http://www.computerworld.com/action/article.do?command=viewArticleBasic&articleId=9009961
http://www.computerworld.com/action/article.do?command=viewArticleBasic&articleId=9009961&pageNumber=2
http://www.computerworld.com/action/article.do?command=viewArticleBasic&articleId=9009961&pageNumber=3
http://www.computerworld.com/action/article.do?command=viewArticleBasic&articleId=9009961&pageNumber=4

文章中不乏对Vista在原来版本Windows改进,以及微软整个team在Vista上所下功夫的肯定,但主要还从背后驱动Vista的动机来解释为什么Vista会做成现在这个样子。微软变了,不再是10年前那个关注用户体验,站在最终用户角度考虑问题的公司,而将注意力集中在以下两点:1- 尽量避免在公众领域的负面影响;2- 确保高端企业用户满意。在后"微软vs反垄断"时代,用户不再是上帝,微软也不再倾听。什么该有什么不该有早早就被确定下来。文章从Security、升级方式、DRM、Software Protection Platform (SPP)、定价5个方面一一进行分析。最终的结论是尽管Vista有很多受欢迎的改进,也一定能够成功,但它已不再让人兴奋,也不再有趣,"I don't absolutely have to have it. You don't either."

你会升级到Vista吗? 如果你问我,我的答案是: 现在还不会,将来有可能,不过如果上天给我这个机会,我将收拾行李,逃离MS和Windows。


posted @ 2007-02-01 21:30 laogao 阅读(627) | 评论 (0)编辑 收藏


http://www.alittlemadness.com/?p=76

今天读到这篇文章,原来和我想的一样,不过DRO这个提法的提法比我提炼的要更好,呵呵。


posted @ 2007-01-30 23:09 laogao 阅读(639) | 评论 (0)编辑 收藏


The greatest of faults, I should say, is to be conscious of none.
- Thomas Carlyle

Thomas Carlyle是19世纪英国历史学家、评论家、作家,试着翻译一下:“我得说,所有过失中,最严重的,莫过于意识不到它们的存在。”


posted @ 2007-01-29 19:33 laogao 阅读(690) | 评论 (0)编辑 收藏


接着上一篇的思路聊。既然我们可以把开发者社群看作一个整体,copy-paste别人的blog文章就是在违背DRY的精神,其实所谓"重造轮子"道理也是一样,既然别人都已经做了相同的事情,并且把它开源了,并且你看了它的代码以后,觉得做得不错,为什么还要自己费心去实现同样的功能呢?自己来实现能给你带来什么好处呢?

我可以列举一些我认为可能会让我们选择自己来做的理由:

  1. 我比其他人更了解我们自己的需求。
  2. 自己实现起来更容易,代码量更小,也更好用。
  3. 我是做技术的,能够DIY,就DIY,这样更能体现我的价值。

这些理由有它的道理,但是我们有必要仔细掂量掂量:

  1. 我比其他人更了解我们自己的需求。这是软件开发中很常见的一个误区,客户的需求难以把握,随着时间的推移,我们自己的技术层面的需求实际上也在不断变化,开源的框架往往经历了更多的考虑和验证,并且有一群热心的维护者帮你做bug-fix和升级,甚至我们自己就可以成为这群热心人中的一员。
  2. 自己实现起来更容易,代码量更小,也更好用。一开始确实是这样的,开源的框架为了满足不同的需要,往往需要比我们自己写代码要更加复杂和冗余,但是自制框架意味着我们自己定义的接口规范,这个接口规范能不能够在整个项目周期保持稳定暂且不谈,就算接口实现的再简单,项目中其他人也需要时间去理解和消化,然后记住一个定义好的调用方式,今后新加入的工程师也需要学习这个接口规范。开源框架则做得更好,一方面在这个项目中积累和学习到的知识,可以直接用在其他采用同一框架的项目中,另一方面新加入的人如果有过该开源框架的开发经验,上手时间可以缩短。
  3. 我是做技术的,能够DIY,就DIY,这样更能体现我的价值。我必须承认,我本人就亲身经历过这样的情况。在即将结束的这个项目中,我甚至自己DIY了一个简易的.NET报表引擎,为的是甩开Crystal Reports。一开始能够DIY报表引擎的想法让我兴奋得睡不着觉,最终前后花了3天很满意的完成了设计和开发,并交付报表开发人员重画报表。可是真正用了一段时间之后,基本的需求满足了,基本的可扩展性也具备,但是缺少可视化设计器、更灵活的公式、更丰富的报表元素,基本上就定型了,没有人有时间和精力再去维护它。

在很多开发团队,大家经常碰在一起讨论具体的技术和设计,这很有必要,有时也不可避免。但是也许Joel Spolsky说的对,软件设计很难,但是比设计软件更难的,是同整个team一起设计软件。做技术的,对于自己了解、掌握、做过、尝试过的东西,对于自己熟悉和信任的东西,多多少少有些偏袒,而对于新的、自己不了解、不熟悉的东西,则难免心存疑虑。这就难怪很多设计讨论会最终很难达成一致。这个时候,要么由技术上的最高权威直接拍板,定下来是什么就是什么,要么就分歧双方或多方各自陈述,然后由项目外部的实体进行独立仲裁。

我看好开源框架,尤其是那些经过考验广泛被采用的框架,因为相比自制框架,它们有着更大的优势。


posted @ 2007-01-26 00:32 laogao 阅读(936) | 评论 (0)编辑 收藏


如果你使用Firefox或Opera并且看到我上一篇随笔WYSIWYG这一个词,你可以看到它下面是用一串点标注出来的,如果你鼠标悬停在上面,会有工具提示"What You See Is What You Get"。HTML源代码是:

<abbr title="What You See Is What You Get">WYSIWYG</abbr>

可惜微软的IE并不能正确render这个tag,尽管它是标准(X)HTML的一部分。


posted @ 2007-01-25 23:23 laogao 阅读(1116) | 评论 (2)编辑 收藏


http://www.garrettdimon.com/archives/aspnet-vs-front-end-architecture

该文作者细数了他在使用ASP.NET进行开发的过程中遇到的6点不爽的地方,主要都集中在前台架构上,包括大量内联的风格标签、不同浏览器生成不同页面代码、失败的标记设计、缺乏语意一致性、服务器端label和客户端label的脱节、服务器端ID和客户端ID脱节等等。尤其当你想使用标准的CSS,构建数据结构和表现分离的清晰页面时,ASP.NET的一些默认的内部处理可以让你对ASP.NET为何这样做完全无语。比较有趣的是本文后面的回复,其中有不少与楼主同病相怜的网友,还有来自微软员工的为ASP.NET辩护的声音。

我一直对MS在很多设计思路和决定上心存疑虑,不明白为什么MS硬是要自成风格搞自己那一套蹩脚的所谓"规范"或"标准",似乎在鼓励大家follow一个并不清晰、多少有些混杂无章的设计架构,其实为了方便它实现更cool的WYSIWYG开发工具。就拿今天来说,本来我们项目定义好所有模块都按BO和UI分开,BO里面的类和UI里面的类各施其责,原则上UI依赖BO,而不是反过来,按照我的理解和期望,Windows.Forms命名空间应该是由UI层来依赖,而非BO层。很显然,因为我们的form都放在UI层,肯定是依赖Windows.Forms了,而我们尽可能把所有业务逻辑代码放到BO层。但是为了临时实现一个文本文件形式的log,因为我们的业务逻辑代码都在BO层,所以为了记录有意义的log,我们的log逻辑自然而然只能放在BO层。但是一个基本的获取程序运行路径的方法属于System.Windows.Forms.Application类,让我们不得不using System.Windows.Froms。这其实还好,我们也许不应该强求Windows.Forms一定就是只针对UI上的应用。问题是你每天都在面对类似的情况,每天都或多或少在和.NET API和框架其他部分在打架,当你使用.NET的API时间久了,自然而然你就被它带到它的那一套思路中,你的设计也就自然而然跟着它走了,业务逻辑和UI逻辑交织在一起,当你回过头来想把层次理清理顺已经成为Mission:Impossible。因为抛开MS推荐的方式,自己实现一套自认更清晰的架构,相较"官方"的blueprint设计,代价实在有些高。

所以虽然我没有真正开发过ASP.NET,尤其是2.0版,但我很能理解他们遇到的尴尬。


posted @ 2007-01-25 23:01 laogao 阅读(743) | 评论 (0)编辑 收藏


http://mikeomatic.net/?p=138

挺有趣的一篇文章。Java在桌面应用这个领域始终得不到广泛的认同,虽然Java 6和SWT/RCP都为改善桌面版Java应用做出了自己的努力,但Java在这个领域的坏名声已经难以挽回。造成这一现状的始作俑者是谁,是什么原因导致人们对桌面版Java心存偏见,使用Java开发桌面应用的朋友也会经常会觉得力不从心呢?该文作者提出了三点:

  1. Sun没有意识到这样一个事实:任何一款桌面框架的实现,假如不能无缝的运行在Windows上,都注定成为“也能运行”的一种GUI技术,始终无法和native的版本抗衡。
  2. 他们认定解决(实现)高级桌面控件的方法是通过Swing这种方式,为了“跨平台”,所有东西本质上都是通过JFrame自己在canvas上画,而不是利用现成已经实现的东西,带来额外的开销和重复劳动。
  3. 他们早应该把官方的开发工具做得更加完善,现在NetBeans发展很好,但是不是有点太晚意识到这个问题了,而不论OS X还是Windows,都在这方面积累了一大批忠实用户。

我认为,不管桌面版Java过去的名声如何,能够跨平台运行,越来越好的虚拟机环境和性能,越来越好的API和工具支持,庞大的开发群体和开源框架/工具,Java仍然是开发企业级桌面应用的一个相当不错的选择。


posted @ 2007-01-25 21:30 laogao 阅读(1080) | 评论 (4)编辑 收藏


http://www.artima.com/weblogs/viewpost.jsp?thread=192781

Artima上刚发表了一篇关于开发人员按照对待单元测试的态度和接受程度划分的三种不同的基因:
T1 - 天生接受型,给他们演示一下单元测试的概念和用法,他们立即一拍即合,编写单元测试案例成为他们开发中一个理所当然、不可或缺的步骤。
T2 - 易于接纳型,给他们足够的时间和鼓励,能够理解单元测试的好处并在开发活动中执行,但遇到项目压力,他们会选择代码优先而忽略单元测试。
T3 - 先天免疫型,不论你如何给他们灌输单元测试的好处,他们都不会领情,如果让他们把单元测试作为开发中的日常活动,他们宁愿不做开发。

我提议大家想一想,自己属于哪一类?自己所在的团队中的其他人,属于哪一类?我们希望自己和自己的团队是哪一类?希望单元测试在我们日常开发中扮演什么样的角色?


posted @ 2007-01-25 20:47 laogao 阅读(541) | 评论 (0)编辑 收藏


作为开发者,我们必须要学会defensive programming,尤其是对要求高可靠性和无人职守的企业级应用中,需要特别留意我们的设计和编码,必须尽可能做到足够defensive。

什么是defensive programming?举个大家都看过的例子:

String str = ...
if ("".equals(str)) {}

在这里我们不写str.equals("")而是反过来,就是为了防止出现不必要的NPE – NullPointerException。

运行期异常是最最需要特别关照的一种非正常状况,除了像上面这类要求我们采用相对较好的编码习惯之外,为了减少运行期异常的发生,通常也需要使用try-catch代码块来把我们相对脆弱,或者需要格外保护的逻辑包起来,对于外部传进来的参数,一定要assert它们的合法性,即assert它们是否能够安全的被后面的逻辑所使用。

通常意义上,defensive programming主要cover的是避免不必要的运行期异常发生。我们可以更进一步,更广义的运用defensive programming的核心思想:在企业应用中,除了运行期异常,对于有些看似严重的极端的错误,如网络超时,连接丢失,数据库提交失败等情况,需要我们具体问题具体分析,并非所有checked exception都一定需要我们去一一catch然后处理。更多的时候,尤其当开发无人职守的后台程序,我们可以采取重试、报告、修改外部数据等方式处理,能够自行解决的,就不要动不动就报错,或等待用户确认,不能自行解决的,则要及时报告并停止运行,避免更大的错误发生。

举个相对具体的例子,两个异构的系统,通过一个中间层的消息平台相互发送消息,通信协议采用最基本的socket方式,这三个系统随时都可能出现宕机或链接中断的情况。为了保证数据的完整性,我们拿其中一个需要发送和接收消息的系统来细说:

一个可能的实现方式是:该系统所有要发送的消息保存到数据库,给它一个初始状态;另一个独立进程从数据库按照时间先后拿出消息,更新拿出的这条消息的状态为处理中,并尝试发送消息;成功后根据需要,更新消息状态为成功发送或者直接删除,如果遇到失败或异常,消息恢复为初始状态,线程sleep一段时间,然后再次尝试,多次尝试或者尝试跨度超过一定时间范围,则停止处理,向管理员汇报(通过邮件、短信等途径)。对于接收到的消息,同样是先存入数据库,然后再由后续的进程用类似的方式取出并处理。如果程序崩溃,可以自动重新启动(应用或整个服务器)。这样不管哪一段通信线路出现故障或阻塞,或者宕机,系统都可以一步一个脚印,确保任务主动而自动的执行,并且忠实记录下有价值的状态信息,出现问题时管理员可以很直观的看到在哪个环节出现故障,从而快速找到问题关键并有效解决。

Defensive programming可以让我们的应用更健壮,在保证数据正确性、完整性的前提下,面对困难也能更加独立自主。和defensive programming相关的话题我想大家如果感兴趣,可以展开更多更深入的探讨,这里只是给大家做个介绍性的铺垫,能抛砖引玉当然更好。


posted @ 2007-01-25 00:03 laogao 阅读(1357) | 评论 (1)编辑 收藏


链接:
http://wordpress.org/development/2007/01/ella-21/


posted @ 2007-01-24 21:04 laogao 阅读(482) | 评论 (0)编辑 收藏


本文假定你有CD-ROM光驱以及Linux Live CD (如Ubuntu),并使用GRUB作为bootloader。

安装好Windows基本系统后,用Live CD启动,进入Linux桌面,打开Terminal,sudo -s切换到root,然后执行如下步骤:
  # grub
  grub> root (hd0,7)
  grub> setup (hd0)
  grub> quit
  # shutdown -r now
机器重启后,熟悉的grub界面又出来了。:)

注意在root命令和setup命令后都有空格。另外稍微解释一下hd0和hd0,7的含义:hd是Hard Disk的缩写,0表示第一块硬盘,7表示编号为7的分区。如果不确定原先的Linux安装所在的分区编号是多少,可以在敲完"root (hd0,"后敲[TAB]键,在列表中即可通过文件系统类型和分区大小一目了然的找到。


posted @ 2007-01-23 21:14 laogao 阅读(5074) | 评论 (4)编辑 收藏


详见:
http://www.linux-foundation.org/wordpress/?p=286


posted @ 2007-01-22 23:59 laogao 阅读(668) | 评论 (0)编辑 收藏


DRY为何物?DRY是Don't Repeat Yourself的缩写,不要重复自己,这是一项软件开发中的重要原则,或者至少是一个很好的习惯。同样的数据、逻辑,我们应该尽量避免在代码、配置文件、数据库中重复,如果实在没有其他更好的办法,也应该尽可能不要手写这些重复的内容。

既然是闲侃,我想就没必要那么一本正经,索性天马行空一把,想到哪儿写到哪儿吧。

一直不习惯用桌面版RSS阅读器,最近又从Newsgator回到了熟悉的Bloglines,由于工作忙,经过几周的积累,Keep New的条目数超过500。唉,又欠下一堆的阅读债。几经删减,订阅的RSS Feed源还是有80个之多。

一直在犹豫要不要取消BlogJava的综合区RSS订阅,一方面舍不得,毕竟自己在BlogJava安家,怎么说也得捧一下场,而我也需要持续了解这个圈子的人眼下都在做些什么想些什么;另一方面,实在有些难以忍受无数不做删减,原封不动照搬照抄其他网站内容的blog文章,其中不少我早已从其他渠道看到过,或者没什么特别的内容,整段整段的代码,这样的文章看了就是一句话,头痛。

当然了,别人怎么写blog,我无权干涉,但是我是不是可以在这里呼吁一下,引用其他网站内容,能不能不要整篇照贴,要么给个链接,让大家自己去看,要么适当的引用你认为最有价值的段落或句子,或者适当给出自己的见解和评论?否则很难让别人相信你的诚意和动机,这是对原文作者、你的读者、以及你自己起码的尊重。

换个角度来看问题,如果我们把软件开发社区看作一个整体,而我们就是这个整体中的一员,那么原封不动的拷贝粘贴这个整体中另外一个个体的文章内容,又何尝不是在广义上与DRY背道而驰?既然互联网给我们大家提供了分享信息的便利,为什么我们自己不懂得去维护这个本该服务于我们自己的环境呢?


posted @ 2007-01-22 23:22 laogao 阅读(738) | 评论 (1)编辑 收藏


"Personally I'm always ready to learn, although I do not always like being taught."
- Sir Winston Churchill

这是邱吉尔的一句名言,“就我个人而言,我总是乐于学习,尽管我并非总是喜欢被教导。” 我们通常认为与learn对应的词当然是teach,但是学习和受教其实是两回事。不断学习是好事,但总是被别人指手画脚是什么感觉,相信所有人都能够理解。


posted @ 2007-01-21 19:14 laogao 阅读(519) | 评论 (0)编辑 收藏


虽然官方网站显示最新版Rails还是1.1.6,RubyForge上已经可以下载1.2.1版。

[UPDATE] 官方已正式宣布: http://weblog.rubyonrails.org/2007/1/19/rails-1-2-rest-admiration-http-lovefest-and-utf-8-celebrations


posted @ 2007-01-19 09:20 laogao 阅读(588) | 评论 (0)编辑 收藏


详情请见FreeBSD官方网站官方声明


posted @ 2007-01-15 21:16 laogao 阅读(613) | 评论 (0)编辑 收藏


"An optimist stays up to see the New Year in. A pessimist waits to make sure the old one leaves."
- William Vaughan

"乐观的人总是主动去迎接新的一年的到来,悲观的人却经常是盼着旧的一年早点过去。"

顺便说一下,英文名Bill是William的简称,所以Bill Vaughan指的是同一个人,正如美国第42任总统克林顿,我们都叫他Bill Clinton,但是他正式的全名是William J. Clinton,又比如微软的总裁Bill Gates,其实你如果去翻他的简历,全名是William H. Gates。


posted @ 2007-01-14 23:23 laogao 阅读(572) | 评论 (0)编辑 收藏


原文:
http://www.linux-watch.com/news/NS6467114693.html

#更新:
根据Eclipse Foundation的Executive Director Mike Milinkovich的blog文章,Eclipse Foundation除了将加入JCP之外,还将加入OMG和OSGi。


posted @ 2007-01-13 12:05 laogao 阅读(976) | 评论 (1)编辑 收藏


安装NFS的方法很简单,apt-get install nfs-kernel-server,之后只要配置/etc/exports (如[path] [client-hostname](rw,async)),然后/etc/init.d/nfs-kernel-server start (或者stop|restart等等)即可启动和控制NFS服务运行。在客户端通过mount xxx.xxx.xxx.xxx:/xxx ([ip-address]:[server-path])的方式即可挂载并当做本地文件系统一样使用。

如果遇到在服务器端无法正常启动nfs-kernel-server,多半是你的portmap没有正确配置,需要dpkg-reconfigure portmap,弹出的界面选No。


posted @ 2007-01-10 21:17 laogao 阅读(3729) | 评论 (0)编辑 收藏


[注]由于Debian相当保守的包管理和更新机制,本文提到的编译和安装过程可能要求你在/etc/apt/sources.list中开放testing级别的包。

1- 首先是去PostgreSQL的官方网站[link]下载最新8.2.1版本的源码,postgresql-8.2.1.tar.gz。
2- 拷贝并解压:
     $ sudo -s
     # cp postgresql-8.2.1.tar.gz /opt
     # cd /opt
     # tar zxvf postgresql-8.2.1.tar.gz
     # cd postgresql-8.2.1
3- 在开始configure和make之前,先做一些准备工作,为了正常configure和make,需要:
     # apt-get install build-essential gcc-4.0 libreadline5 libreadline5-dev m4 flex bison zlib1g zlib1g-dev
4- 一切就绪,开工:
     # ./configure --prefix=/opt/postgresql ### 更多选项参考./configure --help ###
     # make
  正常的话,可以看到最后一行输出为: "All of PostgreSQL successfully made. Ready to install."
5- 安装:
     # make install
  最后应该看到输出"PostgreSQL installation complete."。
6- 初始化数据库环境:
     # mkdir /opt/postgresql/data
     # adduser postgres
     # chown postgres /opt/postgresql/data
     # sudo -u postgres /opt/postgresql/bin/initdb /opt/postgresql/data/
  编辑/opt/postgresql/data目录下的pg_hba.conf,添加local all postgres ident sameuser和local all all md5两行;
  编辑/opt/postgresql/data目录下的postgresql.conf,去掉listen_addresses的注释符,修改为listen_addresses = '*'。
7- 启动数据库:
     # sudo -u postgres /opt/postgresql/bin/pg_ctl -D /opt/postgresql/data -l /opt/postgresql/data/serverlog start
     # sudo -u postgres /opt/postgresql/bin/createuser -P dbuser
     # sudo -u postgres /opt/postgresql/bin/createdb testdb
     # /opt/postgresql/bin/psql -U dbuser testdb
  若能正常进入PostgreSQL控制台并执行查询如select version();即表示安装成功。

每次都这样去命令行启动数据库当然有点太笨了,下次再抽空和大家分享PostgreSQL自动化启动脚本的编写。


posted @ 2007-01-10 01:35 laogao 阅读(1447) | 评论 (1)编辑 收藏


由于最近国际互联网速率不是很稳定,而gem install自动默认到rubyforge下载gem安装包,由于rails依赖好几个其他的gem,而gem install需要遍历所有这些gem,所以gem install经常出出现超时的情况,怎么办呢?答案就是把相关的每个gem单独下载到本地,然后用--local选项安装。但是怎么确定你的需要哪些gem呢?

简单说明一下rubyforge的目录结构,了解之后找起gem来就会方便很多:
    http://rubyforge.org/projects/[project_name]/
# 把[project_name]替换为你要找的gem名称(不要加版本号)就能访问到该gem的主页,然后中间靠右即是跳转到下载页面的链接("Download"),排在最上面的就是最新版,注意文件扩展名,我们要找的是.gem。

本文假定你已经apt-get install ruby1.8 ri rdoc irb,并且也已经去http://rubyforge.org/projects/rubygems/下载并安装好RubyGems。

1- 首先下载rails gem,按照刚才提的方法,rails的gem主页在http://rubyforge.org/projects/rails/,目前的最新版本是1.1.6。
2- cd到下载到本地的目录,然后
    $ sudo gem specification --local --version 1.1.6 rails | grep "^   name:\|^        version:" # (^后分别是2个空格和8个空格)
    可以看到如下结果:
----------------------------------------
  name: rake
        version: 0.7.1
  name: activesupport
        version: 1.3.1
  name: activerecord
        version: 1.14.4
  name: actionpack
        version: 1.12.5
  name: actionmailer
        version: 1.2.5
  name: actionwebservice
        version: 1.1.6
----------------------------------------
3- OK,接下来我们依次去rubyforge下载这些gem,注意actionwebservice的project name是"aws",其余的project name和gem名称一样。
4- 依次sudo gem install --local [gem_name],rails放在最后,即可完成安装,可以通过which rails或者rails [项目名]验证。


posted @ 2007-01-08 23:32 laogao 阅读(936) | 评论 (0)编辑 收藏


http://www.reghardware.co.uk/2007/01/04/warners_readies_total_hd_disc/

上一篇随笔中曾经提到Blu-ray和HD DVD两种格式,不少人也许正在犹豫到底如何选,LG适时的宣布了同时支持Blue-ray和HD DVD格式的播放器产品,但是价格不菲,如今华纳也对外宣称:他们将在下周公布Total HD,一种同时支持Blu-ray和HD DVD的光盘格式,相比LG的播放器路线,在光盘上做文章,应该会更加经济一些吧。对消费者来说,是个好消息。


posted @ 2007-01-05 00:48 laogao 阅读(576) | 评论 (0)编辑 收藏


在Ubuntu下安装和配置PostgreSQL相对来说很简单,只是需要注意一些细节上的问题。在这里简单过一遍安装步骤,其中带[*]的地方需要特别留意。

1- $ sudo apt-get install postgresql-8.1 #[*]apt-get install postgresql会安装7.4版的PostgreSQL。
2- $ sudo nano /etc/postgresql/8.1/main/postgresql.conf #如果不是单机使用,需要修改CONNECTION AND AUTHENTICATION段的"#listen_addresses = 'localhost'"为"listen_addresses = '*'"(去掉注释符"#",允许网络访问而非仅限localhost)。
3- $ sudo -u postgres createuser -P #依次输入需要创建的用户名、密码、以及是否是超级用户、是否有权限创建数据库、是否有权限添加新的用户/角色 [*] 建议一定要用-P选项当场创建密码,避免以后的连接配置问题。
4- $ sudo -u postgres createdb [databasename] #创建数据库。
5- $ psql -U [username] [databasename] #正常的话已经可以进入PostgreSQL交互命令界面,并且看到PostgreSQL版本号,如8.1.4。[*]注意大小写
6- 安装自己喜欢的客户端,官方推荐pgadminIII,安装方法 $ apt-get install pgadmin3; 或者其他客户端,如Eclipse + QuantumDB (需要另外下载JDBC驱动)。

大功告成,坐下来喝杯咖啡~~


posted @ 2007-01-04 21:39 laogao 阅读(1988) | 评论 (0)编辑 收藏


http://docs.codehaus.org/display/GROOVY/2007/01/02/Groovy+1.0+is+there

Groovy是与Java平台无缝结合的动态语言,如今终于发布了1.0版。

posted @ 2007-01-03 23:53 laogao 阅读(1277) | 评论 (1)编辑 收藏


"You can only be young once. But you can always be immature."
- Dave Barry

你只能年轻一次,但你可以(选择)永远都不成熟。当有一天你不再年轻,并不意为着你已经成熟。


posted @ 2007-01-03 22:51 laogao 阅读(561) | 评论 (0)编辑 收藏


http://www.linux-watch.com/news/NS4586903228.html

由Debian创始人之一Ian Murdock担任主席的LSB(Linux Standard Base, Free Software Group的下属机构)近日做出计划,要提供一套通用的API整合不同的包管理工具/机制,如Debian的APT、RedHat和SuSE的RPM、YUM等等,使得在Linux平台安装软件变得更加标准化,以吸引更多的ISV为Linux平台开发软件。


posted @ 2007-01-03 22:23 laogao 阅读(698) | 评论 (0)编辑 收藏


http://wqy.sourceforge.net/cgi-bin/index.cgi?BitmapSong

该版本更好的支持粗体中西方字符,推荐大家更新。一个小小的注意事项,如果你使用官方的deb包在Ubuntu下安装,可能需要加上--ignore-depends=xfonts-utils,才能正确dpkg -i成功,这应该是这个安装包的一个bug。


posted @ 2007-01-01 19:17 laogao 阅读(688) | 评论 (1)编辑 收藏


转眼间,我们来到了2006年的最后一天,回顾即将过去的这一年,我们经历了什么,失去了什么,又得到了什么?

对我而言,2006年最大的一个决定,就是终于下定决心,离开工作和奋斗近两年的公司和圈子,举家从内地搬回上海。我胡汉三又回来啦!在这里,有我熟悉的环境,有我熟知的朋友,有我喜爱的工作。

一年中,和同事们一起,克服种种困难,完成并上线了一个重要的外包项目。在这里我想感谢大家对我的信任和帮助,感谢所有关注我、关心我的人。在这个过程中,我结识了新的朋友,同时,也很无奈,要和其他一些朋友说再见,包括一些曾经一起奋斗的知心好友,让我祝他们好运。

展望2007,我想我应该需要静下心来,总结一下自己在过去一年中学到的新知,以及做得还不够的地方,然后放下之前的所有包袱,整理好心情,去迎接新的挑战。


posted @ 2006-12-31 23:56 laogao 阅读(496) | 评论 (0)编辑 收藏


http://www.theregister.co.uk/2006/12/27/windows_drm_monstered/

网上关于Vista和DRM的讨论已经存在很长时间,按照上文中提到的Peter Gutmann的说法,Vista给大家,尤其是最终用户,带来了什么呢?答案是:
"A more expensive and less functional operating system"。


posted @ 2006-12-31 17:10 laogao 阅读(725) | 评论 (0)编辑 收藏


你是否经常需要ps aux然后kill -9?或者你已经使用过top?向你推荐一款top工具的全面升级版 - htop,这是一款在命令行运行,但是操作十分友好的Linux进程管理工具,打开以后,你可以直接用上下键选择进程及垂直滚屏,用左右键水平滚屏,F6选择排序方式,F9选择kill某进程,传递的SIGNAL可选,F10或q退出。

截屏:

htop.jpg

安装方法,如果你是用Ubuntu或者Debian:
$ sudo apt-get install htop


posted @ 2006-12-31 16:19 laogao 阅读(1188) | 评论 (1)编辑 收藏


"It's a common delusion that you make things better by talking about them."
- Dame Rose Macaulay

[Merriam-Webster's Collegiate Dictionary]
delusion n, 2 a: something that is falsely or delusively believed or propagated (http://m-w.com/dictionary/delusion)

有时候我们会以为我们谈论某件事某个问题,可以让它们实际上得到解决或者变得更好,这通常是一种错觉。


posted @ 2006-12-31 15:07 laogao 阅读(575) | 评论 (0)编辑 收藏


让我提醒一下各位准备进入IT行业,或者在IT行业但是还没有真正融入的朋友,IT这个领域,不管你做什么,都很有挑战,需要你的热情和勇气,这里没有金饭碗、铁饭碗,如果你入这行纯粹为了更轻松的工作或者更高的收入,我只能说我个人极其不看好你的这个动机。没有合适的心态和必要的职业素养,你很难成功或者满足。

首先需要好奇心,从计算机如何工作,到某个软件系统或框架是如何实现的,到具体业务领域为什么会有某项特定的需求,都需要我们的好奇心,没有好奇心,就没有兴趣,没有兴趣,做出来的东西就必然缺少灵魂。如果你连基本的好奇心都没有了,我劝你还是早点关注一下其他更能够引起你好奇和感兴趣的行业,否则要么你很失败,要么会做得很辛苦。

有了好奇心,接下来一定要有强烈的求知欲望,要有知甚解的精神。IT业是一个瞬息万变的行业,当下如日中天的技术,到了明天、下周、下个月、明年,可能就回无人问津,对于和你的知识面,和你的公司所涉猎的行业相关的技术知识、领域知识需要我们不断学习,不断充实自己,这个环节很难有什么捷径,如果有,也是通过一定的广度和深度来逐步达到举一反三的目的。曾经接触过不少“不求甚解”的朋友,表面上他们能够应付相当的工作和压力,但是很难让他们理解和掌握更深层次的东西。如果你观察他们足够长的时间,你会发现他们为了掌握不断变化或者不断发展的技术、框架、平台,或者适应某些看似极度不稳定的用户需求,由于没找到谱,其实也很累。

有了必要的好奇心,也有足够的动力去学习新事物之后,我们需要有追求完美的工作态度。拿软件开发来说,我们产出的是软件,从某种意义上讲,是我们的孩子,应该给予足够的关爱和呵护,谁不希望自己的孩子是天下最棒的?说到底软件这个东西从无到有,灵活性相当大,能够做到怎样优秀的程度,很多时候取决于我们自己。

最后是解决实际问题。追求完美没有错,但是需要有个度,需要有的放矢,需要有一个更加全局的指导方针,那就是解决实际问题。不论你做的东西采用多么先进的技术,你用了多么业界认可的管理方法,假如最后一些基本的客户需求无法达成,也是白搭。这是典型的“学院派”作风,我们在不断追求完美的同时,时刻都不能忘记我们存在的目的:解决实际问题。



posted @ 2006-12-26 23:39 laogao 阅读(1125) | 评论 (0)编辑 收藏


"Everyone thinks of changing the world, but no one thinks of changing himself."
- Leo Tolstoy

“每个人都想着要改变世界,却没有人想要改变自己。”
- 列夫·托尔斯泰


posted @ 2006-12-24 11:16 laogao 阅读(523) | 评论 (0)编辑 收藏




从上面这张对比图来看,似乎传统的影音播放产品和家用电子电器厂商更多的倾向于Blu-ray,而在这个产业相对新生的企业,许多在PC领域的强者,以微软和Intel为代表,更多的倾向于HD DVD。这两个标准第一次正面交锋出现在XBOX 360的HD DVD,以及PS3的Blu-ray。

HD DVD还是Blu-ray,这是个问题。


posted @ 2006-12-24 10:59 laogao 阅读(610) | 评论 (0)编辑 收藏


"Everywhere is walking distance if you have the time."
- Steven Wright

所谓walking distance,指的是走路就能到的距离,虽然没有一个明确的数字,但是很显然从杭州到无锡就不是walking distance。“只要你有时间,到哪里都是走路就能到的距离。”


posted @ 2006-12-23 13:36 laogao 阅读(638) | 评论 (0)编辑 收藏


http://leadinganswers.typepad.com/leading_answers/2006/11/agile_methods_a.html

关于如何使用敏捷方法管理知识型员工和团队,推荐阅读。其中两幅插图很形象的表示出:

Command-and-Control的管理模式如何压制团队和个人的创造力、贡献的热情和生产效率,而适当的敏捷方法和实践如何推动和提高团队及个人的创造力、贡献的热情和生产效率。

一个典型的Command-and-Control模式的特征:
- One way communications
- Lack of local control
- Compliance activities
- Bureaucracy
- Lack of recognition

一个典型的敏捷管理模式的特征:
- Self organizing team
- Empowered to make decisions
- Focus on business value
- No blame culture
- Team recognition + development


posted @ 2006-12-23 11:33 laogao 阅读(670) | 评论 (0)编辑 收藏


看到一篇好文,和大家共享之:
http://blog.technoetic.com/2006/09/19/threshold-of-pain/

大意是探讨为什么有些team的“技术债”(我们在IT项目进展中犯下的哪怕是小小的一点错误或者不作为,都会影响到整个项目产出的质量,影响到该目未来的发展、维护,甚至验收,使得成本和预算无法被有效管理)会慢慢堆积,而另一些team能够及时发现并纠正这些潜在的问题。是team的技能水平吗?并不完全是。我们可以从不同team对pain(项目进展和产出上出现的瑕疵)的敏感程度的不同来考量,而非简单的技能差异。

对pain的容忍度过高,项目中的“技术债”就会日益堆积,到最后项目变得无法收拾;对pain的容忍度过低,会让项目组变得吹毛求疵,得不偿失。当然,这个容忍度不可能也没必要定死在一个固定值上。有时候,我们也不得不临时调高这个容忍度,比如为了赶进度(如果错过某个deadline整个项目都可能会变得一文不值或者失去意义那种进度),问题的关键是,当我们有意识的提高宽容度,达到我们某个目标之后,能不能及时回过头来弥补这部分缺失的产出,避免今后带来更大的问题。今天你看来需要2周时间,你觉得不值,2周之后,同样这些欠下的“技术债”可能会“吃掉”你2个月,这不是在危言耸听。

如何找到一个平衡点?如何根据项目实际情况调整这个平衡点的位置?这是摆在每个项目管理者面前的现实问题,也是项目管理者的责任和义务。


posted @ 2006-12-23 10:40 laogao 阅读(725) | 评论 (0)编辑 收藏


如果你需要在不同的操作系统之间备份/恢复DB2数据库,那么你很可能遇到麻烦,据说有人成功的把DB2数据库在AIX 5上backup然后在Windows下restore,反正我是没那么幸运了,restore过程中除了备份文件名和路径不一致的问题,到最后一步还是报错,而Windows本地数据库backup然后restore就很顺利。

世界末日?还好,IBM DB2提供了db2move这个命令行工具,使用方法如下:
在需要备份的数据库服务器上执行
$> db2move [数据库名称] export
根据表的多少,当前目录下会生成一大堆文件,拷贝到新的系统下面,新建一个同名数据库,执行
$> db2move [数据库名称] import
即可。

直接敲
$> db2move
可以看到命令行选项的说明。


posted @ 2006-12-23 00:04 laogao 阅读(1382) | 评论 (0)编辑 收藏


看到这样的结果你也许并不意外,但是看到具体的数字可能会惊讶:

测试环境:
IBM (Lenovo) ThinkPad T43 (1G Mem);
Windows XP Professional (SP2), 文件系统NTFS,默认设置;
Ubuntu GNU/Linux 6.06 (Dapper Drake), 文件系统ext3,默认设置.

测试用例:
1M左右大小的文本文件,共计200个,搜索包含字符串'1000456732'的文件和相关内容。

Windows Search - 37秒,正确找到包含字符串的6个文件,但是没有直接提取出相关内容。
Notepad++ (Windows) Search in Files - N/A,超过5分钟没有任何反应,CPU99%。
grep (Ubuntu, 直接读NTFS分区) - 12秒,正确找出所有6个文件,63行相关内容。
grep (Ubuntu, 拷贝到ext3分区再执行) - 拷贝3秒,执行2秒,正确找出所有6个文件,63行相关内容。

还记得上次在Ubuntu下安装CVS带来的性能提升吗?
http://www.blogjava.net/sean/archive/2006/09/17/70145.html


posted @ 2006-12-21 23:59 laogao 阅读(689) | 评论 (0)编辑 收藏


我发觉技术出身的人,尤其是做编程、爱编程的,至少在我接触到的很多人,都有这种在普通人看来多少有些奇怪甚至相互矛盾的混合特质:好奇?单纯?内敛?天 真?执著?怀疑?死板?刻薄?叛逆?理性?感性?优雅?浪漫?洁癖?幽默?自我?敏锐?木讷?书卷气?追求完美?理想主义?孤芳自赏?难以形容的十分清楚,但就是让人觉得这个人群看问题 的角度、思维的方式、处理问题的方法,都在不经意间流露着可爱。

可能我骨子里就是这样一个人吧,表面上说别人,其实在暗示自己对类似的性格特征很有共鸣。不论现实让我走了多少弯路,直到我最终"子承父业",干上了 编程,仿佛才找到了真我。编程及编程相关的工作,不论是学到一个新的东西,实现一个新的想法,完成一个有挑战的任务,遇到志同道合的朋友,总能给我带来快乐,这样的快乐,直接而 纯粹。


posted @ 2006-12-21 22:34 laogao 阅读(488) | 评论 (0)编辑 收藏


http://blogs.zdnet.com/Burnette/?p=216

这是一周多以前的文章了,不过如果你还没从其他渠道看到这篇来自Ed Burnette的blog,推荐你读一读,挺有趣的,包括comments。


posted @ 2006-12-21 22:06 laogao 阅读(498) | 评论 (0)编辑 收藏


"The limits of my language are the limits of my world."
-Ludwig Wittgenstein

这是维特根斯坦的一句哲学经典:“(我的)语言之极限即(我的)世界之极限。”
人们对客观世界的认知和定义其实是局限于我们能够通过语言来理解和描述的它的极限。

用这句经典来调侃一下编程语言,某个编程语言能够做到的,是不是也局限于它从语意上乃至通过其相关的API/运行环境能够描述的?语言越强大,表达能力越强,背后的平台越强,那么它能够实现的功能,能够达到的高度和广度,就越高或者越广?

或者说,当你掌握的语言(不论是我们通常意义的语言、编程语言、还是所谓的DSL - Domain Specific Language、行话、方言)足够强大,或者你掌握的语言足够多,且涉及不同的domain,那么你的世界也将变得更加广袤和开阔。


posted @ 2006-12-18 23:21 laogao 阅读(579) | 评论 (0)编辑 收藏


http://www.blogjava.net/sean/archive/2006/12/15/87874.html

上一篇提到NAnt 0.85的两个bug,经过一番折腾,发现问题其实出在它bundle的sharpcvslib(scvs.exe),我的解决步骤如下:

1- 安装CVSNT,并在编译脚本加入
<property name="sourcecontrol.usesharpcvslib" value="false"/>
让NAnt不要使用那个bundle的sharpcvslib(scvs.exe),而是使用CVSNT的cvs.exe;

2- 去掉先前由NAnt建议的<cvs-pass>这个Task,以及<cvs-checkout>中的passfile属性;

3- 指定cvsroot中直接包含密码,格式
:pserver:username:password:@xxx.xxx.xxx.xxx:/your/cvs/path

前面提到的文件编码以及用户密码验证等问题均不复存在。

以下谈一谈我的观感:

.NET的开源项目,就NAnt和sharpcvslib来说,不论是代码质量、文档、社区活跃程度、更新/反馈周期,都还有很大的改进和提高的空间,从实际效果来看,感觉.NET部分开源项目的定位和初衷也很值得思考,究竟一个.NET开源项目的存在更多的是要证明.NET/C#也可以做到xxxx,还是要解决实际问题?这背后的价值观到底是什么?

如果是解决实际问题,那么为什么有现成的Win32环境下成熟的、完整的CVSNT可用,却一定要自己搞一套cvs库,而且还要默认使用这个相较而言颇为不成熟的库?如果你跟我说这样是需要对CVS访问有更精细的控制,那我想还不如在CVS的命令行参数上多下些功夫来得实际。

其实CVS已经存在很久,对于基本的协议、标准,现有的不少CVS客户端都实现的比较到位,sharpcvslib不知何故进展如此缓慢,官方站点 sharpcvslib.sourceforge.net最后更新时间是今年2月,上一个发布版本0.35是2004年,开发版本0.36是2005年1 月,NAnt也好不到哪里去,0.85的RC1版本2004年11月就出来了,正式的0.85到今年10月才放出,如果你看看它的bug database,很多bug都石沉大海。

这个版本的NAnt在使用中的一些细节的处理个人感觉也有些欠缺的地方:比如:使用<cvs-checkout>,password属性被deprecated,直接就不支持了,没办法,“官方”建议使用<cvs-pass>那我们就用吧,但是<cvs-pass>和<cvs-checkout>就目前看来,配合的并不默契(详见上一篇随笔bug ID 1616136)。

相比之下,生活在Java以及GNU/Linux/BSD下的朋友们,在上述这些方面就要幸运的多。


posted @ 2006-12-17 22:49 laogao 阅读(2387) | 评论 (1)编辑 收藏


由于是从Java转做.NET项目,在考虑SCM和自动编译时,自然而然想到NAnt,不过0.85的RC版本出来很久,一直没有正式release,直到最近一次偶然的机会我才得知正式版已经出来,虽然不支持Visual Studio 2005的解决方案/项目文件,但至少支持.NET 2.0,正好项目整个框架和模块清单基本定型,遂决定下点功夫把我们的构建过程脚本化、自动化。

经过些磕磕绊绊,总算是跑起来了,但还是有不够完美的地方,发现2个bug,提交到NAnt在SF.net上的bug database:

[1614467] NAnt自带的scvs.exe(<cvs-checkout>)从CVS拿文件时会忽略文件的原始编码,如UTF-8。
[1616136] NAnt的<cvs-pass>和<cvs-checkout>两个task对passfile属性的处理不一致,<cvs-pass>创建密码文件在指定位置,<cvs-checkout>却不从那里拿。

不知大家有没有遇到类似的问题。如果有时间,我倒是很想把源码拿下来看个究竟。


posted @ 2006-12-15 10:14 laogao 阅读(1905) | 评论 (1)编辑 收藏


参考上一篇(Second zero-day flaw):
http://www.blogjava.net/sean/archive/2006/12/06/85968.html

以下是来自CNET News.com的报道:
http://news.com.com/2100-1002_3-6143853.html


posted @ 2006-12-15 08:58 laogao 阅读(1616) | 评论 (1)编辑 收藏


在Google正式加入Eclipse Foundation后不到一周,又传来好消息:GWT开源了!GWT是Google重量级的Ajax开发框架,使得广大开发者可以使用熟悉的Java语法实现Ajax,这次GWT开源选择的是Apache License, version 2.0。详情:

http://code.google.com/webtoolkit/


posted @ 2006-12-14 18:52 laogao 阅读(1915) | 评论 (0)编辑 收藏


http://blogs.msdn.com/bclteam/archive/2006/12/07/introducing-pipes-justin-van-patten.aspx


posted @ 2006-12-09 00:57 laogao 阅读(1635) | 评论 (0)编辑 收藏


http://blogs.zdnet.com/Burnette/?p=214


posted @ 2006-12-09 00:35 laogao 阅读(1590) | 评论 (0)编辑 收藏


http://www.sutor.com/newsite/blog-open/?p=1264

注:
[1] Open XML是微软基于MS Office文档格式提交ECMA审核表决的文档格式标准
[2] Bob Sutor是IBM负责标准和开源的VP
[3] 目前已经存在同类标准 - ODF (Open Document Format),OpenOffice.org支持ODF标准。


posted @ 2006-12-09 00:08 laogao 阅读(1610) | 评论 (2)编辑 收藏


昨天刚刚向大家推荐了一个关于Trusted Computing的短片,今天继续沿着这个话题往前走,读一篇来自InformationWeek的文章:

How Vista Lets Microsoft Lock User In

通过在Vista中真正融入所谓的DRM/IRM(Digital/Information Rights Management)技术,微软可以有效地在"开放和标准化Office文件格式"的同时,通过加密、数字签名和数字授权等方式控制文件的打开、打印、修改、保存、转发,渗透到文档的整个生命周期,甚至文档发出去之后,还能亡羊补牢,收回授权!表面上这当然是在提高安全性,事实上这也是在打压Google、OpenOffice.org等MS Office之外的MS Office格式文件阅读/编辑器,使得它们不再能够在没有微软授权的情况下合法的打开MS Office文档,或者至少会让这个过程变得极端复杂。故事的另一头,在最终用户对安全都十二分的敏感的大前提下,典型的Office用户当然会遵从微软的官方建议或者许多媒体推荐的安全建议,把安全级别提高,乃至采取严格的加密授权这样的极端措施,因为MS Office给他/提供了这样的便利。到最后,要想得到加密的内容,光有key还不行,还必须使用MS Office,因为IRM理论上可以阻止其他阅读/编辑器得到认证。

举个例子,如果我的PC装的是Windows和Linux双系统,那么当我使用Linux并试图申请授权,尽管我的机器配置不变,IRM仍然可以认为我是不可信赖的接收者,因为OS也会参与IRM认证计算,甚至有可能当我升级我自己的硬件,会造成先前运行良好的应用程序或服务突然变得无法使用,同理,同样是Windows环境,如果使用非MS Office的编辑器,那么计算出的序号也将不同,无法获得密钥,从而也无法打开文档,这就事实上把用户,把用户的数据,和MS Windows、MS Office绑在了一起。我们有理由置疑这背后的动机,TC/DRM/IRM是不是有点管得太宽了呢?

如果我们日常工作和生活的文件编辑、交换、共享,甚至是官方公文的流转,都采用MS的格式和MS的工具,一旦微软成功实现了Lock-in,想想都觉得可怕。

TC/DRM/IRM背后最大的利益推动者就是微软,纵观微软TC/IRM/DRM的渗透过程,大致可以分为三个阶段:第一个阶段是硬件支持,目前市场上相当数量的主板,都已经集成了TCM(Trusted Computing Module)模块,只是没有被很好的利用;第二个阶段实现软件、服务平台、乃至操作系统级别的支持,初步实现远程认证,这个在微软的Genuine Advantage实施中收到了实际效果;第三个阶段当所有人都更新到最新的支持TC/DRM/IRM的Windows和MS Office,微软就可以从容的使用他们精心部署的"秘密武器"来实现垄断了。

近一段时间以来我时常对同事朋友们说,MS的世界是封闭的,为了达到所谓的"Openness",它要求所有人都使用MS Windows,进入这个封闭的世界,而且总是列举各式各样冠冕堂皇的理由。如果有一天,MS占据了我们整个生产链条的每个环节,并且有效的控制了盗版,我们每做一件事,哪怕是买一份早点,都在给MS上税,因为为我们提供早点的整个流水线的成本中包含了MS软件的成本,因为找不到合适的替代品,或者寻找替代品代价高昂(也许通过FUD造成这样的假象)。这就是垄断的危害,这就是为什么我主张大家更多的了解、学习和使用那些更开放的,甚至开源的操作系统、服务器和应用软件。

别小看了微软,尽管这两年.NET喜忧参半,Vista发布一再推迟,开源风头正进,微软也一度被很多置疑和负面消息笼罩,似乎正在逐渐失去它以往的光环,现如今Vista已经正式发布,微软这个昔日软件帝国新一轮的战斗野心正蓄势待发。

除了我自己,我无法阻止任何人使用Windows、MS Office,也无法阻止他们使用盗版软件,但是,我可以以自己的实际行动避免把自己反锁在微软的乌托邦,希望你也可以。


posted @ 2006-12-08 21:16 laogao 阅读(1873) | 评论 (1)编辑 收藏


很有趣的短片,介绍所谓的"Trusted Computing":

http://www.lafkon.net/tc/

[Note]"Trusted Computing"是业界许多公司非常推崇的一项技术,支持者包括Mircosoft、Intel、Dell、Cisco、HP、Apple等。我们经常在网上看到的另一个词汇"DRM - Digital Rights Management"也和这项技术密切相关。


posted @ 2006-12-07 22:04 laogao 阅读(1446) | 评论 (0)编辑 收藏


http://www.adobe.com/support/security/bulletins/apsb06-20.html

大家注意了,如果你正在Windows下使用Adobe Reader 7.x,建议尽快更新到Adobe Reader 8。如果无法更新至新版本,可按照官方的说明手工打上补丁:

1. Exit Internet Explorer, Adobe Reader, and Adobe Acrobat, if necessary.
2. Browse to <volume>:\Program Files\Adobe\Acrobat 7.0\ActiveX. Note: If you did not install Acrobat to the default location, browse to the location of your Acrobat 7.0 folder.
3. Select AcroPDF.dll and delete it.
4. Download the AcroPDF.dll file provided here: http://www.adobe.com/support/security/bulletins/acropdf.dll
5. Copy the new AcroPDF.dll file in to the ActiveX directory.

或者也可以选择Windows平台下其他的PDF阅读/修改工具,如:
http://www.download.com/Foxit-PDF-Reader/3000-2079_4-10313206.html


posted @ 2006-12-07 21:39 laogao 阅读(1454) | 评论 (0)编辑 收藏


http://www.microsoft.com/technet/security/advisory/929433.mspx

大家小心了,不要随便打开不明来源的Word文档,尤其是邮件附件或者网上采集的Word格式的文章,目前发现的这个缺陷在几乎所有市场上使用的Word版本(2000~2003等等)中都存在。至于何时可以发布补丁,目前官方还没有一个正式的时间表。

根据微软官方说明,该vulnerability的workaround是:
"Do not open or save Word files that you receive from un-trusted sources or that you receive unexpectedly from trusted sources. This vulnerability could be exploited when a user opens a specially crafted Word file." 不要打开不可靠的来源的Word文件,或者可靠的来源但并非预期会收到的Word文件,该缺陷可以在用户打开特别制作的Word文件时...blah blah blah

官方建议采取的行动包括:
"We recommend that customers exercise extreme caution when they accept file transfers from both known and unknown sources." 我们建议客户在接受文件传输时要“极端小心”,不论该文件来自认识的人或者不认识的人。

Fantastic!

建议大家还是在文件传输和共享时多多使用PDF或者其他更透明的格式吧。

For those interested, here is the link to an earlier Word vulnerability alert by EWeek:
http://www.eweek.com/article2/0,1895,1965042,00.asp


posted @ 2006-12-06 22:47 laogao 阅读(962) | 评论 (1)编辑 收藏


来自JavaLobby的报道:
http://www.javalobby.org/java/forums/t85683.html

以及官方消息:
http://www.terracottatech.com/press_12_04_06_oss.shtml


posted @ 2006-12-06 21:33 laogao 阅读(857) | 评论 (0)编辑 收藏


"Unable to connect to server. The server may be shut down."

??!! WTF.. 我想,说这句话的人一定是想表达“无法连接至服务器,该服务器可能已关机”这个意思。不过怎么看怎么别扭,按照字面理解,这句话的意思是:“无法连接至服务器,该服务器可以被关闭了。”

正确的说法应该是:
"Unable to connect to server. The server may/might have been shut down."

在这里顺便批评一下Foxmail,长期以来无法正常通过SMTP发送邮件,总是报无法连接的错误,同样的配置在Outlook、Outlook Express、Mozilla Thunderbird中均工作正常,忍无可忍之下,前不久把默认的邮件客户端彻底换成了Thunderbird。没错,前面提到的英文原句即是摘自Foxmail 5.0英文版。本想多多支持国人的作品,无奈最终还是没能坚持多久,总感觉不是很"适逸"。在此提醒各位软件行业的朋友,不论你做什么类型软件,细节上总是应该多多留意才是。


posted @ 2006-12-05 22:52 laogao 阅读(1204) | 评论 (4)编辑 收藏


发现一组有趣的测试题,完成这些测试,你会得到适合你的Linux发行版的建议。如果你正在众多优秀的Linux发行版中难以取舍,也许这组测试题能够帮你你找到答案:

http://www.zegeniestudios.net/ldc/index.php?firsttime=true


posted @ 2006-12-04 21:20 laogao 阅读(890) | 评论 (0)编辑 收藏


http://networks.silicon.com/lans/0,39024663,39164446,00.htm

个人认为比较值得推广的是住院病人的RFID腕带,药品等的正品/库存标识,血库,以及机场等公共场所的安检。


posted @ 2006-12-03 15:00 laogao 阅读(780) | 评论 (1)编辑 收藏


前几天刚在JoelOnSoftware上看到Joel Spolsky对Vista中关机菜单设计的不满:
http://www.joelonsoftware.com/items/2006/11/21.html

今天就已经看到亲身参与开发这一功能的前微软工程师(具作者本人称现就职于Google)的回复:
http://moishelettvin.blogspot.com/2006/11/windows-shutdown-crapfest.html

从中我们也许可以吸取一些设计上和开发过程管理上的经验。


posted @ 2006-11-30 23:07 laogao 阅读(1341) | 评论 (1)编辑 收藏


"It is almost a law of history that the same wealth that generates a civilization announces its decay. For wealth produce ease as well as
art; it softens a people to the ways of luxury and peace and invites invasion from stronger arms and hungrier mouths."

 - Will Durant
Our Oriental Heritage (The Story of Civilization, Vol.1)

这是Will Durant所著的《世界文明史》(第一卷)东方文明遗产中的一段精辟的论断:“这几乎是历史的定律:产生了某个文明的同一笔财富也宣告了这个文明的衰败,因为财富带来安逸和艺术,它使一个民族在享乐和太平中变得软弱,招致更加强壮且饱受饥饿之苦的外敌入侵。”


// 翻译的不好,只为大家能够明白大致意思。


posted @ 2006-11-30 21:05 laogao 阅读(307) | 评论 (0)编辑 收藏


当Firefox 2.0正式发布后,你也许觉得Ubuntu 6.06下面理所当然可以自动更新到最新的Firefox 2.x吧,可能你也听说了,Ubuntu 6.10默认就是Firefox 2.0,但是很不幸,在Ubuntu 6.06下面你并不能使用你也许已经习惯甚至依赖的apt-get install命令来安装它,你需要在命令行做一些dirty work:

首先备份原有的Firefox设置,这些可以在~/.mozilla/firefox/目录下找到。[此步骤可选]
从Mozilla官方网站下载最新的for Linux的Firefox 2.x:http://www.mozilla.com/firefox/
打开命令行:
# sudo -s
[输入root密码]
[cd到你保存Firefox下载包的路径解压缩]
# tar -C /opt -zxvf firefox-2.0.tar.gz
[链接plugins]
# mv /opt/firefox/plugins /opt/firefox/plugins.bak
# ln -s /usr/lib/firefox/plugins /opt/firefox/plugins
[链接firefox启动脚本]
# dpkg-divert --divert /usr/bin/firefox.ubuntu --rename /usr/bin/firefox
# ln -s /opt/firefox/firefox /usr/bin/firefox
# dpkg-divert --divert /usr/bin/mozilla-firefox.ubuntu --rename /usr/bin/mozilla-firefox
# ln -s /opt/firefox/firefox /usr/bin/mozilla-firefox
# exit

现在关掉所有Firefox窗口,重新按照原来打开Firefox的方式即可启动新版本的Firefox了。另外,如果你觉得Ubuntu默认的蓝色地球仪图标不好看,可以右键选择快捷方式,选属性,点击图标即可更改。我的做法是把官方的icon拷贝到/usr/share/pixmaps/目录下,即可从列表中直接选择。


posted @ 2006-11-29 23:32 laogao 阅读(2711) | 评论 (2)编辑 收藏


最新研究发现,在45度前倾、90度角直立上身、45度后仰三种坐姿当中,最不易引发背部劳疾的姿势是后仰45度,其次是90度直立上身,对身体最不利的是前倾45度的姿势。大家要注意哦,尤其是软件开发和服务行业的朋友们,你习惯的坐姿是?

http://www.sciencedaily.com/releases/2006/11/061127112844.htm


posted @ 2006-11-29 20:09 laogao 阅读(439) | 评论 (1)编辑 收藏


今天来了解一下Alan Kay。

Alan Kay何许人也?看看http://ei.cs.vt.edu/~history/GASCH.KAY.HTML便知。原来Smalltalk背后和早期OOP的探路者当中都能够找到他的身影,他还积极参与了以太网、激光打印、便携电脑等的前沿工作,他关于窗体化的图形界面的概念也直接影响到后来的Macintosh以及MS Windows的设计理念。

以下这句也许是Alan Kay最著名的名言了(越是经典的越是言简意赅):
"The best way to predict the future is to invent it." 预测未来最好的方式是创造未来。多么有气势的一句话!


posted @ 2006-11-28 23:13 laogao 阅读(375) | 评论 (0)编辑 收藏


Enhmm..(清清嗓子先) 一点一滴学英语系列已经很久没有和大家见面了,希望大家还没有完全失去印象。今天一起读一句名人名言:

"One machine can do the work of fifty ordinary men. No machine can do the work of one extraordinary man."
- Elbert Hubbard

Google一下发现这个Elbert Hubbard原来就是《把信带给加西亚》的作者,英语原文的标题是"A Message to Garcia",讲的是一个关于古巴的故事,当美西战争爆发后,美国必须立即跟西班牙的反抗军首领加西亚取得联系。加西亚在古巴丛林的山里,没有人知道确切的地点,所以无法带信给他。美国总统必须尽快地获得他的合作。怎么办呢?有人对总统说:“有一个名叫罗文的人,有办法找到加西亚,也只有他才找得到。”他们把罗文找来,交给他一封写给加西亚的信。作为一名合格的士兵,罗文接到信,并没有多问,一个人用了3周时间,徒步走过危机四伏的丛林,最终成功的完成了任务。

海尔集团总裁张瑞敏也有一句名言:“把每一件简单的事做好就是不简单,把每一件平凡的事做好就是不平凡。”

昨天看中央电视台的纪录片《大国崛起》,其中说到荷兰商人在一次试图航海通过北冰洋运送货物的故事,一船人被困在北极圈,缺医少药,最后不惜用生命的代价保全了货主的货物,其中就有可以救命的药品等,最后还安然无恙的送到货主手中。什么叫感动?这就叫感动。这当然也顺理成章的成就了当时荷兰商人的威信。

成熟发达的商业社会,对个人而言,最重要的素质就是诚信和敬业,这两点中的任何一点都很有分量,很有说服力。咱们中国人不缺勤劳,不缺智慧,也不缺口号,但是往往容易忽视诚信和敬业,缺少那种脚踏实地把自己本职工作做好,把每一个细节做到家的职业素养,这直接影响到我们在国际上的竞争力。很难想像,一个公司,如果所有人,或者相当数量的一批人,成天抱怨自己的工作太没有激情、没有创意、没有挑战,只关心自己的腰包,或者自己的工作量和薪资福利,成天挂在嘴边的就是公司政治,你争我夺,吃着碗里盯着锅里,抱着拿多少钱做多少事的心态,这样的公司如何能在各大行业日趋同质化,分工越来越细的全方位竞争中生存?


posted @ 2006-11-16 21:38 laogao 阅读(605) | 评论 (6)编辑 收藏


看来传闻中的GPL成为现实。来自国际先驱论坛报IHT的报道:
http://www.iht.com/articles/2006/11/13/business/web.1113sun.php


以下援引美联社的新闻稿:

Sun releases Java as open-source project


SAN FRANCISCO: Computer server and software maker Sun Microsystems said Monday that it had begun to make its Java technology an open-source software project available for free on the Internet.

The announcement represents one of the largest additions of computer code to the open-source community - and it marks a major shift for a company that had once fiercely protected the source code used in 3.8 billion cell phones, supercomputers, medical devices and other gadgets.

Santa Clara-based Sun said it is making nearly all of Java's source code - excluding small pockets of code that are not owned by Sun - available under the GNU General Public License. The same type of license also covers the distribution of the core, or kernel, of the popular open-source operating system Linux, which competes against Microsoft Corp.'s Windows operating system.

Making Java an open-source project allows programmers from around the world to examine, modify, fix bugs and contribute new features in Java's underlying code. It requires that any changes be made public.

Sun, a formerly high-flying dot-com that has lost billions of dollars since the stock market collapse of 2000, has hitched its rebound strategy in part to the growing open source movement.

Rich Green, Sun's executive vice president of software, said the company hopes to turn more developers into Java programmers, who may then create additional software to support Sun products.

"The open-sourcing of this really means more - more richness of offerings, more capability, more applications that consumers will get to use," Green said. "The platform itself will become a place for innovation."

All the Java source code is expected to be released by March 2007, Green said. The move covers all Java technology, which includes software that runs on handheld devices, personal computers and servers.

Analysts said the decision would likely extend the life of Java, which was released more than a decade ago, and boost business for the company.

"Sun profits from the Java ecosystem thriving," said Michael Cote, an analyst with RedMonk. "Whether it's their hardware sales or their service sales, by open-sourcing Java they're hoping to ensure its longer life and ensure it's what the community wants it to be."


posted @ 2006-11-13 21:49 laogao 阅读(1163) | 评论 (4)编辑 收藏


http://java.sun.com/javase/downloads/ea.jsp

以下是Java SE 6的新特性介绍:
http://java.sun.com/javase/6/webnotes/features.html

以及新版本Java SE的文档:
http://java.sun.com/javase/6/docs/


posted @ 2006-11-12 09:34 laogao 阅读(412) | 评论 (0)编辑 收藏


最近有关微软和Novell之间颇受争议的五年协议引来网上大小媒体争相报道,褒贬不一,甚为热闹,究竟微软这次真正意图何在,未来的Linux市场上会因为这次微软和Novell的合作协议受到怎样的影响,很多人的神经都不由得为之紧张起来。故事的背景我在这里就不重复了,本来也没想着为了这个已经被闹得沸沸扬扬的事件再多写些什么,但今天看到Linux界颇有影响的Nicholas Petreley的一篇与微软和Novell针锋相对、5年内和Novell/SuSE划清界限的宣言,忍不住还是出了这篇随笔,和大家分享:

A five year deal with Microsoft to dump Novell/SUSE


posted @ 2006-11-09 21:45 laogao 阅读(561) | 评论 (0)编辑 收藏


今天的Dilbert蛮逗的:如何利用你的无能来达到目标?
http://www.dilbert.com/comics/dilbert/archive/dilbert-20061105.html


posted @ 2006-11-05 19:01 laogao 阅读(380) | 评论 (0)编辑 收藏


来自CNET科技资讯网:
http://www.cnetnews.com.cn/news/softwares/story/0,3800055189,39543751,00.htm

Mark Shuttleworth是一个有着传奇经历的南非企业家,年仅33岁,全世界屈指可数的自费太空旅行者,Ubuntu社区的创始人,11月1日他在北京接受了记者采访,以上是CNET科技资讯网的报道。

30岁上下恐怕是一个人在人生和事业上最黄金的年纪,想想自己也是PIII的人了(刚刚过完27岁生日),至今除了有一个温馨的小家和一份喜欢的工作,鲜有作为,更谈不上成就了,实在有些惭愧。父母、家人、同事和朋友为自己创造了这么好的环境和平台,可别辜负了他们。


posted @ 2006-11-05 15:48 laogao 阅读(426) | 评论 (0)编辑 收藏


以下是来自CBS News的报道:
http://www.cbsnews.com/stories/2006/11/02/health/webmd/main2147223.shtml

咸水鱼类的大面积灭绝不仅仅是意味着我们可能再也吃不到现在这么丰富的海鲜,由于海水中的鱼类可以净化毒素,防止“红潮”等藻类泛滥,如果失去这样一个天然保护层,滨海城市乃至整个人类的生存环境都将受到严重的影响。保护海洋生物的多样性,我们别无选择。



posted @ 2006-11-04 15:47 laogao 阅读(521) | 评论 (0)编辑 收藏


Interesting read:

http://www.economist.com/agenda/displayStory.cfm?story_id=8113328



posted @ 2006-11-04 00:05 laogao 阅读(318) | 评论 (0)编辑 收藏


Check it out:
http://testng.org/



posted @ 2006-11-03 23:29 laogao 阅读(297) | 评论 (0)编辑 收藏


http://www.ubuntu.com/news/610released

主要的功能能强包括:
# Tomboy记事工具,电子版报事贴软件
# F-Spot图片管理,类似Picasa
# GNOME 2.16桌面系统
# Upstart,新的启动daemon
# 最新版Firefox 2.0浏览器
# 主动预防式安全功能
# Evolution邮件客户端

Tomboy和F-Spot可能是目前Mono应用中最成功的两个项目了。比较遗憾的是Canonical这次对于新版的Ubuntu 6.10 (Edgy Eft)并没有提供Shipit免费寄送光盘服务,它的Shipit服务目前仍然是6.06 LTS版,当然,你还是可以在相当多的镜像服务器免费下载到最新的ISO。


posted @ 2006-10-28 16:24 laogao 阅读(658) | 评论 (5)编辑 收藏


Check this out:
http://www.computerworld.com/action/article.do?command=viewArticleBasic&articleId=9004468


posted @ 2006-10-28 16:11 laogao 阅读(452) | 评论 (1)编辑 收藏


看到这个标题你也许会问,网络带宽不是越大越好么,干嘛还要限制?事情是这样的:如今越来越多的互联网接入都不再是单机,而是一个互联网连接,多个PC机或服务器共享。这样一来如果不对每个点的带宽做限制,当这个点肆意使用带宽的话,势必影响到同样使用该连接的其他主机对互联网的访问效果。

Linux下有什么设置可以实现么?答案是trickle和trickled。如果你还没有安装,那么在Ubuntu下,打开命令行,使用如下命令安装:

# sudo apt-get install trickle

安装完毕,即可使用trickled -d [XX] -u [XX]修改全局的下载速率和上传速率(对所有trickle进程的总开关而非系统级别),或者用trickle -d [XX] -u [XX] [COMMAND]以限制速率的方式启动某个程序。如:

# trickled -d 40 -u 20
或者
# trickle -d 40 -u 20 firefox

这样下载速率就会被限制在40KB/s之内,上传速率会被限制在20KB/s。以下信息仅供参考:一般家庭接入的ADSL总下载速率可以达到100~150,上传速率可以达到50左右。



posted @ 2006-10-22 00:00 laogao 阅读(4054) | 评论 (6)编辑 收藏


Eclipse Google Code Search Plugin
可以在Eclipse中直接右键搜索,并在Eclipse中直接打开搜索结果,目前版本1.0.1.
http://egcs.javaforge.com/

ZDT - Zhongwen Development Tool
中文教学插件,可以看到拼音,自定义词库,小测验等,目前版本0.6.0.
http://zdt.sourceforge.net/

上面的链接中都有截图供给大家参考。



posted @ 2006-10-21 10:59 laogao 阅读(1668) | 评论 (1)编辑 收藏


先介绍一下问题的语境:相信我们当中不少人已经都有过输液的经历,也就是大家通常所说的打点滴、吊盐水,更专业一点,可能会听到医生护士用静脉滴注这样的表述,究竟我们生活中经常说起的"输液"用英文中哪个单词来表达最为贴切呢?

简单搜索一下,发现这个词的英文翻译有很多的版本,有drip、 transfusion、 perfusion、 infusion,甚至我也曾经看到有人用injection这个词。最后一个其实很好排除,injection用于医疗注射这一含义的时候,是特指那种使用针筒注射器将药液推注进体内的方式,也就是通常说的肌注-肌肉注射,它一个核心的特点是by force。Drips则近了很多,drip作名词时有"滴注器"这个含义,put somebody on a drip,给某人输液。

剩下的3个词则显得更加难以区分。都是fusion,究竟这3种不同的词根加在fusion前面会给这个词带来些什么微妙的变化呢?我们首先分别来看看 transfusion、 perfusion和 infusion在Oxford Advanced Learner's Dictionary (牛津高阶词典)和Merriam-Webster Collegiate Dictionary (韦氏大学词典)两大词典中的定义吧(忽略掉不相关的条目):

Transfusion:
[Oxford] (also blood transfusion) n [C,U] an act or the process of putting one person's blood into another person's body.
[Webster] an act, process, or instance of transfusing (to transfer (as blood) into a vein of person or animal); esp: the process of transfusing fluid into a vein(静脉) or artery(动脉).
# 主要(最早的用法)还是指输血,也可以指输液,重点在"TRANS/转",从一个个体到另一个个体,或者从一个地方到另一个地方,也不限制是不是by force,比较泛。

Perfusion:
[Oxford] (ENTRY NOT FOUND)
[Webster] perfuse: to force a liquid through (an organ or tissue) esp. by way of the blood vessels(血管).
# 通过血管输送液体通过器官或组织,不具体指某一中注射方式,重点在"PER/通过、透过、彻底"。多见于美式英语。

Infusion:
[Oxford] 1: [C usu sing] ~ of sth (into sb/sth) the introduction of sb/sth new that will have a positive influence. 2: (a) [U] the act of process of soaking tea, herbs, etc in a liquid. (b) [C] a drink, medicine, etc prepared in this way.
[Webster] 1: the act or process of infusing. (infuse - to steep in liquid (as water) without boiling so as to extract the soluble constituents or principles) 2: a product produced by infusing. 3: the continuous slow introduction of a solution(溶液) esp. into a vein(静脉).
# 最常用的含义是泡、沏,在美语中直接可以指静脉滴注,在英式英语中含义则相对泛一些,指引入某种能够带来积极效果的人或事物,重点在"IN/入"。

最后再看看前面提到过的drip在这两大词典中的定义:

Drip:
[Oxford] [C] (medical) a device that passes liquid food, medicine, etc directly into a patient's vein(静脉).
[Webster] a device for the administration of a fluid at a slow rate esp. into a vein(静脉); also: a material so administered.
# 不论在美式英语还是英式英语中都指医用滴注器,也衍生出静脉滴注这个process的含义。

哈哈,看到这里,是不是有点晕了,不过我们还是需要找出一个答案,不然岂不白白看了这么一大堆英文词典的定义?我选drip,你的选择是?



posted @ 2006-10-20 23:06 laogao 阅读(7291) | 评论 (8)编辑 收藏


For your leisure reading:

http://www.hacknot.info/hacknot/action/showEntry?eid=90



posted @ 2006-10-13 00:10 laogao 阅读(1057) | 评论 (0)编辑 收藏


实事求是的说,Linux下面默认的字体,尤其是中文字体,绝大多数发行版自带的都不怎么好看。于是安装字体成了安装桌面版Linux之后顺理成章的一个必要的步骤。但是从哪里开始呢?推荐GNU的文泉驿项目:http://wqy.sourceforge.net/

这篇blog中,我就简单整理一下文泉驿点阵宋体0.7版(北斗)在Dapper Drake上的安装步骤,供大家参考。(部分内容来自网友ailantian的Debian下安装文泉驿点阵宋体的说明文章 http://wqy.sourceforge.net/cgi-bin/index.cgi?Dou_INSTALL_Deb )

本文成型时最新的北斗版本为0.7.0-4,首先到文泉驿的主页找到wqy-bitmapfont-pcf-0.7.0-4.tar.gz的下载,从SourceForge.net的其中一个镜像站点下载到本地。(笔者使用的是Optus Net http://optusnet.dl.sourceforge.net/sourceforge/wqy/wqy-bitmapfont-pcf-0.7.0-4.tar.gz )

下载好的文件放到本地/opt目录下,接下来在本地依次执行以下命令:
# sudo -s
# cd /opt
# tar zxvf wqy-bitmapfont-pcf-0.7.0-4.tar.gz
# cd wqy-bitmapfont
# mkdir -p /usr/share/fonts/bitmap/wenquanyi
# cp *.pcf /usr/share/fonts/bitmap/wenquanyi
# fc-cache -f
# cd /usr/share/fonts/bitmap/wenquanyi
# mkfontdir
# vi /etc/X11/xorg.conf
{在这里添加如下一行:FontPath "/usr/share/fonts/bitmap/wenquanyi"}
# cd /etc/fonts/conf.d
# unlink 30-debconf-no-bitmaps.conf
# exit

这个时候从System->Preferences->Font中已经可以找到WenQuanYi Bitmap Song这个字体了,按自己的喜好选择使用该字体(笔者的选择是除了Fixed width Font之外都是用WenQuanYi)。如果确认以后并没有整个桌面都刷出新的字体,登出GNOME再登录回来即可。

posted @ 2006-09-17 17:44 laogao 阅读(1605) | 评论 (2)编辑 收藏


之前项目一直使用Win32环境的CVSNT做源代码版本管理,终于有一天受不了Windows下面跑CVS的性能(一方面CVS很慢,另一方面做CVS服务器的机子也被拖累了),下定决心把CVS搬到Linux环境下。

以下简单记录一下在Dapper Drake上安装和配置CVS的步骤,供大家参考(由于服务器在内网,无法使用Debian系统下方便而强大的apt-get,只能手动下载了):

1- 下载和Dapper Drake匹配的CVS版本cvs_1.12.9-17_i386.deb,建议从国内比较快的ubuntu.cn99.com的源上拿,路径是/pool/main/c/cvs/cvs_1.12.9-17_i386.deb;

2- 下载xinetd包,同上/pool/main/x/xinetd/xinetd_2.3.14-0ubuntu1_i386.deb;

3- sudo -s转成root;

4- dpkg -i cvs_1.12.9-17_i386.deb;

5- dpkg -i xinetd_2.3.14-0ubuntu1_i386.deb;

6- 为你的CVS资源库选择一个目录,比如mkdir /MyCVS;

7- cvs -d /MyCVS init 初始化该CVS资源库;

8- vi /etc/xinetd.d/cvspserver,添加
service cvspserver
{
     port = 2401
     socket_type = stream
     protocol = tcp
     user = root
     wait = no
     type = UNLISTED
     server = /usr/bin/cvs
     server_args = -f --allow-root /MyCVS pserver
     disable = no
}

9- /etc/init.d/xinetd start;

10- 开始配置CVS用户,最简单的方式就是采用Linux自己的用户/文件系统权限管理机制,我的做法是添加一个专门的用户组dev,然后往里面加用户,最后修改CVS资源目录的权限:
# addgroup dev
# adduser username
# adduser username dev
# chown -R username:dev /MyCVS
# chmod -R 775 /MyCVS
暂时用775,今后可以根据需要再细化每个文件/文件夹的细节权限;

11- exit 退出sudo -s模式;

12- 打开你熟悉的CVS客户端开始享用新的CVS服务器吧,相信它的性能相比较Win32下的CVSNT,一定会给你带来惊喜:D。


posted @ 2006-09-17 17:10 laogao 阅读(2322) | 评论 (8)编辑 收藏


http://domino.research.ibm.com/comm/pr.nsf/pages/news.20060809_openhealthcare.html


posted @ 2006-08-12 00:13 laogao 阅读(815) | 评论 (0)编辑 收藏


Trolltech发布了针对Java的Qt工具包(Preview版本) - Qt Jambi,可以直接用Java编写Qt式跨平台(Linux/Mac OS/Windows)GUI应用,继承了Qt的简洁高效和本地化的L&F,同时也和SWT/Swing/AWT友好共存。不过一方面这个小东东还在探索阶段,另一方面不太喜欢Qt的授权模式,姑且先观望一阵吧。

http://www.trolltech.com/company/newsroom/announcements/press.2006-07-14.7914556269/

FAQs:
http://www.trolltech.com/developer/faqs/Qt%20Jambi


posted @ 2006-08-02 23:29 laogao 阅读(2903) | 评论 (0)编辑 收藏


Free Software Magazine发表的评论文章:

Why Red Hat will go bust because of Ubuntu
http://www.freesoftwaremagazine.com/articles/editorial_13


posted @ 2006-08-02 22:35 laogao 阅读(1046) | 评论 (0)编辑 收藏


For your leisure reading.

http://www.computerworld.com/action/article.do?command=viewArticleTOC&specialReportId=9000100&articleId=112360
http://www.computerworld.com/action/article.do?command=viewArticleTOC&specialReportId=9000100&articleId=112368



posted @ 2006-07-15 12:20 laogao 阅读(1165) | 评论 (2)编辑 收藏


你是否曾经为Windows关机等得不耐烦而又不知道它在背后鼓捣什么?或许下面的文章能对你有所帮助。

http://www.intelliadmin.com/blog/2006/07/why-windows-takes-so-long-to-shut-down.html


posted @ 2006-07-07 14:13 laogao 阅读(1054) | 评论 (1)编辑 收藏


http://www.eclipse.org/callisto/

http://www.eclipse.org/downloads/

等了太久了。


posted @ 2006-07-01 09:15 laogao 阅读(918) | 评论 (0)编辑 收藏


http://www.eclipse.org/callisto/

Bookmark this!


posted @ 2006-06-27 13:55 laogao 阅读(921) | 评论 (0)编辑 收藏


开发过程中把Eclipse当作CVS客户端来用的时候,可能会遇到这样的情况:发现某些文件其实不需要CVS来管理,比如很多中间文件和可以通过其他源代码自动生成的东东,时间长了,一方面影响CVS性能,另一方面也是增加了同步时的额外工作,和真正需要上传的源代码混在一起,看上去很是不爽。这个时候你想起来可以把这些文件加入.cvsignore,但是这个时候无论你怎么弄,"Add to .cvsignore"菜单项总是灰掉的。

为什么会这样呢?答案是这个"Add to .cvsignore"只能对还没有加入版本控制的文件起作用,所以对于那些已经加入的文件,这个菜单就被disable掉了。

一个彻底但是相对野蛮的的解决办法是把项目从CVS断开,删掉所有的CVS目录,删掉CVS服务器上的这个项目的目录,在本地所有需要的地方新建.cvsignore文件(Windows用户注意,在Explorer中无法创建这样的文件,只能走命令行或者用编程的方式创建),和CVS目录一样,每个目录一个,打开.cvsignore文件以文本方式加入希望被CVS忽略的条目,如:"*.exe"、"bin"等等。然后再和CVS同步,这个时候被忽略的条目(文件或者整个子目录)就不再出现在同步的文件列表中了。


posted @ 2006-06-27 11:36 laogao 阅读(3814) | 评论 (6)编辑 收藏


http://blogs.msdn.com/winfs/archive/2006/06/23/644706.aspx

You still don't get it, do you?
Vista? 还是算了吧。


posted @ 2006-06-26 22:03 laogao 阅读(849) | 评论 (0)编辑 收藏


由于MP3是专属格式,并不free,所以一般的Linux发行版默认都不带MP3编码器,如果你希望Sound Juicer直接压缩MP3格式,需要手动改些东西:

打开Sound Juicer,选择Edit->Preferences,在Output Format下可以选择不同的编码,默认是没有MP3的,点击右面的Edit Profiles,选New,名字取成MP3,选中MP3,点Edit,在GStreamer Pipeline项输入:
audio/x-raw-int,rate44100,channels=2 ! lame name=enc
File Extension用mp3,勾上Active选择框,确认。

如果没有刷出来,重启Sound Juicer即可使用。


测试环境:
Ubuntu 6.06 LTS (Dapper Drake) + GNOME 2.14.2 + Sound Juicer 2.14.4。


posted @ 2006-06-17 01:07 laogao 阅读(830) | 评论 (0)编辑 收藏


经过数月的测试,Dapper Drake终于正式发布。

http://www.ubuntu.com/news/606released




posted @ 2006-06-01 22:19 laogao 阅读(402) | 评论 (0)编辑 收藏


Interesting theory.

http://www.forbes.com/2006/05/20/executive-compensation-tournament_cx_th_06work_0523pay.html

posted @ 2006-05-28 23:29 laogao 阅读(410) | 评论 (0)编辑 收藏


http://www.vnunet.com/vnunet/news/2156205/sun-promises-open-source-java

很显然Sun自己也知道只有把Java真正完全开源,才能最大限度的阻止Java开发社群走向分化。但问题是如何确保Java不会像各式各样的Linux发行版本那样陷入一种开源而又相互排斥、各自为政的尴尬境地。

在今年的JavaOne上,Sun公司新CEO Jonathan Schwartz向媒体传递了这样的信号:"It's not a question of whether we'll open source Java, the question is how"。我们当中很多人应该都记得当年IBM多少带这些挑衅的要求Sun开源Java,我们不少人或许还自觉或不自觉地成了那次事件的炮灰。还有后来的Kaffe、GCJ等等开源的JVM和Java编译器不断涌现,不少开源社区的开发者等不及Sun,于是决定自己做一套开源的Java。所有这些事,Sun看在眼里,记在心里,却迟迟没有让人们看到曙光,Sun在犹豫,它没有准备好。

虽然我很愿意相信这次Sun是认真的发自内心的对开源的热情拥抱,但是理智告诉我这是Sun在外界的强压下做出的又一次妥协,与之前Java部分开源、OpenSolaris开源并追加GPL方式、Sun ONE Studio等IDE免费/开源等等事件本质上并无二致。并且这样的决策取向也符合Sun的最高利益。

与这次JavaOne宣布Java开源同步进行的另一件事也值得我们关注一下,那就是Sun重新定义了对GUN/Linux和OpenSolaris等开源操作系统的Java分发包的许可协议,OS厂商可以按照自己的打包方式发行官方许可的Java,以往我们在几乎所有通行的GNU/Linux开源发行版上找不到现成的Sun官方版Java的情况有希望成为历史,至少这个许可协议刚一推出,就得到了Debian和Ubuntu社区的积极回应,这当然是好事。

"Official packages of Sun Java are now available from the non-free
section of Debian unstable, thanks to Sun releasing[1] Java under a new
license: the Operating System Distributor License for Java (DLJ)[2][3].
This license, while still non-free, allows the Sun Java Runtime
Environment (JRE) or Java Development Kit (JDK) to be distributed by
Debian, with our own packaging." [摘自debian-devel-announce的邮件列表]

更多Sun Java在Debian的进展细节:
http://packages.qa.debian.org/s/sun-java5.html

Sun官方新闻(关于新的Operating System Distributor's License for Java):
http://www.sun.com/smi/Press/sunflash/2006-05/sunflash.20060516.4.xml


// 无关技术细节,故不确定是否合适放在首页。不过我觉得上述内容值得和大家,和更多关注Java的人分享。

posted @ 2006-05-17 22:17 laogao 阅读(1150) | 评论 (0)编辑 收藏


http://jcp.org//en/jsr/results?id=3770

JSR #244 - Java Platform, Enterprise Edition 5 (Java EE 5) Specification在2006年5月1日全票通过。

posted @ 2006-05-03 04:18 laogao 阅读(658) | 评论 (1)编辑 收藏


 3M为了表明他们的防盗玻璃性能卓越无懈可击,在一个公交车站安放了这样一个装满钞票的橱窗,怎么样,够创意吧?其实里面只有$500美金的真钞,而且旁边还有保安看守,规则是如果你想试试破坏它,也只能用脚踹。不过总的来说,这个创意还是不错的,你觉得呢?

转自:http://gizmodo.com/gadgets/gadgets/3m-security-glass-ad-170504.php

posted @ 2006-04-30 14:18 laogao 阅读(497) | 评论 (0)编辑 收藏


下载:
http://download.eclipse.org/eclipse/downloads/drops/S-3.2RC2-200604281315/index.php

posted @ 2006-04-30 09:16 laogao 阅读(555) | 评论 (0)编辑 收藏


不知不觉中,我在NewsGator Online订阅的Feed已超过100个,每天的阅读压力也在逐渐增加。在使用NewsGator的过程中,发现一个很生动的当代GC(垃圾收集器)实现的类比,拿出来和大家分享,能帮助其他人理解GC当然再好不过,帮不上的话(言下之意你已经知道分代式GC的原理),就当是消遣吧。

我不知道大家平时怎么用NewsGator来阅读订阅的Feed,我的习惯是先简单浏览一遍,把感兴趣但是暂时没时间看的话题加入My Clippings目录,然后把当前这一页全部标记为已读,继续浏览下一页或者下一个目录。等到空闲的时候,打开My Clippings仔细阅读那些被我加进来的文章和链接。My Clippings目录和其他目录一样,默认都是时间降序排列的,越新的Feed越靠前,而我通常都会把My Clippings里面的Feed数量控制在100以内。

由于我订阅的Feed很多,涉及到的领域也较广,加上阅读时间有限,第一遍总会有一些原本不是我想细看的溜进My Clippings目录,当我进入My Clippings,发现这样的Feed,对待它们我就是一个字:删。然后会陆续读掉一些Feed,分享一些Feed,这些阅读掉和分享掉的Feed,我也会清理出My Clippings。而我的阅读顺序,默认也是先读新的,再读旧的,因为越新的,越值得关注。我每次打开My Clippings也不一定总能把整个目录从头到尾浏览一遍,不过几乎也总能发现、阅读和清理掉一些Feed。这样通过一伦又一伦的新陈代谢,我的My Clippings目录能够长时间保持在100个条目之内,也总是能够留下我感兴趣但是还没来得及细看或者分享的Feed。

想想看,一个分代式GC背后的想法和实现不也是这样么?当内存不够或者应用程序主动提出垃圾收集的要求时,GC会在最新的一代对象池中找出垃圾(可能是没有意义的,被错误创建的对象,也可能是被使用掉,失去作用的对象),清理掉,留下的被升级为第二代。为什么GC可以认定第一代中的对象最有可能是垃圾,而第二代、第三代对象相对而言不大可能是垃圾呢?比对一下刚才的例子,没有经历过清理同时又是新加进来的Feed,最有可能是被错误加进来或者已经阅读和分享过的,而经历过一次和多次清理都没有被清除或者分享掉的,则更有可能是那些等待我阅读和分享的Feed。换作对象的概念:那些没有经历过GC、新创建的对象,即第一代对象中,最有可能发现错误创建或者已经处理结束的对象(超出生命周期),而第二代或者更老的对象,经历过GC,却没有被清掉(因为有其他对象还在使用它),则更有可能可能是真正有用的对象。把有限的精力用在真正值得的地方,这就是分代式GC相对传统GC的更高效率的来源。


posted @ 2006-04-27 23:08 laogao 阅读(1733) | 评论 (6)编辑 收藏


http://www.sysinternals.com/

如果Windows是你常用的操作系统,那么当你遇到一些莫名其妙的问题(可能是病毒、木马或者流氓软件,也可能是系统自身的缺陷)时,除了像没头苍蝇一样上网到处找解决方案、请高手修改注册表、甚至不得已重装之外,应该有更好的办法。这里以Freeware方式提供并持续更新相当数量的系统工具和专业信息,值得大家一试。


posted @ 2006-04-27 21:07 laogao 阅读(1353) | 评论 (0)编辑 收藏


http://programming.linux.com/article.pl?sid=06/04/12/1921225

这是一篇组织的相当好而且也控制得相当精简的Mono入门向导,推荐感兴趣的朋友阅读。如果你没听说过Mono,没关系,简单的说,Novell资助的开源项目Mono解决了在Linux环境下编译和运行.NET(C#)应用,甚至是ASP.NET以及Web Services,加上用作图形界面的GTK#,我个人认为Mono在Linux下面的应用环境开始逐步趋于完整,值得花些时间和精力去学习、尝试。


posted @ 2006-04-26 00:56 laogao 阅读(1214) | 评论 (3)编辑 收藏


http://www.businessweek.com/technology/content/apr2006/tc20060425_843283.htm

Jonathan Schwartz接任Scott McNealy成为Sun的新CEO。


posted @ 2006-04-25 23:57 laogao 阅读(1182) | 评论 (0)编辑 收藏


JDBC和 ADO.NET都提供了脱机数据缓存机制。孰优孰劣?不同的人会有不同的答案。那么它们之间的区别在于?可以看看About.com上的这组文章:

http://java.about.com/library/weekly/uc_cacheyourdata1.htm
http://java.about.com/library/weekly/uc_cacheyourdata2.htm
http://java.about.com/library/weekly/uc_cacheyourdata3.htm
http://java.about.com/library/weekly/uc_cacheyourdata4.htm
http://java.about.com/library/weekly/uc_cacheyourdata5.htm



posted @ 2006-04-24 23:10 laogao 阅读(1305) | 评论 (0)编辑 收藏


http://www.codinghorror.com/blog/archives/000568.html
http://www.codinghorror.com/blog/archives/000283.html

你会遵照油漆桶上的说明来涂漆吗?油漆桶上的说明,如果你仔细去看,会发现很多条目都是你觉得理所应当的,没什么了不起,甚至没有什么技术含量,但正是这些看似简单甚至"弱智"的使用说明保证了最终油漆涂出来的质量。转念想想现如今做软件何尝不是如此,管你技术再先进,个人的水平再高,如果忽略了好的习惯和基本的纪律,最终的结果未必好看。

posted @ 2006-04-23 21:53 laogao 阅读(1158) | 评论 (0)编辑 收藏


http://blogs.msdn.com/danielfe/archive/2006/04/19/579109.aspx

刚看到的消息,之前正式的说法是,作为促销手段,从去年11月7日开始,只要你在一年之内成功的从微软网站上下载到Visual C#/C++/Basic/J#/Web Dev 2005 Express,你都可以免费使用任意长的时间,现在(2006年4月19日起)这个一年之内获取拷贝的限制已被正式取消。

早该如此了。

posted @ 2006-04-20 02:32 laogao 阅读(2382) | 评论 (0)编辑 收藏


在EclipseZone上看到这则消息,Eclipse Project发布了3.2的RC1版,Callisto也在一步一步地走向最终的成功。顺便看了一下Callisto的首页Callisto Simultaneous Release,接下来每两周都会有新的RC出来,very solid it seems:

  • 12-Apr 9am PT/noon ET - CallistoRC1 status
  • 19-Apr 9am PT/noon ET - CallistoRC2 status
  • 26-Apr 9am PT/noon ET - CallistoRC2 status
  • 3-May 9am PT/noon ET - CallistoRC3 status
  • 10-May 9am PT/noon ET - CallistoRC3 status
  • 17-May 9am PT/noon ET - CallistoRC4 status
  • 24-May 9am PT/noon ET - CallistoRC4 status
  • 31-May 9am PT/noon ET - CallistoRC5 status
  • 7-Jun 9am PT/noon ET - CallistoRC5 status
  • 14-Jun 9am PT/noon ET - CallistoRC6 status
  • 21-Jun 9am PT/noon ET - CallistoRC6 status

  •  

    posted @ 2006-04-15 16:56 laogao 阅读(1152) | 评论 (0)编辑 收藏


    工作累了?看看这里的几段视频广告,当作休息吧:(前提是你不反感MS的宣传,呵呵)

    http://www.400plusdifferences.com/

    posted @ 2006-04-15 10:38 laogao 阅读(1007) | 评论 (0)编辑 收藏


    今天照旧看老刘的东方夜谭,听到一首改编得相当有味道的音乐FLASH,听得我忍俊不禁。如果你不巧错过了,这里给你来一段回放(audio only):


    posted @ 2006-04-12 22:39 laogao 阅读(1624) | 评论 (0)编辑 收藏


    http://www.redhat.com/about/news/prarchive/2006/jboss.html

    posted @ 2006-04-10 23:19 laogao 阅读(869) | 评论 (0)编辑 收藏


    我相信我们当中不少人已经都知道GNU/Linux和Sun之间那种心照不宣选的分歧,加上是Stallman和他的FSF在中间掺合,还有一群志愿者自己弄一个开源的Java,似乎这个分歧已经要演化成为Java和Linux之间一堵柏林墙。真有必要这样吗?我不想说谁对谁错,谁都有自己的价值观和信仰,但是这样的纷争对开发者,对于那些真正想要通过软件改善这个世界的人们来说,有什么好处呢?喜欢(Sun)Java的会怎样看Linux,喜欢Linux的又会怎样看Sun?这还不止,拜FSF所赐,甚至Linux阵营内部也为了一个GPL v3出现了不小的裂痕,你说闹不闹庭?相比之下,还是BSD的世界来的清静,虽然也有分歧,但是更多了一分理性和务实。默默无闻的做自己想做的事,不是挺好的吗?

    题外话不多说了,看看这则新闻。FreeBSD将随他们的OS发行Sun授权的Java的二进制版本:

    http://lists.freebsd.org/pipermail/freebsd-announce/2006-April/001057.html


    posted @ 2006-04-06 15:07 laogao 阅读(1052) | 评论 (1)编辑 收藏


    和1.5.0相比,除了一般的bugfix之外,比较重要的改进是性能(内存使用)有了很大提高。详见:
    http://www.eclipse.org/aspectj/

    posted @ 2006-04-05 21:31 laogao 阅读(811) | 评论 (0)编辑 收藏


    这里查看News & Noteworthy:
    http://download.eclipse.org/eclipse/downloads/drops/S-3.2M6-200603312000/eclipse-news-M6.html

    目前大多数mirror还没有更新这个版本的下载包,只能从加拿大的Main Download Site下载

    posted @ 2006-04-02 08:12 laogao 阅读(1384) | 评论 (2)编辑 收藏


    新的项目要求使用C#,对于习惯了Java开发模式和环境的朋友来说,一开始总会有些不适应。

    拿我自己的体验来说,VS2005跟Eclipse SDK相比,当然画GUI和调试的直观性方面给我留下的印象很深,不过也有些我认为缺少了的东西:增量编译(很多时候只有F6以后,编译错误提示才会消失,有些引用和IntelliSense才生效,不像Eclipse,保存后自动增量编译)、代码排版(很怀念Ctrl-Shift-F)、引用整理(很怀念Ctrl-Shift-O)、很多有用的重构(可以说VS里面代码级的重构相比很多Java IDE差远了)、单元测试的集成(NUnit理论上应该可以很好的集成到VS2005,不过还是花了我一些功夫)、CVS客户端(很怀念Eclipse SDK)。当然,一些IDE当中相对小的差异一开始也很难适应,不过这些也可以理解,属于正常范畴。

    最近为了把项目的一些基调和开发模式定下来,做了一些尝试,我想也许对大家还有些用,整理一下放在这里。

    一个好的.NET项目,我相信有些东西事先定义好,对项目整个过程是有很大好处的,这些东西至少应该包括:开发工具选择和配置、代码模板、单元测试、代码自动化review工具、自动编译和测试、缺陷跟踪、文档管理等。当然如果不计成本,那么有很多重量级的SDLC框架可以用,如VSTS(MSF)、Rational(RUP)和Borland的集成工具,以上这些环节的问题相应的框架也大都给出了很好的解决方案,但是毕竟不是所有的项目都会购买和采用那么"重"的方法和过程,很多时候就算有那个预算,对于特定的项目,实施起来也不见得就会收到好的效果。于是我们接触到的很多项目,其实都还是需要自己去寻找适合的工具来把整个周期串起来。以下是我在尝试找到一套合适方案时遇到的一些特定问题以及解决办法:

    首先是单元测试工具以及和IDE的集成。在Eclipse SDK中,我们不必太过关心这个问题,因为Eclipse已经很好的集成了JUnit。但是在.NET的世界,人们是怎么做的呢?答案是NUnit,一个跟JUnit非常类似的东西。和JUnit一样,NUnit也提供了命令行版本和GUI版本,但是VS里面并没有直接提供集成,你更多的时候需要从外部运行NUnit,当然这样很不爽啦。VS号称是自己也提供了单元测试工具,但是那仅仅在高端VSTS中才有。如何解决这个集成的问题呢?可以到http://www.testdriven.net/ 上下载一个TestDriven.NET的VS add-in。安装以后,就可以在VS中调用我们可能经常需要调用的NUnit来跑自己的单元测试了。

    其次是代码模板。一个项目,不管大小,总会涉及到相当数量的源代码文件,我们希望这些源代码都包括一些共有的东西和特定的注释,怎么办?在Eclipse里面有code template的概念,那么在VS里呢?答案是Project Template和Item Template。一开始我根本摸不着头脑,只看到MSDN上正在说Code Snippet,于是我实现的1.0版代码模板就是基于Code Snippet的,用起来很不方便,有关Code Snippet,我等下还会提到,这里先看Templates。我Google了一下相关的Project Template和Item Template的说明,基本都是VS 2003的,不过它们给了我很好的提示,至少可以知道VS在生成默认的代码时是怎样一个思路。所有的VS 2005代码模板都可以在%VS_2005_INSTALL_PATH%\Common7\IDE\ProjectTemplates和%VS_2005_INSTALL_PATH%\Common7\IDE\ItemTemplates目录下面找到,Project Template和Item Template不同的是Project Templates是在你新建一个项目时使用的模板,而Item Templates是在你往一个现有项目中添加item,如Form、Class等的时候使用。这里需要注意两点:一是VS 2005跟VS 2003不同,templates不再是直接的.cs文件等,而是打包在了.zip中,需要修改的话,需要把新的文件重新压到.zip中;二是除了template目录,还有一个TemplateCache目录,为了立即看到模板的效果,这里面的相应.cs文件等也需要修改。模板改起来相当直接,一看便知,比如新建Form的模板:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;

    namespace $rootnamespace$
    {
        
    public partial class $safeitemrootname$: Form
        
    {
            
    public $safeitemrootname$()
            
    {
                InitializeComponent();
            }

        }

    }


    接下来说说Code Snippet,这个东东被MSDN吹得有点大,不过用起来实在有些不顺手,你虽然可以定义一大块代码片断,然后填一些参数,就能得到一个定制的代码段,但是毕竟你还是需要自己写很多东西,然后使用的话需要在代码编辑器里面点很多下才出来,又没有很好的快捷方式。不客气地说我觉得用Code Snippet来模拟Eclipse的很多现成的重构功能实在不能够体现出优势。退一万步讲,有总比没有强,至少你还是可以做一些东西的。使用现成的Code Snippet很简单,只要把VS指向你存放Code Snippets的目录即可,新的Code Snippets会被自动扫描到。方法是:Tools -> Code Snippets Manager或者Ctrl-K Ctrl-B然后添加目录名。所有的Code Snippets文件都以.snippet后缀结尾,其实内部是个XML,像这个样子:

    <?xml version="1.0" encoding="utf-8" ?>
    <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
      
    <CodeSnippet Format="1.0.0">
        
    <Header>
          
    <Title>Insert a simple set of getter and setter pair</Title>
          
    <Author>Sean GAO</Author>
          
    <Description></Description>
          
    <Shortcut>simplisticGetterSetter</Shortcut>
          
    <SnippetTypes>
            
    <SnippetType>Expansion</SnippetType>
          
    </SnippetTypes>
        
    </Header>
        
    <Snippet>
          
    <Declarations>
            
    <Literal>
              
    <ID>AccessLevel</ID>
              
    <ToolTip></ToolTip>
              
    <Default>public</Default>
            
    </Literal>
            
    <Literal>
              
    <ID>PropertyType</ID>
              
    <ToolTip></ToolTip>
              
    <Default>string</Default>
            
    </Literal>
            
    <Literal>
              
    <ID>PropertyName</ID>
              
    <ToolTip></ToolTip>
              
    <Default>name</Default>
            
    </Literal>
            
    <Literal>
              
    <ID>LocalVarName</ID>
              
    <ToolTip></ToolTip>
              
    <Default>localVar</Default>
            
    </Literal>
          
    </Declarations>
          
    <Code Language="csharp">
    <![CDATA[        $AccessLevel$ $PropertyType$ $PropertyName$
            {
                get { return $LocalVarName$; }
                set { $LocalVarName$ = value; }
            }
    ]]>
          
    </Code>
        
    </Snippet>
      
    </CodeSnippet>
    </CodeSnippets>

    我们可以看到,首先在.snippet中我定义了一些变量,然后在<Code/>段加入了<![CDATA[...]]>,就这么简单。

    最后,还剩一些具体的工具,选择面比较广,我只列举一下我都选了哪些:
    - 代码review和分析工具:FxCop,可以在GotDotNet网站上下载:http://www.gotdotnet.com/team/fxcop/ 。
    - 自动编译管理:NANT和CruiseControl.NET:http://nant.sourceforge.net/ 和 http://ccnet.thoughtworks.com/ 。
    - 缺陷跟踪:mantis:http://www.mantisbt.org/ 。
    - 文档管理: jLibrary:http://jlibrary.sourceforge.net/ 。
    - 版本控制:CVSNT和Eclipse SDK:http://www.cvsnt.org/ 和 http://eclipse.org/

    暂时就是这么多,如果你和我一样从Java转向.NET,然后正在犯愁如何做一个.NET项目的前期准备,希望能给你一些参考。

    posted @ 2006-04-01 17:04 laogao 阅读(4060) | 评论 (1)编辑 收藏


    You are what you read.

    我们经常会看到这样的说法,直译过来就是:你读什么,你就是什么。言下之意,如果你什么也不读,当然就什么也不是。不难理解,我们的阅读习惯和阅读的东西在很大的程度上都会影响我们的价值观和判断力,进而也会影响到我们的为人处事。所以说,通常如果了解了一个人的阅读喜好,也就在很大程度上了解了这个人。比方说,很多人物传记中,我们都能看到某某伟人喜欢的作者和书等等,传记的作者则在此基础上推衍出这个伟人的方方面面。我想,这就是上面这句话的本意,当然,在现代社会,这个read也许已经不仅仅指读书了。

    posted @ 2006-03-30 12:25 laogao 阅读(909) | 评论 (2)编辑 收藏


    大家最近大概都已经听说了Windows Vista延期的消息。纽约时报的记者和编辑们当然也没有闲着,Windows Vista为什么一再推迟,当初承诺的很多远景为什么最终没有实现或者说最终被取消,以及Windows本身是不是存在一些难以克服的内在约束,这篇文章尝试回答上面这些问题(跟我很多想法都不谋而合):

    http://www.nytimes.com/2006/03/27/technology/27soft.html



    posted @ 2006-03-29 00:29 laogao 阅读(853) | 评论 (0)编辑 收藏


    到新公司上班已经快一个月了,这一次对我来说,是机遇,也是挑战。又回到了这个熟悉而又陌生的城市,很多身边的人和事,甚至自己,都在慢慢的发展和变化中。一个月以来,杂七杂八的事情很多,在BlogJava的随笔也更新得慢了,不过当一切步入正轨,我还是会继续为大家提供越来越多的原创文章和新闻链接,希望不会令喜欢我blog的朋友们失望。

    说到具体的变化,大大小小的都有。首当其冲的当然是工作环境变了,从一个城市到另一个城市,从一个公司到另一个公司,虽然有很多同事之前就一直认识,从事的行业也是自己比较熟悉的,但是毕竟是一个全新的环境,饮食起居也和前面两年的悠闲适宜形成了鲜明的反差。甚至一向都很喜欢和习惯的Bloglines也改成了NewsGator。原因么,一方面我的一个朋友很早以前就向我推荐过这个NewsGator,另一方面,不知道是不是地域的差异,这边访问Bloglines很慢,加上Bloglines本身的特点,很容易在浏览时超时,丢掉一些可能对你有意义的feed,在这一点上,NewsGator做的更好。

    从一个侧面,我们也可以看到ASP.NET在Web应用上,可以带个我们的东西,其实很多,类似NewsGator这样的ASP.NET站点,包括我们的博客园和BlogJava在内,我相信应该已经有相当大的数量。了解我的朋友大约都知道,我对.NET是一种又爱又恨的感觉,加上在Java阵营待的时间很久了,多多少少对.NET还是有些偏见,也很少有多余的时间去全面的学习.NET。我接下来这个新的项目将是基于.NET的,这就给我一个相当好的机会更加真实的去重新认识.NET。看来接下来这段日子不可避免要双修了。;)

    昨天看Anders Hejlsberg的专访,给我印象最深的,是他的率真、务实和对编程的热忱。同时我也看到了Visual J++和C#、.NET背后的内在驱动力,其实和Eclipse背后的那股力量有着某种相似:We're not focused on hurting them, we're focused on helping us. (引用Eclipse Foundation的Mike Milinkovich)

    这段采访视频可以在这里看到:
    http://channel9.msdn.com/ShowPost.aspx?PostID=159952#159952

    posted @ 2006-03-26 13:49 laogao 阅读(2597) | 评论 (6)编辑 收藏


    SearchOpenSource.com上有一篇文章,标题是你不应该使用PostgreSQL的五条理由。当然了,作者是在澄清为什么PostgreSQL虽然大家看到很多评论在技术上都超出MySQL,实际应用中却没有看到大规模的人转向PostgreSQL。作者举出了五条最常听到的原因,并一一解释和澄清了一番。

    原文链接:
    http://searchopensource.techtarget.com/originalContent/0,289142,sid39_gci1172668,00.html

    posted @ 2006-03-19 15:51 laogao 阅读(959) | 评论 (2)编辑 收藏


    http://www.gnome.org/


    posted @ 2006-03-17 12:41 laogao 阅读(716) | 评论 (0)编辑 收藏


    由于主站博客园维护,BlogJava也停了一段时间。今天发现自己在Bloglines上的RSS出现了很多其他人的文章,想必是昨天维护留下的吧。;)


    posted @ 2006-03-16 10:20 laogao 阅读(699) | 评论 (0)编辑 收藏


    挺有趣的一篇文章,推荐阅读。
    http://management.itmanagersjournal.com/article.pl?sid=06/03/06/1731240


    posted @ 2006-03-14 14:04 laogao 阅读(1046) | 评论 (0)编辑 收藏


    你今天Flickr了吗?下面这个网站可能对你有些用处:

    http://www.houserdesign.com/flickr/


    它可以根据不同的搜索条件,找出最符合要求(如:某一天中最多人觉得有趣的500张)的照片,并把它们列在一起方便浏览。


    posted @ 2006-03-11 19:11 laogao 阅读(754) | 评论 (0)编辑 收藏


    首先是ExtremeTech发表了一篇对Vista充满期待的评论文章:
    http://www.extremetech.com/article2/0,1697,1931914,00.asp

    然后DesktopLinux.com上争锋相对泼冷水的:
    http://www.desktoplinux.com/articles/AT8288296398.html

    到底Vista会怎样,恐怕还是只有等出来了才知道。


    posted @ 2006-03-02 14:30 laogao 阅读(835) | 评论 (0)编辑 收藏


    GNOME 2.14即将于3月15日正式发布,是时间看看它的新特性了:
    http://www.gnome.org.nyud.net:8080/~davyd/gnome-2-14/


    posted @ 2006-02-21 12:55 laogao 阅读(660) | 评论 (0)编辑 收藏


    EclipseZone上有一篇文章,讲的是作者关于Eclipse作为一个ecosystem的一些见解:
    http://www.eclipsezone.com/eclipse/forums/t64080.rhtml

    比较有意思的一个比喻是这样说的:
    "IBM has effectively created a digital snowball that is rolling down a mountain, and there are all these other snowballs that want to roll down the mountain too. They are certainly welcome to start rolling on their own, but they will never get as big or as fast as the IBM (Eclipse) snowball because it started at the top of the mountain. So instead the other snowballs just roll themselves into the big IBM snowball. They won't effect the ultimate path of the big snowball very much, but they can change it just enough to meet their needs which is what they wanted AND what IBM wanted too."


    posted @ 2006-02-18 01:32 laogao 阅读(874) | 评论 (1)编辑 收藏


    "可持续发展"是近年来出现率颇高的一个词,知道用英语怎么说吗?是"sustainable development"。

    放在真实的语境中,如"... the government's newly stated emphasis on seeking sustainable development after years of breakneck growth."


    posted @ 2006-02-16 00:44 laogao 阅读(713) | 评论 (0)编辑 收藏


    这是一篇纽约时报的新闻稿,对2006都灵冬奥会上张丹/张昊的表现和最终的银牌给出了很高的评价,推荐阅读:
    http://www.nytimes.com/2006/02/14/sports/olympics/14pairs.html

    摘录:
    "They skated to a silver with a moment that will be remembered longer than the golden one."


    posted @ 2006-02-15 11:41 laogao 阅读(765) | 评论 (0)编辑 收藏


    Oracle支持Eclipse,不过看来并不是那么全心全意,在大多数人都以为Oracle要将JDeveloper基于Eclipse的时候,我们突然发现自己错了:

    http://www.eclipsezone.com/eclipse/forums/t63839.rhtml


    posted @ 2006-02-15 02:28 laogao 阅读(818) | 评论 (0)编辑 收藏


    http://www.unixguide.net/linux/linuxshortcuts.shtml


    posted @ 2006-02-14 11:58 laogao 阅读(898) | 评论 (1)编辑 收藏


    据报道,Google正在和CodeWeavers合作,将Picasa完整移植到Linux平台,严格讲并不是100%的移植,而是把原来的Picasa代码和Wine绑在一起,但这对用户来说是透明的。Linux版Picasa将具有完整的Picasa 2.x功能。

    链接:
    http://www.desktoplinux.com/news/NS9556554213.html

    另外文中还提到Google雇用了GAIM的核心开发Sean Egan,估计Google Talk离Linux版本也不远了。


    posted @ 2006-02-14 11:50 laogao 阅读(745) | 评论 (0)编辑 收藏


    JBoss不用说了,Zend主要是PHP,Sleepycat主要是一些开源的数据库,尤其是内存式数据库。

    新闻链接:
    http://www.businessweek.com/technology/content/feb2006/tc20060209_810527.htm


    posted @ 2006-02-10 22:35 laogao 阅读(705) | 评论 (1)编辑 收藏


    根据英国Register的报道,Halo 2的PC版本将只能运行在Windows Vista上,微软想重复当年用一款游戏推动XBOX销量的把戏?

    新闻链接:
    http://www.reghardware.co.uk/2006/02/10/ms_halo_2_windows_vista/


    posted @ 2006-02-10 21:29 laogao 阅读(441) | 评论 (0)编辑 收藏


    在IT部门,我们也许经常会遇到同其他市场/销售部门之间的沟通和配合存在问题,时间长了,很容易在这样两个不同的部门之间产生不信任,有时甚至是IT部门和公司其他所有部门之间的不信任,导致IT项目失败,投资无法挽回的局面。更糟的是,如果这种趋势如果不能及时得到纠正,IT部门的日子将很不好过,陷入恶性循环:领导层鉴于看不到IT部门的业绩,不愿意对IT追加投资,IT得不到应有的重视,没有资金,无法创造更多更好的业绩,像哑巴吃黄莲一样扮演着替罪羊的角色。

    作为有原则、有责任心的IT经理,我们必须清晰的认识到这个问题,摸清它的来龙去脉,切实的行动起来,去寻求解决它的途径。

    这里有一篇文章值得一读:
    http://management.itmanagersjournal.com/article.pl?sid=06/02/08/1556259

    基本上这篇文章没什么生僻字,唯独解释一下这个词:

    ombudsman

    按照Merriam-Webster的解释,an ombudsmam is "one that investigates reported complaints (as from students or consumers), reports findings, and helps to achieve equitable settlements".


    posted @ 2006-02-10 17:24 laogao 阅读(354) | 评论 (0)编辑 收藏


    以下是Google Toolbar (Firefox)的主页:
    http://toolbar.google.com/firefox/index.html


    posted @ 2006-02-10 16:45 laogao 阅读(363) | 评论 (0)编辑 收藏


    F-Spot (类似Picasa的照片管理工具)
    http://www.gnome.org/projects/f-spot/

    Tomboy (桌面报事贴工具)
    http://beatniksoftware.com/tomboy/


    posted @ 2006-02-08 18:45 laogao 阅读(573) | 评论 (0)编辑 收藏


    "Why offshoring fails":
    http://management.itmanagersjournal.com/article.pl?sid=06/02/02/2135206

    "Five reasons why offshore deals go bust":
    http://www.computerworld.com/managementtopics/outsourcing/story/0,10801,102677,00.html


    posted @ 2006-02-08 18:35 laogao 阅读(701) | 评论 (0)编辑 收藏


    之前我提到过automatix,这里还有一些tips for Firefox and OpenOffice.org:

    http://lxer.com/module/newswire/view/53395/index.html


    posted @ 2006-02-08 18:24 laogao 阅读(426) | 评论 (0)编辑 收藏


    http://www.novell.com/linux/xglrelease/


    posted @ 2006-02-08 16:31 laogao 阅读(392) | 评论 (1)编辑 收藏


    这儿有一篇挺有意思的文章,告诉你Apple从PowerPC转向Intel背后的故事:

    http://macslash.org/article.pl?sid=06/02/06/1654252


    posted @ 2006-02-08 16:06 laogao 阅读(383) | 评论 (0)编辑 收藏


    最近把工作环境换成了Ubuntu 5.10,感觉还不错。一开始觉得没有SuSE方便,因为有很多feature还需要自己去找去安装,不象SuSE那样随盘带了很多工具,包括KDE、MONO、GCC等等,用了一段时间,逐渐体会到Debian系统独有的包管理优势,大部分时候只需要apt-get install一下就搞定,卸载也就是简单的apt-get remove,很elegant,不用去关心包依赖性之类了。

    先废话到这儿,这里跟大家讲一讲如何从Ubuntu访问本地硬盘的NTFS分区。

    默认设置下面,如果你安装的是双系统,Windows分区是用NTFS格式化的,那么你会沮丧的发现,在Ubuntu下面,你无法访问你原来Windows下面的文件,也无法修改这些分区和其挂载点的只读属性,dr-x------ root root,其实还不是简单的只读,而是“不可读”,你连有哪些目录都看不到,基本无法访问,连root账号也无济于事。怎么办?其他Linux发行版是可以访问到NTFS的啊。是的,一定是什么地方可以设置的。

    Ubuntu默认是把非Linux分区mount到/media目录下,如/dev/hda1默认是挂到/media/hda1。假定你的NTFS分区是hda1(通常你安装Windows的时候,那个C盘,对应过来就是hda1,意思是,第一块硬盘的第一个分区),执行下面的步骤:

    # sudo -s
    password:
    # mkdir /media/C
    # gedit /etc/fstab

    找到/dev/hda1对应的那一行,把<mount point>一项由"/media/hda1"改为"/media/C";把<options>一项由"defaults"改为"umask=0222";保存;退出。

    # umount /media/hda1
    # mount /dev/hda1
    # exit

    桌面上原来的hda1变成了C,再次尝试访问,这下就可以看到NTFS分区的文件了。:) 不过由于NTFS本身的一些约束和限制,目前从Linux系统往NTFS分区写数据还很不稳定,所以几乎所有的Linux发行版都不支持对NTFS格式分区的写操作,所以现阶段就不必费心去找解决方案了。


    posted @ 2006-02-05 13:59 laogao 阅读(6471) | 评论 (1)编辑 收藏



    http://www.developer.com/java/other/article.php/3576286

    节选如下:

    Technology of the Year:
    AJAX From Mozilla Developer Center

    Framework of the Year:
    JavaServer Faces From Sun Microsystems Inc.

    Development Tool of the Year:
    Eclipse From the Eclipse Foundation

    Development Utility of the Year:
    Ant From The Apache Software Foundation

    Web Service Product of the Year:
    Google APIs From Google Inc.

    Wireless/Mobile Development Tool or Add-in of the Year:
    J2ME™ Wireless Toolkit From Sun Microsystems Inc.
    (Runner up)
    Sybase® PocketBuilder 2.0 From Sybase Inc.

    Database Tool or Add-in of the Year:
    MySQL 5.0 From MySQL AB

    Java Tool/Add-in of the Year:
    Sun Java™ Studio Creator By Sun Microsystems Inc.

    JSR (Java Specification Request) of the Year:
    JSR 244: Java EE 5.0

    .NET Tool or Add-in of the Year:
    Microsoft® Visual Studio® 2005 From Microsoft Corporation
    (The Winning Non-Microsoft product:)
    Mono .NET Framework From mono-project.com

    Security Tool or Add-in of the Year:
    Sun Java System Identity Manager From Sun Microsystems Inc.

    Open Source Tool of the Year (Tie):
    OpenOffice 2.0 From OpenOffice.org and
    Firefox From Mozilla Foundation


    posted @ 2006-02-04 01:15 laogao 阅读(299) | 评论 (0)编辑 收藏


    http://trends.newsforge.com/article.pl?sid=06/02/02/1636216


    posted @ 2006-02-04 01:04 laogao 阅读(311) | 评论 (0)编辑 收藏


    "So, first of all, let me assert my firm belief that the only thing we have to fear is fear itself—nameless, unreasoning, unjustified terror which paralyzes needed efforts to convert retreat into advance."
    - Franklin D. Roosevelt

    以上的这段文字是美国前总统罗斯福在1933年的总统就职演讲上说的一段话,其中"the only thing we have to fear is fear itself" (唯一值得恐惧的是恐惧本身) 这个部分经常被后人引用。当时美国经济正处于大萧条,罗斯福就任以后首先要做的一件事就是消除人们的恐惧,让美国人重新找回自信,渡过难关。

    这里有罗斯福这次就职演说的全文:
    http://www.bartleby.com/124/pres49.html

    posted @ 2006-02-02 14:46 laogao 阅读(349) | 评论 (0)编辑 收藏


    http://www.eclipsezone.com/eclipse/forums/t62966.rhtml

    posted @ 2006-02-02 13:48 laogao 阅读(799) | 评论 (0)编辑 收藏


    刚在ComputerWorld上看到的消息,包括IBM、BEA、Borland、Oracle、Novell、Red Hat在内的数家大厂将合力推广AJAX的应用,这当中包括了IBM前不久向Eclipse Foundation递交的ATF建议书。

    http://www.computerworld.com/developmenttopics/development/story/0,10801,108264,00.html

    posted @ 2006-02-02 01:09 laogao 阅读(643) | 评论 (0)编辑 收藏


    不出预料,有关Google向公众推出自己的OS的传言再次被Google否认。参考
    http://www.blogjava.net/sean/archive/2006/02/01/29434.html
    不过也不算是全盘否认,至少Google内部使用Ubuntu这一点得到了证实。

    链接:
    http://arstechnica.com/news.ars/post/20060131-6087.html

    posted @ 2006-02-02 00:58 laogao 阅读(630) | 评论 (1)编辑 收藏


    记得前天刚告诉大家IBM将推出DB2的免费版:
    http://www.blogjava.net/sean/archive/2006/01/31/29387.html
    今天已经看到官方消息。

    链接:
    http://www-306.ibm.com/software/data/db2/udb/edition-expressc.html

    posted @ 2006-02-02 00:48 laogao 阅读(276) | 评论 (0)编辑 收藏


    Mozilla Foundation早已把自己的focus放在了Firefox和Thunderbird上,并且宣布不再大规模升级原来的Mozilla,不过原先的Mozilla套件演化并没有完全终止,只不过是交给了开源社区,现在,Mozilla套件衍生出了新的版本:SeaMonkey 1.0,包括浏览器、E-mail客户端、网页编辑器、IRC、DOM、JavaScript调试工具等,不知这个SeaMonkey前景如何,在如今大家都在用IE/Outlook或者Firefox/Thunderbird的年代,甚至越来越多的人已经开始接纳Web 2.0,我们真的还需要另一款Netscape血统的浏览器套件?

    新闻链接:
    http://www.eweek.com/article2/0,1895,1917213,00.asp

    posted @ 2006-02-02 00:39 laogao 阅读(282) | 评论 (0)编辑 收藏


    Never judge a book by its cover. 不要以貌取人。(不要以一本书的封面好坏来判断书的好坏)

    这是一句经常可以看到的格言,而且也经常被篡改成其他近似的说法,来表达一些特定的意思,Google一下,得到很多这样的句子:
    Never judge a day by its weather. (气象服务)
    Never judge a man by his T-shirt. (服装店)
    Never judge a mobile phone by its cover. (手机门户)
    Never judge a woman by the size of her shoes. (卖鞋的)
    Never judge an auction by its cover. (eBay / 还记不记得上次有人天价买掉XBOX 360...的照片?)

    这个最有意思:
    Never judge a book by its movie.

    是啊,我们已经看到很多由原著的书改编的电影,有多少真正忠于原著,甚至接近原著的高度呢?寥寥无几。出现这样的改编格言,也就相当耐人寻味了。

    posted @ 2006-02-01 21:50 laogao 阅读(381) | 评论 (0)编辑 收藏


    Linux对于一般的用户而言,最容易遇到的是诸如如何播放MP3、DVD、流媒体、安装字体、nVidia显卡驱动、Java、更新的Firefox和插件等等。有人做了一个方便易用的小工具帮你完成这些,只需要执行下面的两行命令来安装:

    wget http://beerorkid.com/automatix/automatix-ubuntu_4.4-2_i386.deb
    sudo dpkg -i automatix-ubuntu_4.4-2_i386.deb

    原文见:
    http://www.pcworld.com/reviews/article/0,aid,124519,00.asp


    //=======更新一下=======

    上面提到的那个下载链接已经失效,请使用以下命令:

    wget http://beerorkid.com/automatix/automatix_5.1-1_i386.deb
    sudo dpkg -i automatix_5.1-1_i386.deb

    posted @ 2006-02-01 15:08 laogao 阅读(622) | 评论 (1)编辑 收藏


    从去年下半年开始,关于Google会推出自己的OS的传闻就一直不断,Google官方也曾经否认过类似传言,但是今天在News.com和The Register上看到的报道却是有板有眼的,"Goobuntu"?

    http://news.com.com/2061-10812_3-6033533.html
    http://www.theregister.co.uk/2006/01/31/google_goes_desktop_linux/

    posted @ 2006-02-01 14:39 laogao 阅读(403) | 评论 (0)编辑 收藏


    如果你是一个IT经理人,那么你也许已经知道什么是performance review,或者一些相关的概念,如KPI - Key Performace Indicators。然而我们经常看到国内外众多IT公司对这一块的重视程度远远不够,很多时候大多数公司的做法都是象征性的做一下年度评估,缺乏明确和统一的目标和标准,被评估的人拿到评估结果容易产生疑惑,而参与评估的项目经理们往往也很头痛,有时候甚至不得不根据上层领导的指示(或者理解为公司实际情况)人为的做一些分数调整。

    如果你是一个负责任的IT Manager,那么你应该可以看到这样敷衍performance review的做法对你所领导的团队带来的负面影响:最具破坏力的当属管理层和执行层之间的不信任,这将严重影响团队的士气和公司氛围,日常的工作开展也将受到牵制,团队整体表现下降。这样的不信任加上沟通的缺乏,最终也很可能造成原本不必要的人才流失。

    有时间可以静下心来读一读这篇文章,重新审视一下我们对待performance review的态度和方式方法:
    http://management.itmanagersjournal.com/article.pl?sid=05/12/22/2122200

    posted @ 2006-01-31 13:06 laogao 阅读(684) | 评论 (0)编辑 收藏


    如果你所在的IT服务公司想要为你的客户提供更好的服务,了解客户的真正需求是绝对必要的,当你面对的是大型的企业,如银行、交通、物流或者医院等,你要打交道的往往是它们的IT部门,就像其他很多公司的IT部门一样,这些大企业的IT部门也是需要完成一定业绩的,只不过这样的业绩往往难以衡量,造成企业对其IT部门的误解或者不重视,直接影响我们自己的项目实施和市场开拓。这就需要我们站在他们的立场上,找出这些IT部门如何能够为他们所在的那个更大的企业创造更多的价值,如何在企业中定位,切实的让这些企业感受到IT带给他们的价值和value-add,我们和这些客户的合作空间也就自然会更大。

    有时间的话,可以看看这篇文章,站在企业的IT部门的角度:
    http://www.computerworld.com/managementtopics/management/story/0,10801,107988,00.html

    posted @ 2006-01-31 02:06 laogao 阅读(294) | 评论 (0)编辑 收藏


    Berkeley DB的大名相信很多人多少有所耳闻,它还有个留着Java血液的同胞:Berkeley DB Java Edition。今天,Berkeley DB的缔造者SleepyCat推出了Java Edition的2.1版。Berkeley DB的最大特点就是它随应用程序一起运行,通常作为应用程序的一部分,提供数据持久化和查询等功能,避开独立运行的数据库安装和性能上的问题,这在某些特定的应用中十分有用。

    详见:
    http://www.sleepycat.com/products/bdbje.html

    posted @ 2006-01-31 00:42 laogao 阅读(484) | 评论 (0)编辑 收藏


    也许是受到来自开源的压力,IBM在推出Community Edition的WebSphere之后,又将推出免费的DB2,不限用户数和数据大小,支持双CPU和4GB内存,同时提供可选的收费服务。比起MS的SQL Server 2005 Express Edition和Oracle的10g Express要更进一步,这两家的免费版都限制在1 CPU + 1G 内存。

    对于广大开发者来说,又多了一个不错的数据库选择。

    消息来源:
    http://www.eweek.com/article2/0,1759,1916097,00.asp

    posted @ 2006-01-31 00:28 laogao 阅读(424) | 评论 (0)编辑 收藏


    Google Toolbar相信很多人都作为一个必需的IE插件安装,为我们的互联网浏览提供了很多方便。也许你还没注意到,Google Toolbar已经推出了for Firefox的版本,另外,新的Beta也已经可以试用了:

    http://www.google.com/tools/toolbar/T4/index.html

    新的功能包括:添加按钮、书签、搜索建议、发送Gmail/Blogger/SMS等,还是有很多改进的哦。

    posted @ 2006-01-31 00:08 laogao 阅读(261) | 评论 (0)编辑 收藏


    最近学习一些开源项目,无奈很多都是在SourceForge安家的,而我经常打不开他们给出的SourceForge下载页面,不知是DNS的原因,还是链接没有及时更新,反正不是很爽啦。今天发现一个方法,记录下来给需要的朋友分享:

    http://prdownloads.sourceforge.net/xxxxxxx/

    我们可以记住这个地址,把"xxxxxx"换成需要的项目名称即可看到所有相关的文件清单,如iBATIS SQLMap叫"ibatisdb",SQLExplorer插件是"eclipsesql",QuantumDB插件的名称是"quantum",等等。这些名字虽然因为SourceForge主页打不开无法直接找到,还是可以从Google搜索结果很容易查到的。

    posted @ 2006-01-30 16:58 laogao 阅读(4894) | 评论 (2)编辑 收藏


    如果你和我一样,喜欢Eclipse和它的WTP,同时也对Geronimo感兴趣,那么当你把WTP 1.0和Geronimo 1.0的正式发行版本拿到以后,一定会感到迷惑,为什么WTP 1.0不直接支持Geronimo 1.0呢?当你尝试添加Geronimo服务器时,首先是找不到现成的Geronimo选项,然后当你点击"Don't see your server listed? Click here",你会看到Geronimo的适配器可以下载,但是却怎么也下不下来。

    不管是之前的Milestone版本,还是网上很多评价,WTP应该都是直接支持Geronimo的啊,到底发生了什么?

    到Geronimo官网的Development Tools页面,可以找到部分答案,有一点可以肯定,你的WTP不支持Geronimo并非版本差异的偶然现象。Geronimo的Eclipse WTP适配器目前还没有正式发布,笔者猜测可能是还存在一些不稳定的地方,不适合包含在WTP 1.0这个重要的发行版本中。

    http://geronimo.apache.org/devtools/

    我们可以在Apache的CVS上找到下面的snapshot下载列表,正式的发布应该不会让大家等太久的:
    http://cvs.apache.org/dist/geronimo/eclipse/unstable/

    posted @ 2006-01-30 15:30 laogao 阅读(513) | 评论 (0)编辑 收藏


    "When I do good, I feel good; when I do bad, I feel bad, and that is my religion."
    - Abraham Lincoln

    这是林肯的一句名言,被无数人当作座右铭。每个人心中都有自己的一杆秤,什么是好的,什么是不好的,就好像心里始终有一个声音在告诉你什么是对什么是错。通俗且不严谨的来理解,在东方文化里面,这个声音叫作良知,在西方,至少是我认识的那个西方,人们习惯叫它上帝。

    posted @ 2006-01-30 13:55 laogao 阅读(315) | 评论 (0)编辑 收藏


    最近大家都忙着过年,但是也别错过了这个消息。如果感兴趣,就去官网上下吧。

    http://www.eclipse.org/downloads/

    posted @ 2006-01-29 15:39 laogao 阅读(617) | 评论 (1)编辑 收藏


    "Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away."
    - Antoine de Saint-Exupery

    Antoine de Saint-Exupery是20世纪法国作家,著有《小王子》一书得以成名。上面这段话很有意思:什么时候才算达到完美?并不是无法再添加更多的东西,而是已经没有剩下什么可以再去掉的了。

    posted @ 2006-01-29 15:26 laogao 阅读(274) | 评论 (0)编辑 收藏


    NASA纽约Goddard太空研究所最新的研究报告显示,2005年,全球表面温度再创新高,超过1998年,成为自19世纪末有准确温度记录以来最热的一年。2005年我们并没有遇到1998年那样的厄尔尼诺现象,所以这是否意味着全球气候变暖正在加剧?

    http://data.giss.nasa.gov/gistemp/2005/

    posted @ 2006-01-26 21:49 laogao 阅读(342) | 评论 (0)编辑 收藏


    http://docs.codehaus.org/display/YAN/Spring%2C+Pico+and+Nuts+Compared

    Spring不用多说,名头最响的IoC容器,但是是否我们也需要了解一下其他的IoC容器如PicoContainer和Spring的差别呢?上面给出的链接是网友做的简单对比,不求100%完整和准确,但是可能对需要做产品选型的朋友提供些参考。需要注意的是Spring远不止IoC这么简单,它包括了完整的Spring DAO, AOP, Spring MVC等等,这里的对比仅限于IoC这一块。

    posted @ 2006-01-26 21:29 laogao 阅读(334) | 评论 (0)编辑 收藏


    下面是两个Java Web Start的链接,区别是使用的Open GL的库不同,Windows推荐用第一个,Linux推荐用第二个,也可以两个都尝试一下。给我的感觉还是比较慢,也许是我机器配置稍低了些,不过比起native的Quake II,确实差了很多,用Java做3D看来还需要更多的优化才行。

    http://www.bytonic.de/downloads/jake2_jogl11.jnlp
    http://www.bytonic.de/downloads/jake2_lwjgl.jnlp

    更详细的说明参考:
    http://www.bytonic.de/html/jake2_webstart.html

    posted @ 2006-01-26 21:22 laogao 阅读(468) | 评论 (0)编辑 收藏


    http://linux.about.com/od/linux101/a/desktop06.htm

    posted @ 2006-01-26 16:08 laogao 阅读(203) | 评论 (0)编辑 收藏


    http://www.linux.com/article.pl?sid=05/11/18/1721201

    posted @ 2006-01-26 16:01 laogao 阅读(227) | 评论 (0)编辑 收藏


    默认XP下面用javaw.exe执行的图形界面使用的都是古老的Windows风格,为了发挥SWT这样的本地控件库的优势,可以考虑使用http://eclipse.org/swt/javaw.exe.manifest文件,拷贝到javaw.exe文件所在的目录,默认是Windows安装目录的system32子目录,然后再运行SWT应用,如Eclipse。

    原文:
    http://www.eclipsezone.com/eclipse/forums/t61545.rhtml
    (Thanks, Vineet!)

    posted @ 2006-01-22 21:37 laogao 阅读(769) | 评论 (3)编辑 收藏


    有时候,我们也许可以静下心来,看一些英文的原版文章,尤其是IT方面的(谁让我们身为IT人呢),既了解IT动态,又可以培养英语语感。也许你觉得这样的文章很多,不知从何下手,那不妨经常来我的blog坐坐,我时不时会贴一些我觉得有意思的文章链接,作为闲暇读物。

    这里有一篇关于微软的:
    http://www.slate.com/id/2133993/

    posted @ 2006-01-22 20:49 laogao 阅读(491) | 评论 (2)编辑 收藏


    http://www.eweek.com/article2/0,1759,1906177,00.asp

    简单的说,就是Windows的.wmf文件存在漏洞,可能会受到病毒攻击,哪怕你用2003打到最新补丁(暂时)也不行,解决办法是不要打开.wmf文件,或者运行:

    regsvr32 -u %windir%\system32\shimgvw.dll

    注销这个DLL。


    posted @ 2005-12-31 16:22 laogao 阅读(375) | 评论 (0)编辑 收藏


    http://www.dpreview.com/news/0512/05122801leicamdigital.asp

    这个消息对于无数Leica迷意味着什么?


    posted @ 2005-12-29 21:03 laogao 阅读(387) | 评论 (0)编辑 收藏


    昨天败了台F80,上点试机片给大家看看:(扫描仪不好,只好后期多调整,但愿没有矫枉过正)

    - 1 -


    - 2 -


    - 3 -


    - 4 -


    posted @ 2005-12-29 17:08 laogao 阅读(4251) | 评论 (8)编辑 收藏


    详情参阅:
    http://www.eclipse.org/org/press-release/20051219wtp10release.php


    posted @ 2005-12-20 00:14 laogao 阅读(1244) | 评论 (3)编辑 收藏


    在BoingBoing上看到这条有意思的文章:
    http://www.boingboing.net/2005/12/16/mona_lisas_emotions_.html

    标题叫做"Mona Lisa's emotions decoded",科学家通过新的软件分析,得出的结论是,蒙娜丽莎的微笑中,带有83%的快乐、9%的厌烦、6%的害怕、和2%的愤怒。

    我在想,如果科技像这样发展下去,直到有一天什么东西都是确凿的一个或一堆数字,留给人们的想象空间还有多少?


    posted @ 2005-12-18 02:10 laogao 阅读(544) | 评论 (0)编辑 收藏


    http://www.eclipsezone.com/eclipse/forums/t59446.rhtml

    我得承认,Ed Burnette确实挺有想象力的,不过这些大公司背后存在的"暗流"(利益冲突)也许决定了它们很难走到一起吧,就像很多人无法理解Sun为何"一意孤 行"一定要搞自己的一套。说到这有些伤感,Java是我很喜欢的语言/平台,但是近年来发生的一系列事情,让我看到这个Java社群陆续出现了很多各自为 政的派系,往好了说,这是百家争鸣,往坏了说,这是Java帝国内部的分裂。很难说这是好事还是坏事,姑且把它当作咖啡与生俱来的"苦"吧。

    其实也不能把责问一味的往Sun身上放,把前一句中的"Sun"换作"IBM"或者"微软",同样make sense,不是吗?只不过我感觉在IBM/Sun/MS这场较量中,Sun无疑处在下风。

    // 思路有点混乱,将就看,呵呵。我都不晓得自己make不make sense,还在这儿高谈阔论别人make不make sense,明白的朋友请多多包涵了。


    posted @ 2005-12-18 01:45 laogao 阅读(500) | 评论 (0)编辑 收藏


    让图自己来说话吧:

    - 1 -



    - 2 -



    - 3 -



    posted @ 2005-12-13 01:23 laogao 阅读(995) | 评论 (3)编辑 收藏


    详见:
    http://www.apache.org/dist/httpd/Announcement2.2.html


    posted @ 2005-12-03 23:32 laogao 阅读(507) | 评论 (0)编辑 收藏


    接上一篇随笔
    http://www.blogjava.net/sean/archive/2005/11/22/20928.html

    再来一张:

    DSC00543ssc.jpg

    posted @ 2005-11-22 13:44 laogao 阅读(569) | 评论 (2)编辑 收藏


    周末逛器材,发现这只口碑不错的Canon原厂镜头,EF 28-105mm F/3.5-4.5 II USM,把手头的SIGMA 28-70mm F/2.8 EX出手了,换成了原厂头,感觉素质很好,对焦快且准,还很安静,毕竟原厂的USM超声波马达,全时手动对焦,同等焦段它在不少网站上的评分仅次于L系列,现在二手市场售价1000元左右,相当超值。

    DSC00537ssc.jpg

    上图为F-717在光圈2.4、快门1/60下拍摄,室内灯光,简易布景(其实就是在茶几上铺上3x4张A4复印纸,吊灯全开,侧面用反光板略微部一些光)。

    posted @ 2005-11-22 12:46 laogao 阅读(929) | 评论 (6)编辑 收藏


    SONY这次闹得沸沸扬扬的rootkit事件又有了新的花边:
    http://www.theregister.co.uk/2005/11/18/sony_copyright_infringement/

    意在保护版权的软件自身就侵犯了别人的版权,这个玩笑开大了吧?


    posted @ 2005-11-18 23:10 laogao 阅读(441) | 评论 (0)编辑 收藏


    这个消息多少来的有点突然:
    http://football.guardian.co.uk/News_Story/0,1563,1645805,00.html


    posted @ 2005-11-18 23:01 laogao 阅读(482) | 评论 (0)编辑 收藏


    我们经常可以看到我们的各式各样商品包装上所带的条形码,那些像斑马线一样的东西是如何被编码和解码的,粗看上去它们似乎没什么规律,就算有,也是很奇怪的一种,如果你和我一样,对这个很好奇,可以看看下面这个链接,你会觉得豁然开朗:

    http://wiki.ehow.com/Read-12-Digit-UPC-Barcodes


    posted @ 2005-11-18 11:19 laogao 阅读(625) | 评论 (0)编辑 收藏


    今天在JDJ上看到这个很有意思的文章:
    http://java.sys-con.com/read/152251.htm

    大意是讲,在很多大的IT企业内部,经常能够看见一组独立的Java架构师,和另外很多个Java开发团队。架构师们往往忙于奔波在不同的项目,他们也有 自己的进度和任务要完成,有很多公用的模块要维护,很多新的框架或者模块要开发,他们开始怀疑自己作为架构师,到底应该做些什么;而开发者们往往被硬性规 定只能使用架构师组指定的方案和类库、框架,随着时间推移,这些原本的金科玉律开始不再光鲜,开发人员开始抱怨架构师组做的东西很不合理,而修改建议和请 求迟迟不能得到响应,时间长了很可能自己寻求其他途径,如开源的框架。但最终,这些都是团队内部矛盾,该怎么办还得怎么办,想撇开架构师组单干?没这个选 项。为什么会这样?这种情形是如何形成的?Java架构师和普通开发人员之间的工作关系经常是由他人指派,各自的工作内容和指标也都是来自不同的部门,而 不是出于双方自身的意愿。如果把上面这句话的“工作”换成“生活”,这不正像是包办婚姻么?

    我想,有很多Java的项目,当它做到一定规模的时候,自然而然就会产生出自定义框架和类库的想法,一开始,这种方法很有效,无论做框架的还是用框架的, 都很happy。但是时间长了,这样的模式就会带来各式各样的问题。这个时候,架构师和开发人员就需要坐下来,开诚布公的好好谈一谈,架构师要多多理解开 发人员的苦恼,因为毕竟他们的薪水来自项目预算,开发人员也需要多多理解架构师,也许是你没有把握好框架的正确使用,那个框架并非一无是处。还是把自己分 内该做的事情,做做好,毕竟,作为夫妻,作为一个家庭单元,有它的责任和义务,那就是养育出“孩子”,即产品或项目。就像夫妻吵架,吵归吵,但是第二天, 过去的不愉快,应该抛在脑后了。

    不知道各位所在的公司和项目有没有类似的情况出现,大家有有些什么好的办法去解决它所带来的麻烦呢?可以分享一下你的经验么?


    posted @ 2005-11-18 10:54 laogao 阅读(1319) | 评论 (2)编辑 收藏


    http://www.boingboing.net/2005/11/15/sony_infects_more_th.html

    有个DNS Hacker对互联网上超过300万个DNS服务器进行了简单的yes-or-no式的扫描,得出的结论,568,200个DNS有记录说它背后的网络中,至少有1台机器在过去这段时间尝试访问过SONY的rootkit才会区访问的专有网址。

    至今SONY也没有公开发布完整可用的卸载程序。

    posted @ 2005-11-17 17:31 laogao 阅读(577) | 评论 (0)编辑 收藏


    作为从最好的Linux发行版之一,Debian GNU/Linux演化出来的一个流行的发行版,Ubuntu如今已经得到了相当多Linux爱好者、使用者的青睐,即继承了Debian的良好的稳定性和安全性,又不失简洁方便实用。

    最近它通过了IBM DB2的认证,开始迈向企业服务器领域。

    http://www.ubuntu.com/
    http://www.ubuntu.com/include/UbuntuReadyForDB2.pdf

    posted @ 2005-11-16 12:46 laogao 阅读(481) | 评论 (0)编辑 收藏


    为何我们本土找不到类似SuSE,Debian,Gentoo这样的Linux发行版?本土Linux企业为何处境艰难?且看NewsForge上的这篇分析评论文章:
    http://business.newsforge.com/article.pl?sid=05/11/04/1727259


    posted @ 2005-11-15 21:01 laogao 阅读(500) | 评论 (0)编辑 收藏


    还记得半个月前我的随笔吗?关于WebSphere的Community Edition:
    http://www.blogjava.net/sean/archive/2005/10/26/16917.html

    根据OETrends.com的报道,该免费版的WebSphere将在本周内推出,作为IBM的拳头产品,这次基于Geronimo开源J2EE服务器,一定要试一试。

    新闻链接:
    http://www.oetrends.com/news.php?action=view_record&idnum=487
    http://www-306.ibm.com/software/info1/websphere/index.jsp?tab=landings/was-c


    posted @ 2005-11-15 20:48 laogao 阅读(1111) | 评论 (4)编辑 收藏


    就在昨天,我还提到这个话题:
    http://www.blogjava.net/sean/archive/2005/11/12/19454.html

    当时说的是特指First4Internet的rootkit,今天又看到这个SunComm的MediaMax,强制安装(即便你选不同意),不提供卸载程序,向SunnComm发送用户数据且无法disable。还有完没完了。

    链接:
    http://www.boingboing.net/2005/11/12/sonys_other_maliciou.html

    [Update]
    针对这次Sony音乐CD的Rootkit带来的安全隐患问题,MS已宣布在后续的AntiSpyware中将它作为恶意代码删除:
    http://www.eweek.com/article2/0,1759,1886122,00.asp


    posted @ 2005-11-13 12:20 laogao 阅读(599) | 评论 (3)编辑 收藏


    最近关于Novell SuSE Linux转向GNOME的报道真是铺天盖地,在整个Linux社区也产生了不小的动荡,还记得我的上一篇随笔吗:
    http://www.blogjava.net/sean/archive/2005/11/06/18376.html

    Novell终于不堪压力,出来澄清:
    http://www.novell.com/prblogs/index.php?title=kde_and_gnome&more=1&c=1&tb=1&pb=1

    原来Novell的SuSE Linux产品线将默认GNOME但将继续提供KDE供选择。

    posted @ 2005-11-12 12:51 laogao 阅读(449) | 评论 (0)编辑 收藏


    想必已经有很多人听说了这个在国外闹得沸沸扬扬的Sony 'rootkit' CD防拷贝技术。但是也许你还不知道的是:到底这个东东算不算spyware?它怎样进入你的Windows系统?有哪些危害?如何清除?

    简单的讲,这个东东主要发现于在美国发行的Sony Music CD,占Sony发行的CD中的一小部分,当它被使用Windows的机器播放时,首先弹出一个许可窗口,如果用户点确认,它会在系统中安装rootkit程序,用于保护CD的版权,并且会向Sony反馈信息。该程序会自动隐藏,并且让其他使用类似手法的spyware或者木马程序同样难以被发现,甚至杀毒软件也看不到它。'rootkit'顾名思义就是以根用户权限运行的工具集,对系统具有至高无上的控制权。想想看,它有多可怕。

    有办法清除吗?Sony官方发布的补丁可以让它的rootkit不再隐藏自己,但是不会卸载它。如果你要卸载,需要到Sony官网提交单独的申请,才能得到卸载的指导文档。

    Sony官方的表态显得十分令人不爽,这不,BoingBoing已经有人坐不住了:
    http://www.boingboing.net/2005/11/11/sony_will_stop_shipp.html


    详情请参阅news.com新闻链接:
    http://news.com.com/FAQ+Sonys+rootkit+CDs/2100-1029_3-5946760.html

    posted @ 2005-11-12 12:10 laogao 阅读(465) | 评论 (0)编辑 收藏


    为了学习和使用TPTP,并且基于此开发自定义的测试工具,我们需要安装和配置Eclipse环境。为了减轻大家到处查看英文网页的负担,在这里做个简要说明:

    1- 下载和安装JDK:
    http://java.sun.com/j2se/1.5.0/download.jsp
    目前最新的是JDK 5.0 Update 5

    2- 下载和安装Eclipse SDK:
    http://eclipse.org/downloads/index.php
    目前最新的版本是3.1.1,解压即可。
    http://download.eclipse.org/downloads/drops/R-3.1.1-200509290840/index.php

    3- 下载EMF SDK 2.1.1:
    http://www.eclipse.org/downloads/download.php?file=/tools/emf/downloads/drops/2.1.1/R200509281310/emf-sdo-SDK-2.1.1.zip
    这是TPTP依赖的SDK,解压到Eclipse SDK相同的目录。

    4- 下载XSD SDK 2.1.1:
    http://www.eclipse.org/downloads/download.php?file=/tools/emf/downloads/drops/2.1.1/R200509281310/xsd-SDK-2.1.1.zip
    这是TPTP依赖的SDK,解压到Eclipse SDK相同的目录。

    5- 下载TPTP SDK 4.0.1:
    http://www.eclipse.org/downloads/download.php?file=/tptp/4.0.1/TPTP-4.0.1-200510031151/tptp.sdk-TPTP-4.0.1-200510031151.zip
    解压到Eclipse SDK相同的目录。

    6- 启动Eclipse:
    直接点eclipse/eclipse.exe启动,如果发现TPTP无法加载,使用-clean参数执行eclipse.exe一次。



    // 欢迎光顾http://www.eclipseworld.org/thread.php?fid=72中国Eclipse社区TPTP版参与相关话题讨论。

    posted @ 2005-11-10 23:14 laogao 阅读(3783) | 评论 (0)编辑 收藏


    从这里看到的消息:
    http://www.eweek.com/article2/0,1759,1884467,00.asp

    在Sun的官网得到证实:
    http://developers.sun.com/prodtech/javatools/free/

    你需要的是一个Sun Developer Network的账号,通过一些简单的步骤,你将得到完整的license。一直以来Sun的IDE总是显得有点另类,且看这次Sun能走多远吧。

    posted @ 2005-11-10 15:14 laogao 阅读(867) | 评论 (1)编辑 收藏


    如果你还记得我的上一篇关于Eclipse套装版命名投票的随笔:
    http://www.blogjava.net/sean/archive/2005/10/18/15755.html

    投票的结果出来了:



    我投的Phobos只得到17%的票数,最终的winner是Callisto(木卫四)。还是很不错!

    posted @ 2005-11-09 23:15 laogao 阅读(825) | 评论 (3)编辑 收藏


    免费的Express版可以在这里下载:
    http://www.microsoft.com/downloads/details.aspx?familyid=220549b5-0b07-4448-8848-dcc397514b41&displaylang=en

    posted @ 2005-11-08 22:41 laogao 阅读(228) | 评论 (0)编辑 收藏


    最有意思的可能是Two-Phase Commit吧。

    更多详情:
    http://www.postgresql.org/

    posted @ 2005-11-08 22:38 laogao 阅读(238) | 评论 (0)编辑 收藏


    以下是新闻链接:
    http://news.zdnet.co.uk/software/developer/0,39020387,39235794,00.htm

    Eclipse确实是成功的开源项目,不但自己发展很好,而且创造了一个良性的产业环境,让无数优秀的厂商、团体和个人的产品能够无缝的集成在一起,形成一个独有的ecosystem。

    你怎么看?

    posted @ 2005-11-08 21:37 laogao 阅读(1335) | 评论 (3)编辑 收藏


    http://forbes.codefix.net/capsule/

    有兴趣吗?Forbes最近正提供一个免费的服务:写一封电子邮件,然后根据你的选择,它负责在N年后帮你寄出。想法不错,可是N年后,我还会用这个邮箱吗?这是个问题。

    posted @ 2005-11-07 12:58 laogao 阅读(617) | 评论 (2)编辑 收藏


    http://linux.slashdot.org/article.pl?sid=05/11/02/0418234


    如果Debian和Ubuntu这两个名字对你来说并不陌生,而你也知道Solaris,那么也许你应该看看上面这个链接。GNU的Solaris?基于Solaris/SunOS核心的Debian?

    你怎么看?

    posted @ 2005-11-06 13:02 laogao 阅读(407) | 评论 (1)编辑 收藏


    据eWeek.com的报道,之前的一些传言说Novell这次裁员将严重影响其Linux产品的相关部门,甚至是终止桌面版和工作站版的SuSE Linux的开发,是不符合事实的。

    http://www.eweek.com/article2/0,1759,1882118,00.asp

    这里提到一个让人多少有点意外的消息:Novell SuSE Linux产品线(SuSE Linux Enterprise Server和Novell Linux Desktop)将以GNOME作为其缺省得图形桌面环境。当然KDE的应用程序仍然可以跑,而openSUSE将继续提供KDE的支持,但是今后Novell主流的Linux产品界面将是GNOME。

    posted @ 2005-11-06 12:14 laogao 阅读(502) | 评论 (0)编辑 收藏


    刚看到的消息,FreeBSD发布了6.0:

    http://www.freebsd.org/releases/6.0R/announce.html
    http://www.freebsd.org/releases/6.0R/relnotes-i386.html

    FreeBSD是开源免费BSD中,性能优异且相对友好的一个发行版,使用它来建站的人很多,如果你对Linux或者PC/x86体系下的Unix感兴趣,也许应该多花些时间了解一下异常健壮的BSD家族中的这个颇受欢迎的家伙。

    // 致初次听说BSD的朋友:BSD全称是Berkeley Software Design,是美国加州大学Berkeley分校的从Unix分支出来的一个版本,相对于Linux,BSD发行版本更加统一和集中,常见的也就是 FreeBSD、NetBSD、OpenBSD等,BSD直接支持Linux下面的应用程序。不过要小心,BSD和Linux之间貌似同本同宗,很多网站 或BBS都把它们归类在一起,但是其实则不然,而且它们深层次的矛盾相当尖锐,涉及到对自由软件的理解问题,开源精神的本质,以及对Unix的忠诚度,甚 至是软件开发哲学的问题等等,还是看自己的喜好和需求来选择吧。

    这里有一个FreeBSD、Linux和Windows 2000的比对,供参考:(其实Solaris和Max OS背后都有BSD的影子)
    http://people.freebsd.org/~murray/bsd_flier.html

    posted @ 2005-11-05 16:09 laogao 阅读(359) | 评论 (0)编辑 收藏


    今天在EclipseZone看到这个消息:
    http://www.eclipsezone.com/eclipse/forums/t53310.html

    乍一看,这个开源的RSS阅读器用的是Sun的ROME聚合框架,还以为是前端也是用的Sun的Swing,正纳闷怎么到了EclipseZone。打开 一看,原来UI还是用Eclipse的SWT/JFace,呵呵。准备什么时候下下来试试看,正好RSSOwl在我的SuSE Linux 10.0上跑起来有些小问题。

    Feed'n Read的主页:
    http://fnr.sourceforge.net/


    posted @ 2005-10-31 22:02 laogao 阅读(895) | 评论 (2)编辑 收藏


    正如很多人所预料的那样,Google开始资助OpenOffice.org。用过OpenOffice.org的人应该知道它背后实际是Sun公司,前不久Google和Sun达成了合作协议,这次Google对OOo的支持正是这份协议的一个实质上的行动。

    OpenOffice这两年发展很快,总算到了要让MS担心的程度了。回头想想我们中国的WPS,做得是很不错,也很辛苦,我很敬佩他们的努力,但是始终 给我感觉金山还差那么一股子劲儿,显得有些不厚道:比如强制注册,比如从他们的网站很不容易找到简单易懂的下载和使用说明(跟其他很多国外的网站相比,这 也是国产软件的通病),比如for Linux的版本,我找半天都没有,最后放弃了。

    国产软件要走的路,真的还很远哦。

    新闻链接:
    http://news.com.com/Google+throws+bodies+at+OpenOffice/2100-7344_3-5920762.html


    posted @ 2005-10-31 21:50 laogao 阅读(772) | 评论 (0)编辑 收藏


    David Heinemeier Hansson是谁?可能一开始看上去并不是什么熟悉的名字,但是Ruby on Rails相信只要你搞Web开发,看点新近的技术文章,应该多少有所耳闻。最近炒得异常火爆,号称兼具Java和PHP的有点的开源Web框架正是出自 Hansson之手。

    Hansson今年才26岁,真是令我倍感惭愧。我前不久也刚满26周,怎么就没有他那种执着和狂热呢?

    新闻背景:
    http://news.com.com/Ruby+on+Rails+chases+simplicity+in+programming/2100-1007_3-5920169.html


    posted @ 2005-10-31 21:37 laogao 阅读(795) | 评论 (0)编辑 收藏


    据报道,随着开源数据库产品的日趋成熟,加上IBM和MS最近也提供免费的DB2和SQL Server版本,Oracle也将在年底前推出免费的Oracle 10g Express Edition (Oracle Database XE)。

    消息源:
    http://news.com.com/Oracle+to+offer+free+database/2100-1012_3-5920796.html


    posted @ 2005-10-29 11:52 laogao 阅读(450) | 评论 (2)编辑 收藏


    从这篇评论看,这本书相当适合Linux初学者。

    原文:
    http://madpenguin.org/cms/index.php/?m=show&id=5406&page=1


    posted @ 2005-10-27 16:40 laogao 阅读(278) | 评论 (0)编辑 收藏


    今天我们要讲的是FUD:Fear, Uncertainty, Doubt的缩写。根据TechTarget的Whatis.com的解释:

    FUD (Fear, Uncertainty, and Doubt) is the term for any strategy intended to make a company's customers insecure about future product plans with the purpose of discouraging them from adopting competitors' products. For example, "You can try using X instead of our product, but you may lose all your data."

    从这个定义我们可以看出,FUD多指一些公司针对竞争者的一些市场策略,使竞争者产品/服务潜在的用户对他们所考量的对象产生不必要的恐惧和疑虑的心理。 这个词最早是IBM的前员工Gene Amdahl创造的,用于形容当初当他离开IBM创业时,IBM对他的公司采取一系列的封杀策略。不过现在使用FUD最多的也许是MS吧?

    // 不知怎么搞的,今天Wikipedia打不开,它上面对FUD的解释可能更全面一些。


    posted @ 2005-10-27 16:35 laogao 阅读(1147) | 评论 (0)编辑 收藏


    这是一组系列文章,主题是轻量级的开发,内容涵盖了轻量级容器、敏捷开发、持久化策略、以及Java语言本身的局限,等等等等。

    英文版出到了第7部分:
    http://www-128.ibm.com/developerworks/opensource/library/os-lightweight1/
    http://www-128.ibm.com/developerworks/opensource/library/os-lightweight2/
    http://www-128.ibm.com/developerworks/opensource/library/os-lightweight3/
    http://www-128.ibm.com/developerworks/opensource/library/os-lightweight4/
    http://www-128.ibm.com/developerworks/opensource/library/os-lightweight5/
    http://www-128.ibm.com/developerworks/opensource/library/os-lightweight6/
    http://www-128.ibm.com/developerworks/opensource/library/os-lightweight7/

    中文的翻译到了第6部分:
    http://www-128.ibm.com/developerworks/cn/opensource/os-lightweight1/
    http://www-128.ibm.com/developerworks/cn/opensource/os-lightweight2/
    http://www-128.ibm.com/developerworks/cn/opensource/os-lightweight3/
    http://www-128.ibm.com/developerworks/cn/opensource/os-lightweight4/
    http://www-128.ibm.com/developerworks/cn/opensource/os-lightweight5/
    http://www-128.ibm.com/developerworks/cn/opensource/os-lightweight6/

    推荐阅读。


    posted @ 2005-10-26 22:37 laogao 阅读(750) | 评论 (1)编辑 收藏


    据报道,截至2005年10月,全球使用Apache服务器的站点超过5200万,而微软的IIS也达到了惊人的1500万个站点。

    消息源:
    http://news.netcraft.com/archives/2005/10/04/october_2005_web_server_survey.html


    posted @ 2005-10-26 21:56 laogao 阅读(304) | 评论 (0)编辑 收藏


    IBM的WebSphere产品线将迎来一个全新的版本,据报道,该版本基于开源的Geronimo,免费提供下载和使用,技术支持的话,相对也很便宜: 起价是$900/服务器.年。IBM对开源软件的支持大家有目共睹,它为什么这么做?现在大家可能也看出点门道了,呵呵。

    相对于JBoss,我还是更欣赏Apache的项目。

    消息源:
    http://www.eweek.com/article2/0,1759,1876964,00.asp


    posted @ 2005-10-26 21:17 laogao 阅读(879) | 评论 (2)编辑 收藏


    http://news.com.com/Key+executives+resign+from+Microsoft/2100-1038_3-5913543.html


    posted @ 2005-10-26 20:56 laogao 阅读(1219) | 评论 (0)编辑 收藏


    MadPenguin.org发表了一则关于SuSE最新版10.0的分析文章,对它的新特性和SuSE一贯的风格做了比较详细的介绍,最终结论是这个版本的SuSE对新用户使用特别友好,而这也正是我的感觉,这个版本我也用了有超过半个月了,确实表现很出色。

    原文:
    http://madpenguin.org/cms/index.php/?m=show&id=5382&page=1


    posted @ 2005-10-26 19:49 laogao 阅读(400) | 评论 (0)编辑 收藏


    你想学习Linux并考虑将工作转移到Linux环境,但是你已经习惯了Windows的工作方式?看看这篇developerWorks上的文章吧:
    http://www-128.ibm.com/developerworks/linux/library/l-roadmap.html

    这里有中文版:
    http://www-128.ibm.com/developerworks/cn/linux/l-roadmap/

    强烈推荐。

    posted @ 2005-10-25 11:55 laogao 阅读(326) | 评论 (0)编辑 收藏


    http://www.mysql.com/


    posted @ 2005-10-24 22:31 laogao 阅读(270) | 评论 (0)编辑 收藏


    好久没有静下来看看TSS.com了,今天看到这个话题还挺有趣的,回复里的辩论也很精彩,备份一下链接:

    http://www.theserverside.com/news/thread.tss?thread_id=37222


    posted @ 2005-10-23 22:13 laogao 阅读(340) | 评论 (0)编辑 收藏


    对于初学者来说,Linux系统如何启动,即如何找到并加载Linux内核,如何确定是否启动X桌面,如何确定默认的运行级别等等,也许是一个很有趣的话题。

    简单的说,常见的Linux系统的bootloader分成LILO和GRUB两种,分别代表LInux LOader和GRand Unified Bootloader。前者通过读取硬盘上的MBR来确定要启动的系统并将控制权交给那个系统;后者在MBR中只占512K,先做一些初始化,然后确定如 何访问启动盘/区,接下来从那个盘/区读取剩余的boot信息。目前更多更常见的Linux系统都采用后者。

    LILO的配置文件是/etc/lilo.conf,而GRUB则通常在/boot/grub目录下,具体的名称视不同的发行版而定,如在SuSE下,这个文件叫做menu.lst,FC下面好象是grub.conf。

    建议感兴趣的朋友把这两个文件打开来看看,里面的注释应该足够让你明白它的含义了。如果你不知道如何看文件内容,简单说一下:打开终端,运行命令su,输 入root密码,或者敲Ctrl-Alt-F1,用root登录,这样你会以root身份操作命令行;先ls /boot/grub -l看看这个目录下的文件列表,找到menu.lst或者grub.conf后,用less menu.lst的方式查看文件内容,退出按q。

    另一个有意思的文件是/etc/inittab,里面包含了所有运行级别和默认的运行级别,可以去看看,也可以修改默认的运行级别,只是注意别改成没有的 级别或者0、6就好。0代表关机,6代表重启,你肯定不希望系统一上来就关机或者重启吧?最常用的是3-不带图形桌面的网络多用户和5-带图形桌面的网络 多用户,另外1-单用户在调试和需要额外安全的时候也很有用。


    posted @ 2005-10-23 21:00 laogao 阅读(383) | 评论 (0)编辑 收藏


    看到一篇相当不错的文章,是关于主流DBMS对于SQL的不同实现,从高端的Oracle和DB2,到中游的MS SQL Server,再到开源的MySQL和PostgreSQL,它都做了相当详细的比较,哪些是符合SQL标准的,哪些不符合,哪些提供了其他途径。对于某 些功能点,作者也指出了应该怎样做才符合标准。

    如果你正在犹豫在新的项目中采用哪个数据库,这篇文章能够帮你从SQL标准这个角度对它们进行一一考量。

    原文见:
    http://troels.arvin.dk/db/rdbms/


    posted @ 2005-10-23 17:06 laogao 阅读(1530) | 评论 (0)编辑 收藏


    Henry is back!

    在刚刚结束的英超比赛中,凭借第61分钟Pires的点球,Arsenal 1:0 战胜曼城。Henry在本场比赛复出英超,首发并打满全场。那个点球正是他创造的。

    henryisback.jpg

    在周二欧冠对阵Sparta Prague(布拉格斯巴达),Henry从伤病重返赛场,并梅开二度,最终比分2:0。

    henry_prague3.jpg

    That's my Henry! That's my Arsenal!!


    posted @ 2005-10-23 00:42 laogao 阅读(386) | 评论 (0)编辑 收藏


    我们知道,SWT最大的特点就是直接利用系统本地的控件,而非模拟出一个类似的或者接近的控件,SWT这种简单直接包装本地控件API的途径不但直接保证 了它的界面看上去相当native,而且用起来这些控件的行为也会是跟native的控件一致,如果有界面上控件的bug或inconsistency, 那么这个bug或者inconsistency 99%来自OS本身。

    OK, 我明白也许对于你来说,这已经不是什么big deal(另一方面,我本人也不止一次提到过)。不管怎么说,对于那些对SWT还有些不熟悉或者心存疑虑的朋友,也许可以看看EclipseZone的这篇报道,对SWT建立更进一步的感性的认识:
    http://www.eclipsezone.com/eclipse/forums/t52878.html

    不用作任何修改,在Windows Vista下面运行Eclipse,它的界面风格直接就跟Vista的本地一般应用程序高度一致。


    posted @ 2005-10-22 23:59 laogao 阅读(775) | 评论 (0)编辑 收藏


    "A sense of humor is part of the art of leadership, of getting along with people, of getting things done."
    - Dwight D. Eisenhower

    “幽默感是领导艺术的一部分,是关于如何与人相处,如何把事情做好。”
    - 德怀特·艾森豪威尔

    "to get along with people"和"to get things done"都是英语中常见的短语。


    posted @ 2005-10-22 21:34 laogao 阅读(376) | 评论 (0)编辑 收藏


    经过一段时间的beta之后,OpenOffice.org终于发布2.0正式版。



    感兴趣的朋友可以下载下来用用看:
    http://download.openoffice.org/2.0.0/index.html


    posted @ 2005-10-21 01:43 laogao 阅读(430) | 评论 (0)编辑 收藏


    根据TSS.com的报道,Apache Geronimo选出了新的图标:(贴个相对小点的)



    完整的图片可以在这里看到:
    http://www.epiqtech.com/corp/products/technology/opensource/apachegeronimo4.htm

    posted @ 2005-10-19 17:07 laogao 阅读(688) | 评论 (1)编辑 收藏


    据News.com报道,MySQL 5.0将于未来10天之内正式发布:
    http://news.com.com/MySQL+preps+business+upgrade/2100-7344_3-5899491.html

    另: Oracle收购Innobase,Sun有意收购PostgreSQL?
    http://ask.slashdot.org/article.pl?sid=05/10/18/2126237

    posted @ 2005-10-19 16:57 laogao 阅读(365) | 评论 (2)编辑 收藏


    你是否觉得Linux的发行版本太多,以致许多大型的软件公司在移植其产品到Linux平台显得力不从心或者犹豫不前?Free Standards Group试图要改变这个现状:

    http://software.newsforge.com/article.pl?sid=05/10/18/141242

    这项新的计划名叫Linux Standard Base (LSB) Desktop,已经有很多大公司参与其中:Adobe, Intel, IBM, Novell, Red Hat, Linspire, Trolltech等等。希望这个项目能够给我们带来一个在Linux环境下开发桌面软件的公共平台。


    posted @ 2005-10-18 23:07 laogao 阅读(415) | 评论 (0)编辑 收藏


    在NewsForge上看到一篇关于Trolltech的介绍,其实从接触Linux起,这个名字就经常在我眼前出现,之前的一篇随笔(http: //www.blogjava.net/sean/archive/2005/10/11/15255.html)中我曾经提到KDE和GNOME的战 争,KDE的背后,正是Trolltech的Qt。

    作为一家开源免费软件的公司,靠什么盈利?Trolltech为什么能够做到那么好?也许它对Qt的双重许可(GPL和非GPL版本,这正是KDE和Qt 备受指责的地方,因为它看上去阻止了许多商业软件公司对Linux潜在的推动作用)是它盈利的主要来源。它背后的逻辑是:如果你用Qt开发GPL的软件, 那么你可以免费使用它;如果你用Qt开发GPL所规定之外的软件,那么你需要向Trolltech购买许可。Trolltech之所以不支持LGPL这样 的license是因为它认为这样的license使得某些公司或个人可以免费的享有其他人的成果,而不需要任何回报。Trolltech通过这些收入来 支持Qt的开发和维护。

    如果对本话题感兴趣,请参考如下NewsForge文章和Trolltech官网的FAQ:
    http://business.newsforge.com/article.pl?sid=05/10/03/155235
    http://www.trolltech.com/developer/faqs/index.html


    posted @ 2005-10-18 22:23 laogao 阅读(399) | 评论 (0)编辑 收藏


    "Our scientific power has outrun our spiritual power. We have guided missiles and misguided men."
    - Martin Luther King Jr.

    再来一句Martin Luther King Jr.的名言:我们科学的力量已经超越了精神的力量。我们成功制导了导弹,却误导了人。


    posted @ 2005-10-18 21:42 laogao 阅读(389) | 评论 (0)编辑 收藏


    http://www.eclipsezone.com/eclipse/forums/t52526.html

    Ward Cunningham,这个在业界响当当的名头,即将加入Eclipse Foundation,成为它的第十个正式员工。如果你觉得这个名字还不够熟悉,我想你一定听说过Wiki吧?除了Wiki之外,在XP(eXtreme Programming)方面,也能经常看到这个名字的出现。可以说,他是个很技术型的人,对于广大开发者来说,应该是相当有亲和力。

    我还依稀记得为我很喜欢的一本书:《The Pragmatic Programmer - From Journeyman to Master》写序的人正是Ward Cunningham。


    posted @ 2005-10-18 00:56 laogao 阅读(679) | 评论 (3)编辑 收藏


    Eclipse Concils计划在2006年六月发布一个Eclipse的"套装版",将会包含数个不同的Eclipse项目,如Eclipse Platform 3.2、Eclipse SDK 3.2、WTP 2.0、TPTP 4.2等等。这些子项目分别都带有自己的发行版本号,也有自己的开发周期,不可能完全统一。因此这次的这个"套装版"也不打算引入自己的一个版本号,而是 打算用一个更加"标志化"、"代号化"、更加"与时俱进"的名称,如Zebra、Lunar、Eclipse 2006、Callisto、Phobos、Corona、Comet等等。

    可以看看这个:
    https://bugs.eclipse.org/bugs/show_bug.cgi?id=108146

    投票的话,可以去这里:
    http://www.advancedsurvey.com/survey/header.asp

    好像目前只有这几个可以选了:(还有不到一个月的时间了)
      Callisto (from a series of moon names)
      Phobos (from a series of moon names)
      Eclipse 2006
      Total Eclipse
      Comet (from a series of famous train names)

    你喜欢哪一个,投出你的一票吧!:)


    posted @ 2005-10-18 00:37 laogao 阅读(811) | 评论 (0)编辑 收藏


    Nothing travels faster than the spead of light with the possible exception of bad news, which obeys its own special laws.
    - Douglas Adams

    Douglas Adams是英国已故科幻小说家,上面这句话说的是:没有什么能比光速运行的更快,可能坏消息是个例外,它遵从它自己特殊的定律。可见坏消息传播速度有多快。


    posted @ 2005-10-17 21:11 laogao 阅读(294) | 评论 (0)编辑 收藏


    这次由CodeProject、MainSoft和IBM赞助的Race To Linux竞赛给了我们一些启示,从Windows平台走出来,其实有很多方式,比较常见的有:

    1- Mono (这个不用我多介绍了吧)
    2- Grasshopper (Visual Studio的插件,把.NET的MSIL编译成Java Bytecode)
    3- PHP (一种服务器端运行的脚本语言)

    也许还应该有4- Java,呵呵,不过个人认为Java本身在"移植"现有Windows应用的方面,其实没什么好的办法。另外像Wine等在这方面倒是做的不错,但他们更像是虚拟出一个环境而非真正的移植。

    BTW,这次比赛的冠军是使用的PHP和PostgreSQL。


    posted @ 2005-10-16 23:21 laogao 阅读(261) | 评论 (0)编辑 收藏


    You don't stop laughing because you grow old. You grow old because you stop laughing.
    - Michael Pritchard

    你不会因为变老而停止欢笑。是因为停止了欢笑你才变老的。

    从现在起,让我们学着用微笑去面对周围的世界。:)


    posted @ 2005-10-16 23:00 laogao 阅读(296) | 评论 (0)编辑 收藏


    IBM近日向Eclipse Foundation提交了一份关于创建一个新的Eclipse子项目的提议,该子项目为Eclipse Process Framework,代号"Beacon",IBM Rational将贡献出RUP的一个子集。

    如果该项目得到批准和执行,Eclipse平台将增加又一个强有力的工具--用于过程改进的框架。

    原文见:
    http://www-128.ibm.com/developerworks/rational/library/05/1011_kroll/


    posted @ 2005-10-15 00:12 laogao 阅读(852) | 评论 (0)编辑 收藏


    Experience teaches only the teachable.
    - Aldous Huxley

    Aldous Huxley是英国已故小说家评论家,上面这句话的含义是,只有那些愿意吸取教训的人才能得到真正的经验教训(不知是不是方言,我觉得汉语中的“乐教”用来翻译这个"teachable"很贴切)。注意only的用法,放在动词后,强调"the teachable"。这句话的句式让我想起另外一个我很喜欢的格言:

    Chance favours only the prepared mind.
    机遇只留给那些有准备的人。

    // 后面这句话的来源有待考证。

    posted @ 2005-10-14 16:20 laogao 阅读(469) | 评论 (4)编辑 收藏


    We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true.

    - Robert Wilensky

    呵呵,相信我们当中很多人都曾经听说过这个比喻:100万只猴子坐在100万台电脑前敲键盘可以产生出莎士比亚的全集,Robert Wilensky评论说:Internet的出现让我们了解到那个说法是不对的,因为Internet连接了无数电脑和人脑,但是我们没有看到莎士比亚全集,对吧?

    呵呵,不管有没有逻辑,权当是Wilensky的幽默吧。Robert Wilensky是美国加州大学伯克利分校计算机系的教授,著有Common LISP的相关书籍。

    posted @ 2005-10-12 16:10 laogao 阅读(335) | 评论 (0)编辑 收藏


    MS再一次做出让人反感的所谓"免费的东西并非真正免费"的市场宣传,不过这次的目标不是Linux,而是Eclipse。
    http://www.internetnews.com/dev-news/article.php/3554936

    Eclipse比Visual Studio的总体拥有成本还要高?(Eclipse 10万美金,Visual Studio 2005 3万美金)

    Javalobby/Eclipsezone有针对这件事的讨论:
    http://www.eclipsezone.com/eclipse/forums/t49894.html

    诚然,在Eclipse下面,各种各样的插件参差不齐,免费插件还需要进一步完善,但是MS的VS真的就那么好用?我看也不见得,更何况MS的价格和每次的升级费用都相当吓人,相比之下,Eclipse的核心功能和很多优秀的插件都是免费的。(没记错的话最新的Visual Studio 2005最基本的Express版都要卖$49)

    看来Eclipse离当初叫板VS的目标不远了,至少获得了Visual Studio的敌视和一定程度上的"针锋相对",呵呵。不知道这次微软是不是同时也在针对Java,不过至少在引起MS注意/敌意这一点上,Eclipse比NetBeans和IntelliJ IDEA还是要成功得多。

    posted @ 2005-10-12 11:07 laogao 阅读(980) | 评论 (3)编辑 收藏


    一个是
    http://kde-apps.org/
    另一个在freshmeat:
    http://freshmeat.net/browse/229/

    KDE的应用程序真的不少,需要处理某个特定需求时,别忘了上这里看一看,一般的Linux发行版不大可能包含所有开源/免费的X Window应用程序的。在freshmeat还有相当数量的GNOME/GTK/Qt的应用,简直让人目接不暇。

    posted @ 2005-10-11 18:04 laogao 阅读(323) | 评论 (0)编辑 收藏


    众所周知,在Unix下面的X Window系统有两套最流行的桌面,它们各有千秋,难分伯仲。两边的支持者和开发者也分成截然两个世界(虽然它们的应用程序相互兼容)。通常我们会看到的两派之争的战场包括:

    1- 授权许可:KDE和Qt曾是QPL,和GPL不兼容;而GNOME生来就是GPL。
    2- 编程语言:KDE使用C++;而GNOME坚持使用C。
    3- 对闭源商业软件开发的支持:都有LGPL。
    4- 地域之争:KDE的开发者很多来自欧洲;而GNOME备受北美开发者青睐。(看看SuSE和Redhat)
    5- 社群:两派都有相当大的用户群和开发者。
    6- 应用程序:KDE有相当多现成的应用程序;而GNOME拥有不少重量级的产品。

    我们且看看双方在各自网上做的宣传:
    KDE - http://www.kde.org/whatiskde/kdemanifesto.php
    GNOME - http://www.gnome.org/about/why.html

    还有就是关于KDE,由于历史原因,也许一直存在一些不必要的误解,这里有一个比较好的总结:
    http://kdemyths.urbanlizard.com/

    不知大家更喜欢哪一个?

    posted @ 2005-10-11 14:32 laogao 阅读(493) | 评论 (0)编辑 收藏

    有一阵子没关心Apache的东西了,只是临散的听说了多少有点孩子气的Rickard Oberg对JBoss的不满,让人间接的想到Geronimo这个开源的应用服务器。今天发现一个很重要的新闻:Geronimo终于通过了J2EE 1.4的认证。 http://geronimo.apache.org/ 目前的版本是1.0M5,让我们等待1.0正式版的发布吧。:)

    posted @ 2005-10-11 00:37 laogao 阅读(594) | 评论 (0)编辑 收藏


    SuSE Linux 10.0按计划在10月6日正式推出,第一时间找下来装起,玩了两天,感觉相当不错。贴几张截屏(点击查看大图):

    SuSE_10_Snapshot_03ss.png    SuSE_10_Snapshot_03ss.png    SuSE_10_Snapshot_03ss.png

    怎么样,SuSE的界面还是一如既往的靓吧?大家要下的话,推荐使用BitTorrent,官方网站有.torrent文件的下载链接

    BitTorrent的客户端我推荐Azureus - http://sourceforge.net/projects/azureus/


    posted @ 2005-10-10 21:16 laogao 阅读(3206) | 评论 (9)编辑 收藏


    我们似乎习惯了MS的宣传,尤其是最近两年的Get The Facts系列,认为Linux并非真的那么安全。TheRegister.com上面有一篇深度调查报告:(虽有些老,但仍然valid)
    http://www.theregister.com/2004/10/22/linux_v_windows_security/

    看看我们经常听到的说Linux并非那么安全的论据:
    1- Windows only suffers so many attacks because there are more Windows installations than Linux, therefore Linux would be just as vulnerable if it had as many installations
    2- Open source is inherently less secure because malicious hackers can find flaws more easily
    3- There are more security alerts for Linux than for Windows, therefore Linux is less secure than Windows
    4- There is a longer time between the discovery of a flaw and a patch for the flaw with Linux than with Windows
    是怎么被一一击破的。尤其是第一条。

    这里有完整的PDF下载:
    http://www.theregister.com/2004/10/22/security_report_windows_vs_linux.pdf

    posted @ 2005-10-08 16:30 laogao 阅读(450) | 评论 (2)编辑 收藏


    Google开始提供RSS在线阅读服务?
    http://reader.google.com/

    如果你有Google账号,又有一个好玩的东西可以用了。

    posted @ 2005-10-08 15:52 laogao 阅读(462) | 评论 (1)编辑 收藏


    在Linux环境下, 尤其是家用桌面电脑系统, 有一些必装的应用软件, 如Firefox, Thunderbird, RealPlayer, OpenOffice.org, GAIM等等, 上面提到的这些基本上主流的Linux发行版都已默认附带了, 或者至少可以从现成的Repositories上面通过YUM, APT-GET, YaST等等配置工具自动下载安装, 还有一些非常好用的软件则往往是需要自己去下载和安装的. 这一部分的软件常见的安装方式大致可以分为现成的自解压安装程序, RPM软件包和源代码tarball三种. 自解压的如Sun的JDK和JRE; RPM是.rpm后缀的文件, 下载下来用rpm -ivh命令安装; tarball是相对来说比较麻烦, 但也是最有意思的一种方式, 把源代码包下载下来之后, 解压, 编译, 安装, 完全自主式的过程. (还有一个很重要的好处那就是编译出来的应用程序是针对目前使用的具体平台优化的.)

    今天我们一起来看看MPlayer的安装过程, 一方面给刚接触Linux的朋友一点感性认识: 在Linux下面如何从源码开始安装应用软件; 另一方面, MPlayer的配置过程并不是十分直接了当, 会遇到这样那样的问题, 而网上能够找到的中文说明比较临散, 在这里做个在FC4环境下的安装过程的整理和备份.

    MPlayer是什么? 是一个在UNIX的X Window环境下播放各种媒体格式的音频和视频播放器, 在目前可能是Linux下最流行, 也是支持格式最全的播放器了, 它的主页是: http://www.mplayerhq.hu/ . 呵呵, 居然是.hu, 有点意外. 为了从源代码开始安装一个支持GUI的MPlayer, 我们首先需要保证我们的系统中包含了gcc, gtk等工具包, 在这里我默认大家都安装了必要的编译所需的工具. 接下来我们就来看看具体的安装步骤:

    ## 1 - 安装准备 ##

    在http://www.mplayerhq.hu/上找到并下载如下四部分相关的文件: (找不到? 别偷懒, Google一下吧.)
    [源代码]MPlayer-1.0.pre7try2.tar.bz2 (主程序, 不带解码器和GUI皮肤)
    [解码器]all-20050412.tar.bz2 (注意不是windows-*, 这一个all-20050412目前是最全的官方codecs)
    [字体]gb2312-ming.tar.bz2 (为了支持中文字幕)
    [皮肤]bluecurve-1.3.tar.bz2 (还有很多其他选择, 笔者比较喜欢简洁, 这个bluecurve就不错)

    ## 2 - 安装Codecs ##

    我们要做的很简单, 就是把all-20050412.tar.bz2解压到/usr/local/lib/codecs/目录下, 命令是:
    bzip2 -cd all-20050412.tar.gz2 | tar xvf -
    cp all-20050412/* /usr/local/lib/codecs/
    注意, 如果没有这个目录, 请用mkdir命令新建, 如果权限不够, 请用su使用root用户安装.

    ## 3 - 配置MPlayer ##

    先解压主程序代码包: (建议在/usr/local/src目录执行以下步骤)
    bzip2 -cd MPlayer-1.0pre7try2.tar.bz2 | tar xvf -
    然后进入MPlayer-1.0pre7try2目录, 执行./configure, 配置Makefile:
    ./configure --enable-gui --cc=gcc32
    --enable-gui参数指明我们需要图形界面, --cc=gcc32指明我们需要3.2版本的gcc (这是该版本MPlayer必须的, 它不支持3.2以下版本, 也不支持FC4自带的4.0). 在这个过程中, configure脚本会找到刚才我们安装的codecs, 执行成功后会有提示信息.

    ## 4 - 编译和安装MPlayer ##

    很简单, 先后执行两个命令:
    make
    make install
    注意, 如果不是第一次安装, 需要在这两个步骤之前做一次make clean.
    OK, 到此我们已经可以在命令行试运行MPlayer了:
    mplayer ?????.avi or mplayer ?????.mp3

    ## 5 - 安装字体 ##

    把gb2312-ming.tar.bz2解压后, 会发现两个目录: gbsn00lp16和gbsn00lp24, 分别是16和24两种大小的字体, 选择其中一个, 将里面的文件全部拷贝到/usr/local/share/mplayer/font目录下.

    ## 6 - 安装皮肤 ##

    把bluecurve-1.3.tar.bz2解压后, 将里面的文件全部拷贝到/usr/local/share/mplayer/Skin目录下.

    ## 7 - 开始运行 ##

    好, 现在可以开始运行我们的GUI版MPlayer了, 命令是:
    gmplayer
    当然了, 你可以选择把上面这个命令加到面板或桌面上作为启动器. 如果发现字幕是乱码, 可以使用-unicode参数启动.

    Enjoy!


    posted @ 2005-10-07 19:40 laogao 阅读(1245) | 评论 (0)编辑 收藏


    不知是不是因为Sun对Java发行版本的控制与GNU/Linux之间的矛盾加剧,很多Linux的发行版都不再默认附带Sun的JDK或JRE。举例来说,

    1- 之前的SUSE Linux 9.2 Professional自带JDK 1.4.2,下载Eclipse后可以直接启动,而现在openSUSE Linux 10.0 RC1里面就找不到JDK的影子,默认的Repository里面也没有,需要自行安装。(也许归结于Professional版和openSUSE本身 产品定位的不同?)

    2- 在Fedora Core 4的发行版中,附带的是GNU版的JRE,javac用的是Eclipse的版本,当然也附带了Eclipse,但那是基于Eclipse SDK 3.1M6加上CDT做成的native版本。虽然这些也能用,但是毕竟不是完整的Java,也不是原本的Eclipse。不信的话你可以下载一个最新的 Eclipse SDK 3.1.1,解压以后,根本不能正常启动界面。

    由于我们一般能够获取的Linux发行版本都是免费的版本,而不是Professional或者Enterprise Server级别的,这些版本对Sun的JDK支持都很有限,另外Linux本身也鼓励我们去学一学如何DIY,我觉得有必要在完成了基本的Linux配 置后,自己安装JDK和Eclipse环境。

    我们以使用比较广泛,也比较容易获取的Redhat Fedora Core 4 (http://fedora.redhat.com/)为例说明这个安装步骤。


    <第一步>安装准备

    我们这个时候可以打开一个命令行终端,输入"java -version",可以看到如下信息:

    [sean@localhost ~]$ java -version
    java version "1.4.2"
    gij (GNU libgcj) version 4.0.0 20050519 (Red Hat 4.0.0-8)

    Copyright (C) 2005 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

    看到了吧?这并非Sun官方的Java。

    我们需要到Sun的网站上下载最新的JDK,目前的版本是JDK 5.0 Update 5,注意,这里有两个版本:jdk-1_5_0_05-linux-i586-rpm.bin和jdk-1_5_0_05-linux- i586.bin,根据Fedora Core 4的Release Notes说明,应该使用后者,也就是不带rpm的版本。

    同时,我们也需要到eclipse.org上下载最新的Eclipse SDK,目前版本3.1.1。需要根据你的系统环境选择合适的下载包,如:我的电脑是x86的,X Window系统用的是GNOME 2.10.0,那么自然应该选「x86/GTK 2」,文件名eclipse-SDK-3.1.1-linux-gtk.tar.gz。需要说明一下,FC4默认的X Window系统是GNOME,但是在KDE环境下,照样可以正常使用GTK的应用程序。


    <第二步>安装和配置

    我们现在打开一个命令行终端,输入命令su,提供root用户密码,进入管理员操作模式。然后用ls -l看一下刚刚下载的jdk-1_5_0_05-linux-i586.bin,可以看到它的权限是-rw-r--r--,所有者为sean。为了能够执 行它,需要更改它的权限设置。敲入命令chmod +x jdk-1_5_0_05-linux-i586.bin,再看权限,-rwxr-xr-x,可以执行了。

    切换到/opt/目录,运行jdk-1_5_0_05-linux-i586.bin即可。注意:在Linux默认PATH不包含当前目录,即".",因 此执行当前目录的文件,正确的方法是在文件名前面加上"./"。成功以后可以发现在/opt/目录下多了一个jdk1.5.0_05子目录,这就是我们的 JAVA_HOME。

    到这里还没完,在终端里检查java -version找到的仍然是原来的GNU版本,我们还需要配置系统的环境变量PATH。检查目前PATH内容的方式是echo $PATH,为了能够直接找到我们自己的java,需要把/opt/jdk1.5.0_05/bin目录加入PATH,并且要在GNU版本的前面,最保险 的办法当然是放到最前面了。方法是PATH="/opt/jdk1.5.0_05/bin:$PATH"。这之后再敲java -version,出来的就是正确的了:

    [sean@localhost Java]$ java -version
    java version "1.5.0_05"
    Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_05-b05)
    Java HotSpot(TM) Client VM (build 1.5.0_05-b05, mixed mode, sharing)

    为了今后登录的时候就把这个路径加到环境中,需要修改一下.bash_profile,先cd ~进入自己的主目录,然后用emacs或者vi编辑这个文件,找到PATH这一行,改成:
    PATH=/opt/jdk1.5.0_05/bin:$PATH:$HOME/bin
    保存,退出,注销然后重新登录。

    接下来要做的就是把Eclipse解压到一个你认为合适的路径。


    <第三步>开始使用

    有很多方式运行我们的Eclipse:命令行或文件浏览器直接打开都可以。我这里告诉大家一个在GNOME里面比较方便的一种途径:从文件浏览器把eclipse运行文件拖放到系统的面板上,给它一个名字和图标,今后就可以直接点这个面板图标启动Eclipse了。

    呵呵,总算看到熟悉的Eclipse界面,一种亲切感油然而生,不是吗?这个Eclipse已经自带Java开发环境,如果想做C/C++,Eclipse下面的CDT也很不错,当然了,以前N多插件也是照用不误,接下来怎么弄就看大家自己了。:)

    posted @ 2005-10-05 13:08 laogao 阅读(9844) | 评论 (7)编辑 收藏


    这里是新闻链接:
    http://www.sdmagazine.com/pressroom/rc2005_winners.html

    大致总结一下:
    最佳雇主 - Google
    最佳GUI - Visual Studio
    最佳开源工具 - Eclipse
    最佳脚本语言 - Perl
    最健壮工具 - Linux

    其余的大家看看原文吧. :)


    posted @ 2005-10-05 11:00 laogao 阅读(693) | 评论 (0)编辑 收藏

     

    前面我们提到安装Linux和通过图形桌面如GNOMEKDE使用Linux已经相当简单和直接。不过很多时候,我们都需要通过命令行来执行一些命令,这不仅是当没有图形桌面时必须的方式,而且也是在各个发行版中相对统一的操作方式,使用恰当的话往往比GUI还要来得方便和直接。关键的问题是,GNOME或者KDE这样的X-Window仅仅是Linux发行版的一个子系统,要发挥Linux的威力,有时候还非得CLI(Command Line Interface)不可。

     

    从图形桌面进入CLI有两种途径:

    1- 从启动菜单或者工具条上点击Shell打开Shell窗口;

    2- 由于Linux直接支持多用户,所以可以使用Ctrl-Alt-F6切换到命令行模式,然后按照CLI的方式进行用户验证和登录。(切换回图形桌面的快捷方式是Ctrl-Alt-F7,在切换回来之前,作为一个好的习惯,应该先登出。)

     

    我们这就来看看常用的CLI命令。

     

    1- ls 列举当前目录下的文件清单

    2- cp 拷贝文件

    3- rm 删除文件/目录

    4- mv 移动目录

    5- cd 改变工作目录

    6- mkdir 创建新目录

    7- tar 解压缩

    8- whoami 查询当前登录用户名

    9- finger 查询其他用户信息

    10- mount 加载设备

     

    另:对于所有的CLI命令,可以用man [命令名]来获取详细的使用方法。在这里我只是列举出一些常用的作为备份,估计也够玩一阵子了,接下来的专题中再按功能划分具体分析吧。

     

     

    posted @ 2005-09-27 13:20 laogao 阅读(523) | 评论 (0)编辑 收藏

     

    开始学习Linux,首要的步骤当然是找一个Linux发行版本和一台空闲的PC机,把Linux的环境搭建起来。这里先说明一下LinuxGNU/Linux:通常我们提到的Linux都是指得GNU/Linux,我也沿用这个习惯。狭义上的Linux仅仅是指由Linus Torvalds发起的在x86体系下的类Unix操作系统内核,该内核的最新版本汇总在http://www.kernel.org/上。我们日常看到的Linux发行版都是在此基础上增加了很多GNU的软件项目组成的合集。

     

    我个人比较推荐的发行版是NovellSuSE LinuxDebian,更常见的也许是Fedora Core(由Red Hat分支出来的免费版本)。

     

    目前主流的Linux发行版都对安装过程做了极大的简化,我们安装Linux通常需要做的跟安装Windows几乎同样简单,甚至更简单。当你真正接触到这些的时候,你还会发现一个相当有趣的使用方式:从光盘直接引导Linux,不需要对硬盘做任何改动,即可使用,虽然有些限制,因为一张光盘和系统本身的内存容量有限,但是这在Windows的世界是无法想象的。

     

    Linux的使用在出现了GNOMEKDE等图形桌面之后,更是变得格外易于使用,除了有些使用习惯上跟Windows有差别,在易用性上已经很接近了。

     

    笔者曾经一度在Linux门外徘徊,很多对Linux的认识都是来自各种媒体的评论和分析,其中不乏偏见和误解。我深信只有亲身体验得出的结论才是有价值的和可信的,至少应该对得起自己,于是决定放弃之前的所有猜测和臆断,花点时间进入Linux的世界,好好打探一番。

     

     

    posted @ 2005-09-26 16:34 laogao 阅读(510) | 评论 (1)编辑 收藏


    如果你对Microsoft为何推迟了Longhorn (Vista)的发布、以及这次Microsoft公司结构调整的来由的话,下面这篇华尔街日报Wallstreet Journal的报道也许是一个不错的切入点:

    http://online.wsj.com/article/0,,SB112743680328349448,00.html

    文章中讲到不少对这次变革起到重要作用的人,其中当然包括负责微软平台产品和服务部门的主管之一Jim Allchin。作为这次微软内部结构调整的一部分,他将在Vista上市后退休。这次变故背后发生了什么?WSJ.com的报道会告诉你一些你也许还不知道的故事。

    posted @ 2005-09-26 14:45 laogao 阅读(358) | 评论 (0)编辑 收藏


    接着上一节20050921讲,我们前面讲到了从1到6的英语词根,我们来对比一下法语的这六个数字:
    un/une(1) deux(2) trois(3) quatre(4) cinq(5) six(6)
    是不是能够找到些影子呢,只是因为很多英语的单词都来自法语,有些更是间接的通过法语从拉丁语继承过来。

    今天我换一种方式,不一上来就一个个词根的讲,我们先来看看这一组词:
    septem
    octo
    novem
    decem

    怎么样?你能发现其中的有趣之处吗?没错,在它们后面加上"ber"就分别对应了九月、十月、十一月和十二月。先别妄下结论,且等我讲清楚它们分别代表的含义:
    septem源自拉丁,意为7;
    octo源自拉丁,意为8;
    novem源自拉丁,意为9;
    decem源自拉丁,意为10。

    发现了吧,正好比它们代表的月份少了2。这是因为目前国际通行的日历是公历,确切的说,是Gregorian Calendar,是由格里高利十三世教皇于1582年开始推行的,计算方法是从冬至的后面第十天作为年度之间的分水岭,包括闰年等概念也是从这个历法来的。在这之前,欧洲各国曾经通行过的是罗马历。上述月份名称即是由罗马历延续下来。

    简单举些例子:
    - 大家记得七匹狼这个牌子英文是什么?Septwolves对吧,人家可不是拍脑袋想的。
    - 八爪章鱼怎么说?octopus。
    - 记得我们Java和很多类C语言中如何来表示八进制的数值吗?对,前面加"o"。
    - 天主教的一种连续9天的祈祷仪式叫做novena。
    - 十进制的数字怎么称呼?decimal。
    - 代表六的词根还记得吗?hex。那么hexdecimal的意思是?十六进制。

    呵呵,挺有意思的吧?我觉得这样学英语还是蛮有趣的,大家不妨换个角度来学习英语,成天背单词那其实不叫学英语,也很难说有多好的效果。

    // 声明:七匹狼和Septwolves乃福建七匹狼实业股份有限公司注册商标。

    posted @ 2005-09-22 21:10 laogao 阅读(686) | 评论 (3)编辑 收藏


    最近似乎对代表数字的词根颇有兴趣,今天的专题就来说说这一块。

    首先来看UNI,也就是“一”,表示一个、单独、唯一的意思。常见的单词有:uniform制服、unify统一(着装等)、unite统一/联合、union联盟、unilateral一致、unique唯一、unit单元、universe宇宙等等等等。

    接下来看一看BI和D(O)U,分别有“二”和“双”的意思。常见的单词有:bicycle自行车(两轮车)、bilingual双语的、bidirectional双向的、dual双、duet二重唱/二重奏、double双倍等等。

    再接下来看看TRI,代表“三”。常见的单词有:triangle三角形、triple三倍等。

    再往下当然是QUARTER/QUADRI,代表“四”。常见的单词有:quarter一刻钟(一小时的1/4)/季度(一年的1/4)、quarter-final四分之一决赛、quadruple四倍、quartet四重奏等等。

    然后来看看QUINT/PENT,代表“五”。常见的单词有:quintuple五倍、quintet五重奏、pentagon五边形、pentagram五角星等。

    再就是HEX了,代表“六”。常见的单词有:hexagon六边形、hexameter六步格(诗)等。

    好了,今天累了,先讲到这儿吧,明天继续说七八九十等。

    posted @ 2005-09-21 23:22 laogao 阅读(459) | 评论 (0)编辑 收藏


    今天讲两个跟数字相关的词根:MILL和SEMI。

    MILL指的是一千或者一千分之一,常见的单词有:million百万(一千个一千,西方是3位数字一组,区别于我们的4位,或者说,万。)、millenium千年、millimeter毫米(一米的千分之一)等等。

    SEMI源自拉丁语,指的是一半,常见的单词有:semifinal半决赛、semiconductor半导体、semicircle半圆形等等。

    posted @ 2005-09-20 23:07 laogao 阅读(376) | 评论 (0)编辑 收藏


    IBM的developerWorks上周发布了一篇关于JUnit 4的预览文章,原文见:
    http://www-128.ibm.com/developerworks/java/library/j-junit4.html

    下一版的JUnit(JUnit 4)是相对很大的一次升级,比较值得一提的改动有:J2SE 5.0注解、不再要求extends TestCase、不再要求一定的测试方法的命名、异常处理、超时机制等。感兴趣的朋友看看上面的链接,有代码示例的。

    不过如其名称所暗示,JUnit始终是针对单元测试,如果你需要更强的控制和配置,测试更复杂的test cases,也许还应该考虑一下TestNG。

    posted @ 2005-09-19 13:48 laogao 阅读(647) | 评论 (0)编辑 收藏


    接着20050905的题目讲。还是来自Robert Frost的名言:

    The world is full of willing people, some willing to work, the rest willing to let them.

    willing在这里是乐意、愿意、心甘情愿的意思。世界上充满了乐意之人,有些乐意工作,剩下的则乐意让这些人(工作)。选择什么样的生活,如何才是快乐,其实很大程度上取决于你自己。

    posted @ 2005-09-19 12:38 laogao 阅读(491) | 评论 (1)编辑 收藏


    这个赛季的英超才打到第5轮,突然变得沉闷起来,因为Chelsea的强大攻势和惊人稳固,还是其他老牌强队Arsenal、Man Utd、Liverpool的状态低迷?我的英超热情在锐减,我的心在流血。Chelsea的球迷请原谅,但是Chelsea是英超中我唯一不喜欢也不可能喜欢的球队。在我的心中,英超本应属于红色。

    现在连英国卫报的足球专栏都抛出了这样的疑问:“英超本赛季已经提前结束了吗?”原文见:
    http://football.guardian.co.uk/Columnists/Column/0,4284,1572157,00.html

    posted @ 2005-09-18 13:55 laogao 阅读(423) | 评论 (0)编辑 收藏


    今天讲一讲两个词根。

    第一个是phobia,常用作名词的后缀,该词根源自希腊文的phobos,意为恐惧某样事物。常见的一个词是acrophobia,恐高症。acro在这里有高空、悬空之意。(参考acrobatics - 杂技)常常有些广告宣传、报章文摘都会用这个词根来造一些新名词,也许有些牵强,不过"恐韩症"也许可以译作"Koreaphobia"?

    第二个也许就更常见,跟phobia是相反的意思,源自希腊文的menos,mania,意为对某样事物极度狂热。这个mania也经常被媒体用来组合成一些新名词,如game-mania、XBOX-mania、Java-mania、.NET-mania等,皆为此意。补充说一下就是这个mania跟fever、addiction这些词也许有些相近的解释,但比较起来要中性的多,更多的是强调这个热情的含义,使用的时候请注意这些细微的区别。

    posted @ 2005-09-18 13:31 laogao 阅读(547) | 评论 (2)编辑 收藏


    在Slashdot上面看到这个链接,很有意思:
    http://www.ranum.com/security/computer_security/editorials/dumb/

    简单用中文转述一下,感兴趣的请看原文。

    作者认为在计算机安全领域有很多我们常识性的错误的理解和观点,最严重的6条分别是:
    1- 默认允许 - 很多东西在我们的系统中都是默认允许的,如程序、端口等,有必要吗?
    2- 枚举不好的东西 - 如果我们只需要关心那些东西是我们真正需要的,岂不是比列出那些我们不需要的来得更方便?(我们真的需要和黑客们搞“军备竞赛”?)
    3- 渗透然后打补丁- 很多软件厂商都是找人来测试系统安全漏洞,然后争取在黑客利用它们之前发布给客户让客户去打补丁,这样真的是一个好办法吗?(作者举的例子是IE)
    4- 黑客很酷 - 很多媒体都有意无意在美化一些不好的事物和行为,比如黑客。
    5- 培训/教育用户 - 为什么我们要教育用户不要这样不要那样,有这个必要吗?很多简单的道理和使用习惯往往是你无法预知和阻止用户去做的,除非你从源头上杜绝用户作出这种选择的可能。
    6- 为好过无为 - 这就跟中国的道家思想有关了,在我们准备要开始安装和使用一个新的软件或工具时,我们最好停下来先想一想,观察观察。

    作者还总结了一些相对不那么严重的错误观点,如:

    - 我们不会是攻击对象
    - 如果大家都随时打补丁所有人就安全了
    - 我们不需要防火墙因为我们有很好的主机安全机制
    - 我们不需要主机安全机制因为我们有很好的防火墙
    - 我们先用起来,稍后再处理安全性问题
    - 我们无法阻止偶然发生的问题

    最后这一点很逗,作者举的例子是如果你认为航空业用这种方式来对待你的生命时,你还会乘坐商业航空公司的飞机吗?

    posted @ 2005-09-13 22:32 laogao 阅读(451) | 评论 (0)编辑 收藏


    项目中杂七杂八的事情太多,有一周时间没有更新了,望各位见谅。

    再来一句Robert Frost的名言:
    The best way out is always through.

    稍微解释一下,way out指的是出路,out作为修饰语,放到了way的后面,这是英文中常见的用法,through在这里指“穿过”、“(亲身)经历”。整句话的意思是,(遇到困难时)最好的出路永远都是穿过它。我们在工作、学习和生活中,经常都会遇到困难和挫折,每每这个时候我们都会条件反射似的抵触或者避重就轻,然而回避问题从来都不是解决问题的正道,最终我们还是不得不面对。英文其实在很多时候也很简练和形象的,比如这句话,没有晦涩的字眼,短短7个单词,却勾划出一个景象:当你陷入困境,比如前方是未知且充满险恶的丛林和沼泽,或者你已经身陷其中,你想逃避和退缩,离开这个鬼地方,但其实你最好的出路不是回头,不是东想西想,而是去坦然面对,踏踏实实去走过这一段荆棘密布的旅程。

    posted @ 2005-09-13 21:00 laogao 阅读(376) | 评论 (0)编辑 收藏


    The reason why worry kills more people than work is that more people worry than work.
    - Robert Frost

    Robert Frost是美国著名诗人,我还记得很早就在一本英语文摘上读到过他的诗句:

    Two roads diverged in a wood, and I--
    I took the one less traveled by,
    And that has made all the difference.

    后面这首小诗我就不多作解释了,估计很多地方都能看到。说说前面那一句:更多的人死于忧虑而不是工作的原因是,更多的人(成天)忧虑而非工作。

    观察一下我们周边的人,很多时候大伙儿都很浮躁,要么想得太多,要么抱怨太多,何苦来的呢?其实认认真真投入工作也许才能让自己真正的放松吧。我想有许多人和我一样,小时候总想不通问什么课本上讲劳动是快乐的,劳动多累啊,多辛苦啊,是不是啊?长大之后,这其中的道理才慢慢体会到。

    posted @ 2005-09-05 20:39 laogao 阅读(652) | 评论 (2)编辑 收藏


    I don't know the key to success, but the key to failure is trying to please everybody.
    - Bill Cosby

    Bill Cosby是美国的喜剧演员。上面的话估计没有大家不认识的单词,整句的意思是:我不知道成功的秘诀,但是失败的秘诀是试着让所有人都高兴。生活如此,工作中何尝不是这样呢?尤其当你走向管理岗位,你更需要学会说不。

    posted @ 2005-09-04 20:37 laogao 阅读(442) | 评论 (0)编辑 收藏


    走在欧洲的大街小巷、地铁口,经常能够看到拿着各种乐器表演的艺人,在英语中人们是怎么来称呼他们的呢?答案是:

    busker - a person who entertains especially by playing music on the street.

    其实类似的艺人在中国和北美甚至世界上许多地方应该都有,由于笔者在欧洲的感受比较多,就举欧洲为例了,这种表演形式已经融入了欧洲的某种意义上的城市文化。

    posted @ 2005-09-03 16:27 laogao 阅读(460) | 评论 (0)编辑 收藏


    最近公司陆陆续续走了很多人,如今TheServerSide.com大名鼎鼎的Floyd Marinescu也离开了TSS。

    http://www.theserverside.com/news/thread.tss?thread_id=36276

    这是怎么了呢?

    posted @ 2005-09-02 11:57 laogao 阅读(732) | 评论 (1)编辑 收藏


    还记得去年微软的"Get The Facts"系列宣传指出的根据它赞助的评测结果,Windows系统的TCO - Total Cost of Ownership要明显低于Linux。今年IBM又根据其赞助的两项评测报告指出Linux的TCO要比Windows和Unix都低。

    根据InformationWeek的报道:
    http://informationweek.com/story/showArticle.jhtml?articleID=170102340

    其中一项调查涉及到对比分别在Linux、Windows、Solaris平台上搭建和运行一个应用服务器的成本,结果发现Linux比一个同等的x86 Windows服务器便宜40%,比同等的Sparc Solaris服务器便宜54%。三组最终总成本为:Linux - 40,149美元、Windows - 67,559美元、Solaris - 86,478美元。

    另一份调查报告显示,Linux在当今IT部门的经理和工程师们那里很受欢迎,并且许多教育和研究机构都非常接受Linux,使得今后的人才市场和产品市场对Linux都相当有利。

    时下的IBM、微软、Sun之间微妙的关系,是不是有点三国的味道了,呵呵。

    posted @ 2005-09-02 11:41 laogao 阅读(510) | 评论 (1)编辑 收藏


    根据CNET News.com的报道,目前Windows XP和Windows Server 2003中自带的Windows防火墙通过注册表的一些设置,使得用户通过Windows防火墙的界面无法看到所有打开的端口,其中包括Windows Firewall自己使用的端口。

    当然,消息一出,微软的网站上就给出了补丁,并将在今后的Service Pack中包括这一补丁。微软当然也有它的立场,它认为这并不是什么系统漏洞,但是对于已经遭到攻击的系统来说,这个安全隐患可以让攻击者隐藏自己的真实身份。

    它同时还指出,通过命令行
    netsh firewall show state verbose = ENABLE
    可以看到所有打开的端口,包括那些被Windows Firewall隐藏掉的。这样看来似乎微软并没有故意隐藏什么,但是既然Windows的GUI那么好用,有多少人真正还会用命令行去敲那么长一行命令去看哪些端口是打开的?

    防火墙是阻止我们的系统遭受外来攻击的第一道防线,相信很多人都认可它应该忠实的告诉用户哪些端口是屏蔽的,哪些是允许的,对吧?在这个环节上出现这种让用户头疼的问题实在有些不应该。

    原文见:
    http://news.com.com/Windows+Firewall+flaw+may+hide+open+ports/2100-7355_3-5845850.html

    posted @ 2005-09-02 10:59 laogao 阅读(520) | 评论 (0)编辑 收藏


    据外电报道,这次发生在美国南部沿海的Katrina(卡特利娜)飓风灾害对Mississippi(密西西比河)流域,尤其是New Orleans(新奥尔良)造成了严重的损失,当地成为一片汪洋,而在相关的报道和最新信息发布中,blog充当了重要的手段,很多当地和附近的居民都纷纷通过blog站点发布和获取最新的信息和救援指南,可见blog这种新闻传播和信息发布的形式在美国也挺受欢迎。

    现在飓风已经过去,但新的问题又来了,这么多居民的日常生活如何保障?于是就出现了居民打破门窗进入杂货店寻找食物的情况,更有甚者,开始了针对珠宝店等的武装抢劫,甚至向救援直升机开火。后面的我们不去说它,针对居民进入杂货店寻找食物一事,细心的blogger们也没闲着,很快发现了美联社和法新社的一组有争议的图片,并展开了激烈的讨论。我们还是别走太偏了,回到"Looting" or "finding"的主题,详细情况可以参考:
    http://www.salon.com/news/feature/2005/09/01/photo_controversy/


    根据Merriam Webster的解释,loot作为动词,意为强行夺取并拿走,尤指在战乱中;也指大型的通常是通过暴力或腐败进行敛财。相应的looting是名词,指强夺/抢劫/敛财的行为;looter指抢劫者。由此可见,这个looting并不是什么好词。引发了什么争议呢?大家感兴趣的话就通过上面的链接去看看吧,英文的,顺便练练阅读咯。

    posted @ 2005-09-01 23:48 laogao 阅读(365) | 评论 (0)编辑 收藏


    I respect faith, but doubt is what gets you an education.
    - Wilson Mizner

    美国剧作家Mizner的一句名言。faith意为信仰,get sb. sth.意为让某人得到某物,整句的意思是:我尊重信仰,但是真正能让你学到东西的是怀疑。

    posted @ 2005-08-31 20:28 laogao 阅读(332) | 评论 (0)编辑 收藏


    接着我的上一篇随笔来讲
    http://www.blogjava.net/sean/archive/2005/08/31/11618.html

    今天又看到另一篇提到:

    'As far as working with Microsoft on a study, Microsoft could probably find one negative line on Linux in a 100-page research report that it would spend $10 million marketing while ignoring the other 99 pages...'

    大意是MS做调研的话,很可能他们会抓住在长达100页的研究报告中对Linux的负面结论的一行,然后用数百万美元去做市场宣传,而忽略掉剩下的99页。类似的评价早就在TheServerSide.com听了很多了,今天再一次听到,看来怀疑MS调研结果的人还真不在少数啊。

    原文见:
    http://linux.slashdot.org/article.pl?sid=05/08/29/0625224

    posted @ 2005-08-31 17:30 laogao 阅读(346) | 评论 (0)编辑 收藏


    今天上午休假,在Slashdot上面看到这个链接:
    http://www.linux-watch.com/news/NS8124627492.html

    由于是英文,这里我简单用中文转述一下,不代表我个人观点,大家要是感兴趣还是看看原文吧,很有意思,也不必太较真,当作笑话看吧。

    作者是一个Linux狂人,至少是个高手,他所有的服务器、台式机、娱乐设备等等都是跑的Linux。但是他指出:Linux并不是给所有人准备的,这里面他认为有5大原因。

    1- Linux过于复杂。论据是尽管Linux有KDE和GNOME,你仍然时不时需要使用命令行以及修改一些配置文件;而Windows呢,你也时不时需要跑命令行,或者修改注册表,后者就像他们经常告诫过你的:很容易对你的系统造成不可挽回的破坏。

    2- Linux安装很麻烦。论据是当今的很多Linux版本需要你插入CD-ROM或者DVD-ROM,按回车、输入用户名和管理员密码,真的好麻烦哦;而Windows呢?你需要做同样上面这些事,然后立即下载最新的补丁,毕竟根据Symantec的报告,没有打补丁的Windows PC,如果连接上Internet,不超过数小时,就会有漏洞被人利用。至于没有打补丁的Linux,已然可以跑上数月,不过这并没有什么好笑的。

    3- Linux没有足够的应用程序。论据是Linux上边只附带了安全的应用程序如浏览器有Firefox、办公套件OpenOffice等等;而Windows呢,给我们提供了当今最流行的Intenet Explorer、Outlook Express、Windows/MSN Messenger等等,虽然他们都有这样或那样的小毛病,而且Windows上面还有MS Office对吧?可惜不是Windows自带的,需要额外购买。

    4- Linux不安全。论据是如果微软这么说,那么一定是真的。那又怎么样呢?如果你很难在一整周之内不读到又一个新的Windows的重大安全问题,那么你会相信谁?微软,还是你自己的眼睛?

    5- Linux更贵。论据是既然你可以免费下载到几乎所有的Linux通行版本,那些大的Linux供应商如Red Hat和Novell竟敢向你卖有偿服务或者产品;而Windows几乎都是在你购买的PC中“免费”预装的。等等,不是免费的吗?已经包含在PC价格中了?还占了很大一部分?不过没所谓了,它已经装好了,你需要的它都有,不是吗?对,不过你可能还是会考虑购买额外的杀毒软件、防间谍软件、全功能的防火墙等等,加起来差不多又要100美元。但是,如果你拥有了像Windows这样安全的操作系统,还需要这些干什么呢?

    posted @ 2005-08-31 12:02 laogao 阅读(563) | 评论 (2)编辑 收藏


    Whatever you do will be insignificant, but it is very important that you do it.
    - Mahatma Gandhi

    甘地大家都认识,说说我对这句话的理解。insignificant意思是无足轻重、无关紧要的,整句话的意思是:无论你做什么,都将是无足轻重的,但是去做是极其重要的。这个是什么道理呢?我想有两层含义,或者说两种不同的解读:

    1- 你需要去做的事情也许看上去不重要,但是a)积少成多,大家都做,坚持做,或者说b)对别人而言,最终的效果是相当有价值也是相当可观的,有点类似“勿以善小而不为”。
    2- 通俗地讲,就是“重在过程、重在参与”,结果不必去想太多,踏踏实实把手头事情做好,远离名利和纷争,去追求心灵的平和。

    顺便说一下,对于类似的文字,怎么理解完全是你自己的事,你当然可以有完全不同的见解。北大校长蔡元培曾经有句话,叫做“多岐为贵,不取苟同”,如果大家想的都一样,有什么意思呢?对于我的这个系列,如果你有自己的见解,也欢迎拿出来跟大家分享。

    posted @ 2005-08-29 23:45 laogao 阅读(405) | 评论 (1)编辑 收藏


    In the end, we will remember not the words of our enemies, but the silence of our friends.
    - Martin Luther King Jr.

    美国的著名黑人民主权力领袖马丁·路德·金相信大家都听说过吧?这句话没有什么高深的辞藻,却很切中要害:最终,我们不会记得敌人的言语,却无法忘记朋友的沉默。伤人至深的往往不是来自敌方的抨击或伤害,而是来自友方的冷漠。

    posted @ 2005-08-28 21:01 laogao 阅读(333) | 评论 (0)编辑 收藏

     

    PMO是什么?它可以是很多不同单词的组合,在这里,我要说的是Project Management Office。请原谅我的孤陋寡闻,PMO的概念其实在两年以前就已经是业界的buzzword了,而我直到最近才因为工作的原因接触到这个概念。

     

    在这篇随笔里面,让我们初步的探讨一下,为什么我们需要PMO,或者说,PMO应该具备怎样的职能呢?

     

    PMO可以说是随着IT产业的潮流应运而生的产物,最初的目的是节约成本,提高项目成功率,以及实施标准流程,以应对越来越多的项目管理任务。虽然它在节约成本和提升项目管理质量上目前还很难有一个可量化的指标,但是越来越多的公司和企事业单位在它们的IT部门设立集中的PMO,统管所有IT项目。

     

    按照比较公认的说法,PMO的核心职能包括:

    1- 定义并推行可重用的项目管理流程;

    2- 集中控制项目进展和资源调配。

     

    仔细想一想,也许我们有两种不同侧重点的PMO:一种是顾问型的,为项目经理提供培训、指导和最佳实践;另一种是集中式管理型,将项目经理集中到PMO,然后派往不同的项目,最终由PMO统一控制所有项目和资源。

     

    我相信国内很多公司应该是更倾向于后者,一方面,项目管理或者说软件工程本来就是一门艺术,很难有一个定式,就算有再多的“最佳实践”,根据项目具体情况的不同,也很难保证它们就一定适用,现实中要找到真正管理经验丰富,可以向别人提供理论指导的人才,并非那么容易;另一方面,后者能够更加直接的体现出PMO存在的价值,不光是直接的具体的项目管理,也有利于确定不同项目的类型和轻重缓急,合理分配资源。

     

    当然,如果一个PMO最终做成一个完全意义上的行政部门的话,它也不应该同公司的企业文化相冲突,它起到的作用也应该更多的体现在如何去将项目的失败和公司的亏损减到最低限度,如何提高公司的项目管理水平,而不是一味的、机械的通过所谓的“标准流程”处理项目的实际问题,或者仅仅是一个跟踪项目进度,通常以一种管理者的姿态去命令各个项目组的部门。它应该同公司的各个相关部门:如CIOCAOQAO,以及具体的项目组、公司财务和高层管理部门共同协作,促进公司各个项目的顺利实施。

     

    一个比较常见的、直观的说法是,PMO需要保证所有其属下的PM具备管理当前项目的能力。而从长远来看,最理想的PMO能够给公司的IT部门带来持续不断的业绩提升。

     

    先说到这,关于本话题,今后也许会有更多后续文章。同时欢迎大家参与讨论!

     

     

    posted @ 2005-08-28 00:15 laogao 阅读(1446) | 评论 (2)编辑 收藏


    学英语并不一定是要拿着书本甚至字典去啃,日常的积累很重要。今后这一专题我会时不时放些短小精悍的句子或者短语,并做些注释,当作消遣也好,学习也好,随大家自己了。

    作为开篇,我们来看看美国喜剧演员Rita Rudner的一句精辟的关于好莱坞婚姻的总结:
    In Hollywood a marriage is a success if it outlasts milk.

    是什么意思呢?outlast在这里是"比......更持久的意思",我们知道,牛奶通常只能保持几天的新鲜,而在好莱坞,如果一段婚姻能够比牛奶还要更持久,那么它就成功了。

    posted @ 2005-08-27 23:00 laogao 阅读(377) | 评论 (0)编辑 收藏


    http://www.personal.psu.edu/users/j/r/jrk132/tech.swf


    呵呵,最近总能看到一些好玩的东东。

    posted @ 2005-08-19 14:29 laogao 阅读(426) | 评论 (1)编辑 收藏


    发现一组很可爱的英文自制明信片,也许我们更能接受用这种方式说出自己心中的秘密?

    http://postsecret.blogspot.com.nyud.net:8090/

    看过之后大概会发现原来这个世界上跟你有着相同/相似经历和想法的人还很多,其实你并不那么特殊和另类,你说呢?这些明信片很平民化,也很艺术,而最最重要的,我想,是它们很可爱。怎么样,有没有突然想创作的冲动?

    // 注意:由于其中有相当多的美式俚语,题材也较前卫,请慎入。

    posted @ 2005-08-18 16:42 laogao 阅读(591) | 评论 (0)编辑 收藏


    http://ubergeek.tv/article.php?pid=54

    有点意思。权当一笑,轻松一下。

    posted @ 2005-08-18 12:36 laogao 阅读(380) | 评论 (0)编辑 收藏


    经过了漫长的夏季,英超终于又回来了。经常看英超的朋友都知道,每个赛季最开始的两轮都会有意安排多场重头戏。我们暂且不算上周末的社区盾杯,看看本周末都有哪几场重要而好看的赛事直播:

    首先当然是英超首场:Everton vs. Man. Utd. - 19:45~21:45

    Man. Utd.自不必说,在国内有N多铁杆球迷,这场球当然是必看,我觉得看点主要还是Phil Neville加盟Everton之后的首场英超就对阵Man. Utd.,其中还有自己的同门兄弟Gary。当然了,亚洲球员的表演也是噱头之一,且看能不能首发吧。

    然后是Aston Villa vs. Bolton Wanderers - 22:00~24:00

    接下来是Middelsbrough vs. Liverpool - 00:15~02:15

    明晚的赛事中,我必看的当然是Arsenal vs. New Castle Utd. - 20:30~22:30

    Arsenal最近状态要说起来还算是不错的,但是转会方面就有些让人揪心了,维埃拉走了,现役主力尤其是亨利真的都太累了,小将又还待成熟,真搞不懂俱乐部是怎么想的。还有就是中后卫的人选问题,Arsenal几乎总是会在这个位置上吃亏。估计这个赛季Arsenal的球迷可能又会比较郁闷。

    接下来是Wigan Athletic vs. Chelsea - 23:00~01:00

    没什么好说的,Chelsea本赛季依然可怕,甚至可以用独孤求败来形容,我们只能期望其他球队有超水平发挥了。这场比赛我甚至都懒得去看。

    // 以上比赛ESPN都有直播的,喜欢英超的朋友别错过了。

    posted @ 2005-08-13 10:45 laogao 阅读(442) | 评论 (1)编辑 收藏


    在Windows平台编写和运行SWT应用程序的最基本要求,除了一个可以编写文本文件的编辑器之外,是什么?三个东西:JDK、swt.jar和swt-win32-xxxx.dll,xxxx代表版本号,如在Eclipse SDK 3.1版本中附带的文件为swt-win32-3138.dll。其中JDK用于提供Java编译器和运行环境、swt.jar提供SWT使用到的类库、swt-win32-xxxx.dll提供平台支持库。

    以上是编写和运行SWT应用程序的最基本要求。大家可能都知道,SWT和Eclipse的关系非常密切,一方面,Eclipse基于SWT,而SWT大量的被使用在Eclipse的插件中。那么在如果我们要独立运行一个SWT应用,如何来配置它的运行环境呢?我在这里跟大家分享一下在Windows环境运行SWT的最基本,也是最省事的一种配置方案:

    1- 安装JRE并按照常规方式配置JAVA_HOME、CLASSPATH和PATH等环境变量;
    2- 由于3.1版针对SWT组件的plugin目录安排跟3.0版有很大的不同,而且今后在这一点上很有可能再次发生重大变更,所以我建议大家直接从eclipse.org上下载单独的SWT包;
    3- 拿到swt.jar之后,拷贝到JRE安装目录下的lib\ext中;
    4- 拿到swt-win32-xxxx.dll之后,拷贝到JRE安装目录的bin中;
    5- 在命令行直接敲java [完整类名]即可。

    我也看到有人提出的另一个更“变态”的方案,连JRE的安装都省了,直接把JRE目录一起拷贝出来,在相应的位置加上swt.jar和swt-win32-xxxx.dll,然后直接用jre\bin下面的java.exe。我想不出比这个更简便,同时又保持Java本质的方法了。不过由于我所用到的PC无一例外都安装了JDK,时间关系我就不做实验了,据说是完全行得通的。

    posted @ 2005-08-11 14:36 laogao 阅读(2199) | 评论 (5)编辑 收藏


    向大家推荐一个优秀的网站:
    http://www.bloglines.com/



    在这里,你可以订阅blog站点、搜索超过6亿篇索引文章、发布自己的blog随笔、以及跟朋友分享你的发现。在使用Bloglines的服务之前,我都是直接上各大新闻站点,或者在自己的RSS阅读器里进行订阅。前一种途径无疑是费时费力的,后者稍好一点,但是一方面你要去维护一个RSS列表,很多需要自己去找新的感兴趣的站点和RSS源,且不说寻找好的RSS源是比较费时间的,为了相对平衡而较少垃圾信息的日常阅读需要,单靠自己去从零开始寻找也不现实;另一方面,假如你跟我一样每天可能要用到不同的PC、Laptop或者甚至不同的操作系统,要在这些环境中同步阅读资源也很困难甚至是Mission : Impossible。或者说得白一点,你仅仅为了阅读和了解最新的信息,有必要弄得这么费劲吗?

    Bloglines相当于是一个在线RSS阅读器,你的订阅和个性化设置都在同一个地方维护着。其实我最喜欢Bloglines的地方是它提供了一组精选的RRS列表,包括Reuters、BBC、New York Times、Guardian、Slashdot等等重头的新闻类网站的RSS,所有这些都可以通过Bloglines一次性轻松获取,满足日常阅读需要。重大事件第一时间知晓,比如昨天发现号成功着陆,Reuters的RSS报道只比发生时间延后4分钟左右。我一直有阅读英文报章的习惯,但是在发现Bloglines之前可以说没什么条理性,现在好多了。当然,Bloglines也支持自定义的RSS源和发布自己的blog,这就使得Bloglines的服务更加贴心。

    注册Bloglines很简单,只需要一个电邮地址,自定义的密码,收到确认信后点击确认链接即可。并且这是免费的服务,诚意向大家推荐!

    posted @ 2005-08-10 13:01 laogao 阅读(794) | 评论 (3)编辑 收藏


    今天发现,博客园cnblogs的各博客主页可以通过二级域名的方式访问了,如:

    http://sean.cnblogs.com/

    什么时候BlogJava也能提供该多好!

    posted @ 2005-08-09 15:18 laogao 阅读(548) | 评论 (3)编辑 收藏

     

    最近看到BlogJava上有人在讨论为什么Java范型不支持数组http://www.blogjava.net/myqiao/archive/2005/08/08/9580.html

     

    我想这个问题的答案是:因为这样做会破坏类型安全。核心的问题在于Java范型和C#范型存在根本区别:Java的范型停留在编译这一层,到了运行时,这些范型的信息其实是被抹掉的;而C#的范型做到了MSIL这一层。Java的做法不必修改JVM,减少了潜在的大幅改动和随之而来的风险,也许同时也反映出Java Bytecode规范在设计之初的先天不足;C#则大刀阔斧,连CLR一起改以支持更彻底的范型,换句话说,在范型这一点上,感觉C#C++一点。

     

    Java中,Object[]数组可以是任何数组的父类,或者说,任何一个数组都可以向上转型成它在定义时指定元素类型的父类的数组,这个时候如果我们往里面放不同于原始数据类型 但是满足后来使用的父类类型的话,编译不会有问题,但是在运行时会检查加入数组的对象的类型,于是会抛ArrayStoreException

     

    String[] strArray = new String[20];

    Object[] objArray = strArray;

    objArray[0] = new Integer(1); // throws ArrayStoreException at runtime

     

    因为Java的范型会在编译后将类型信息抹掉,这样如果Java允许我们使用类似

     

    Map<Integer, String>[] mapArray = new Map<Integer, String>[20];

     

    这样的语句的话,我们在随后的代码中可以把它转型为Object[]然后往里面放Map<Double, String>实例。这样做不但编译器不能发现类型错误,就连运行时的数组存储检查对它也无能为力,它能看到的是我们往里面放Map的对象,我们定义的<Integer, String>在这个时候已经被抹掉了,于是而对它而言,只要是Map,都是合法的。想想看,我们本来定义的是装Map<Integer, String>的数组,结果我们却可以往里面放任何Map,接下来如果有代码试图按原有的定义去取值,后果是什么不言自明。

     

    所以,Java编译器不允许我们new范型数组。

     

     

    posted @ 2005-08-09 09:36 laogao 阅读(5149) | 评论 (3)编辑 收藏

     

    在前面的随笔中,我们一起过了一遍Jakarta Commons这个类库中非常重要的三个子项目:Commons LangCommons BeanUtilsCommons Collections,这些工具包在无数开源或商业框架中都可以找到,可以说应用范围非常广。

     

    当然,Jakarta Commons提供的API远不止我们提到的这些,除了上述三个核心项目之外,还有读取和映射XML文档的Digester/Betwixt、处理命令行参数的CLI、提供常用编码算法的Codec、用于读取多种格式的配置文件的Configuration、发送电子邮件的Email、上传文件的FileUpload、模拟HTTP客户端的HttpClient、处理日志的Logging等等等等,实在是相当的丰富。

     

    Jakarta Commons官网上可以找到完整的组件列表:

    http://jakarta.apache.org/commons/

     

    今后如果发现特别有价值需要跟大家分享的,我还会贴出来,只是不会像这样有条理和规律了。希望我的这一组笔记对大家了解和认识Jakarta Commons有所帮助,也希望这些优秀的类库及其源码能够给大家带来工作效率和编程功底上的提升。

     

    我整理了一份清单,列出了所有这一系列随笔的链接,方便大家查找和阅读:

    http://www.blogjava.net/sean/articles/Jakarta_Commons_Notes.html

     

     

    posted @ 2005-08-06 12:56 laogao 阅读(1676) | 评论 (1)编辑 收藏

     

    来看最后一组 – Iterator

     

    LoopingIterator

    ArrayListIterator

    FilterIterator

    UniqueFilterIterator

    IteratorUtils

     

    java.util.Iterator接口定义了标准的Collection遍历方法,但是如果不做改变的使用它,我们得到的是从头到尾一次性的遍历。假如我们需要循环遍历,假如我们需要遍历某一段,假如我们需要遍历满足某些条件的元素,等等等等,我们就不能完全依赖于这个Iterator的标准实现了。除非我们宁可在此基础上在调用的代码中多加一些判断,不过这样的话代码就会显得混乱,时间长了就容易变得难以维护。Commons Collections的这一组Iterator为我们带来了便利。

     

    这些Iterator使用都很一目了然,直接看例子吧:

     

    package sean.study.commons.collections;

     

    import java.util.Arrays;

    import java.util.Iterator;

    import java.util.List;

     

    import org.apache.commons.collections.Predicate;

    import org.apache.commons.collections.iterators.ArrayListIterator;

    import org.apache.commons.collections.iterators.FilterIterator;

    import org.apache.commons.collections.iterators.LoopingIterator;

    import org.apache.commons.lang.StringUtils;

     

    public class IteratorUsage {

     

        public static void main(String[] args) {

            demoIteratorUsage();

        }

       

        public static void demoIteratorUsage() {

     

            System.out.println(StringUtils.center(" demoClosureUsage ", 40, "="));

           

            // data setup

            String[] weekDays = {

                "Monday", "Tuesday", "Wednesday",

                "Thursday", "Friday", "Saturday", "Sunday"

            };

            List weekDayList = Arrays.asList(weekDays);

           

            // workdays

            Iterator iter1 = new ArrayListIterator(weekDays, 0, 5);

            printColl("Partial:", iter1, 5);

           

            // loop

            Iterator iter2 = new LoopingIterator(weekDayList);

            printColl("Loop:", iter2, 10);

           

            // looping workdays

            Predicate notWeekendPredicate = new Predicate() {

                public boolean evaluate(Object obj) {

                    String str = (String) obj;

                    if ("Saturday".equalsIgnoreCase(str)) {

                        return false;

                    }

                    if ("Sunday".equalsIgnoreCase(str)) {

                        return false;

                    }

                    return true;

                }

            };

            Iterator iter3 = new FilterIterator(

                new LoopingIterator(weekDayList),

                notWeekendPredicate

            );

            printColl("No Weekends loop:", iter3, 12);

           

            System.out.println(StringUtils.repeat("=", 40));

     

        }

       

        public static void printColl(String label, Iterator iter, int maxCount) {

            if (StringUtils.isNotBlank(label)) {

                System.out.println(label);

            }

            int i = 0;

            while (iter.hasNext() && i < maxCount) {

                System.out.println("# " + iter.next() + " #");

                i++;

            }

        }

     

    }

     

    运行结果如下:

     

    =========== demoClosureUsage ===========

    Partial:

    # Monday #

    # Tuesday #

    # Wednesday #

    # Thursday #

    # Friday #

    Loop:

    # Monday #

    # Tuesday #

    # Wednesday #

    # Thursday #

    # Friday #

    # Saturday #

    # Sunday #

    # Monday #

    # Tuesday #

    # Wednesday #

    No Weekends loop:

    # Monday #

    # Tuesday #

    # Wednesday #

    # Thursday #

    # Friday #

    # Monday #

    # Tuesday #

    # Wednesday #

    # Thursday #

    # Friday #

    # Monday #

    # Tuesday #

    ========================================

     

    有了这些实用的Iterator类,我们就可以轻松的实现可配置的遍历行为了。

     

     

    posted @ 2005-08-06 12:47 laogao 阅读(1844) | 评论 (0)编辑 收藏

     

    接下来看Closure组。

     

    Closure

    ChainedClosure

    IfClosure

    WhileClosure

    ClosureUtils

     

    Closure这一组接口和类提供一个操作对象的execute方法,为我们在处理一系列对象时可以将处理逻辑分离出来。理论上讲,使用Transformer也可以达到类似的效果,只要输出对象和输入对象是同一个对象就好,但是Closure接口定义的execute方法返回void,并且从效果和功能区分上,Closure可以更好的诠释对象处理或执行的意思。而事实上,ClosureUtils中也提供了一个asClosure方法包装一个现成的Transformer

     

    沿用前面的Emploee类,我们来给一组员工涨工资:

     

    package sean.study.commons.collections;

     

    import java.util.Arrays;

    import java.util.Collection;

    import java.util.Date;

    import java.util.Iterator;

     

    import org.apache.commons.collections.Closure;

    import org.apache.commons.collections.CollectionUtils;

    import org.apache.commons.lang.StringUtils;

     

    public class ClosureUsage {

     

        public static void main(String[] args) {

            demoClosureUsage();

        }

       

        public static void demoClosureUsage() {

     

            System.out.println(StringUtils.center(" demoClosureUsage ", 40, "="));

           

            // data setup

            Employee[] employees = new Employee[] {

                new Employee("Tony", 26, new Date(), "E4", 2000),

                new Employee("Michelle", 24, new Date(), "E4", 2000),

                new Employee("Jack", 28, new Date(), "E5", 3000)

            };

            Collection empColl = Arrays.asList(employees);

            printColl("Before salary increase:", empColl);

           

            // closure setup

            Closure salaryIncreaseClosure = new Closure() {

                public void execute(Object obj) {

                    Employee emp = (Employee) obj;

                    emp.setSalary(emp.getSalary() * 1.20);

                }

            };

           

            // salary increase

            CollectionUtils.forAllDo(empColl, salaryIncreaseClosure);

            printColl("After salary increase:", empColl);

     

            System.out.println(StringUtils.repeat("=", 40));

        }

       

        public static void printColl(String label, Collection c) {

            if (StringUtils.isNotBlank(label)) {

                System.out.println(label);

            }

            Iterator iter = c.iterator();

            while (iter.hasNext()) {

                System.out.println(iter.next());

            }

        }

    }

     

    以下是运行结果:

     

    =========== demoClosureUsage ===========

    Before salary increase:

    Employee[name=Tony,age=26,dateJoined=2005-08-05,grade=E4,salary=2000.0]

    Employee[name=Michelle,age=24,dateJoined=2005-08-05,grade=E4,salary=2000.0]

    Employee[name=Jack,age=28,dateJoined=2005-08-05,grade=E5,salary=3000.0]

    After salary increase:

    Employee[name=Tony,age=26,dateJoined=2005-08-05,grade=E4,salary=2400.0]

    Employee[name=Michelle,age=24,dateJoined=2005-08-05,grade=E4,salary=2400.0]

    Employee[name=Jack,age=28,dateJoined=2005-08-05,grade=E5,salary=3600.0]

    ========================================

     

    我这里举的是一个相对简单的例子,在Closure这一组还有一些很方便的类,如ChainedClosure可以包装一组Closure作为整体执行;IfClosure在创建时需要提供给它一个Predicate和两个Closure,执行时先做Predicate判定再决定执行哪一个ClosureSwitchClosureSwitchTransformer类似,根据创建时传入的Predicate组和Closure组对应执行;WhileClosure则根据创建时传入的Predicate做判断,如果为true则执行Closure,直到Predicate返回false;等等。

     

    具体用法请参考Javadoc

     

     

    posted @ 2005-08-06 12:31 laogao 阅读(2134) | 评论 (1)编辑 收藏

         摘要:   接下来看Transformer组。   Transformer ChainedTransformer SwitchTransformer TransformerUtils   我们有时候需要将某个对象转换成另一个对象供另一组方法调用,而这两类对象的类型有可能并不是出于同一个继承体系的,或者说出了很基本的Object之外没有共同的父类,或者我们根本不...  阅读全文

    posted @ 2005-08-06 10:40 laogao 阅读(2650) | 评论 (1)编辑 收藏

     

    接下来看Predicate

     

    Predicate

    AndPredicate

    OrPredicate

    AllPredicate

    OnePredicate

    NonePredicate

    PredicateUtils

     

    PredicateCommons Collections中定义的一个接口,可以在org.apache.commons.collections包中找到。其中定义的方法签名如下:

     

    public boolean evaluate(Object object)

     

    它以一个Object对象为参数,处理后返回一个boolean值,检验某个对象是否满足某个条件。其实这个Predicate以及上一篇笔记提到的Comparator还有我们即将看到的TransformerClosure等都有些类似C/C++中的函数指针,它们都只是提供简单而明确定义的函数功能而已。

     

    跟其他组类似,Commons Collections也提供了一组定义好的Predicate类供我们使用,这些类都放在org.apache.commons.collections.functors包中。当然,我们也可以自定义Predicate,只要实现这个Predicate接口即可。在Commons Collections中我们也可以很方便使用的一组预定义复合Predicate,我们提供2个或不定数量个Predicate,然后交给它,它可以帮我们处理额外的逻辑,如AndPredicate处理两个Predicate,只有当两者都返回true它才返回trueAnyPredicate处理多个Predicate,当其中一个满足就返回true,等等。

     

    看看具体的代码中如何使用这些Predicate吧:

     

    package sean.study.commons.collections;

     

    import org.apache.commons.collections.Predicate;

    import org.apache.commons.collections.PredicateUtils;

    import org.apache.commons.collections.functors.InstanceofPredicate;

    import org.apache.commons.collections.functors.NotNullPredicate;

    import org.apache.commons.lang.BooleanUtils;

    import org.apache.commons.lang.StringUtils;

     

    public class PredicateUsage {

     

        public static void main(String[] args) {

            demoPredicates();

        }

       

        public static void demoPredicates() {

            System.out.println(StringUtils.center(" demoPredicates ", 40, "="));

            Predicate p1 = new InstanceofPredicate(String.class);

            Predicate p2 = NotNullPredicate.getInstance();

            Predicate p3 = new Predicate() {

                public boolean evaluate(Object obj) {

                    String str = (String) obj;

                    return StringUtils.isAlphanumeric(str)

                        && str.length() >= 6

                        && str.length() <= 10;

                }

            };

            Predicate p4 = PredicateUtils.allPredicate(new Predicate[]{p1, p2, p3});                String input = "ABCD1234";

            Object[] raw = new Object[] {

                "Is '",

                input,

                "' a valid input? ",

                BooleanUtils.toStringYesNo(p4.evaluate(input)),

                "."

            };

            System.out.println(StringUtils.join(raw));

            System.out.println(StringUtils.repeat("=", 40));

        }

     

    }

     

    输出结果如下:

     

    ============ demoPredicates ============

    Is 'ABCD1234' a valid input? yes.

    ========================================

     

    这里面我首先定义了3个简单的Predicatep1判断对象是否为String的实例,p2判断是否对象为nullp3是自定义的,判断是否为数字字母的组合,并且长度在6~10字符。然后我用AllPredicate将它们组合到一起,成为p4,当p1p2p3都满足时,p4evaluate方法才返回true。利用Predicate我们可以把判断truefalse的逻辑从特定的业务代码分离出来,以后我们重用也好,重新组装也好,都是很方便的。

     

    posted @ 2005-08-06 08:43 laogao 阅读(3393) | 评论 (4)编辑 收藏

         摘要:   接下来我们会讲到辅助类,首先看Comparator组。   ReverseComparator ComparatorChain NullComparator FixedOrderComparator ComparatorUtils   其实Comparator这个概念并不是Commons Collections引入的,在标准的Java Colle...  阅读全文

    posted @ 2005-08-06 08:40 laogao 阅读(2755) | 评论 (4)编辑 收藏

     

    接下来看看Collection组。

     

    TypedCollection

    CollectionUtils

     

    首先就是这个TypedCollection,它实际上的作用就是提供一个decorate方法,我们传进去一个Collection和需要的类型甄别信息java.lang.Class,它给我们创建一个全新的强类型的Collection。我们其实在bagbufferlistmapset这些子包中都可以找到分别对应BagBufferListMapSet接口的TypedXxxx版本。

     

    方法签名:

    public static Collection decorate(Collection coll, Class type)

     

    当它执行时,它会判断coll是否为null,同时如果coll包含数据,它会对数据进行验证,看是否满足指定的type条件。最后它返回一个强类型的Collection,当我们对这个强类型的Collection进行add操作时,它会帮我们确保添加的是正确的类型。

     

    而这个CollectionUtils可能大家都已经想到了,就是提供一组针对Collection操作的工具/静态方法。比较有意思的是对Collection的转型、合并、减等操作。

     

    由于这两个类的功能和作用都比较清晰,我就不举例说明了,需要进一步了解的请看Javadoc

     

     

    posted @ 2005-08-05 12:48 laogao 阅读(2151) | 评论 (0)编辑 收藏

     

    接下来看Map组。

     

    BidiMap

    MultiMap

    LazyMap

    MapUtils

     

    Commons Collectionsjava.util.Map的基础上扩展了很多接口和类,比较有代表性的是BidiMapMultiMapLazyMap。跟BagBuffer类似,Commons Collections也提供了一个MapUtils

     

    所谓BidiMap,直译就是双向Map,可以通过key找到value,也可以通过value找到key,这在我们日常的代码-名称匹配的时候很方便:因为我们除了需要通过代码找到名称之外,往往也需要处理用户输入的名称,然后获取其代码。需要注意的是BidiMap当中不光key不能重复,value也不可以。

     

    所谓MultiMap,就是说一个key不在是简单的指向一个对象,而是一组对象,add()remove()的时候跟普通的Map无异,只是在get()时返回一个Collection,利用MultiMap,我们就可以很方便的往一个key上放数量不定的对象,也就实现了一对多。

     

    所谓LazyMap,意思就是这个Map中的键/值对一开始并不存在,当被调用到时才创建,这样的解释初听上去是不是有点不可思议?这样的LazyMap有用吗?我们这样来理解:我们需要一个Map,但是由于创建成员的方法很“重”(比如数据库访问),或者我们只有在调用get()时才知道如何创建,或者Map中出现的可能性很多很多,我们无法在get()之前添加所有可能出现的键/值对,或者任何其它解释得通的原因,我们觉得没有必要去初始化一个Map而又希望它可以在必要时自动处理数据生成的话,LazyMap就变得很有用了。

     

    我们还是通过一个具体的例子来说明:

     

    package sean.study.commons.collections;

     

    import java.util.Date;

    import java.util.HashMap;

    import java.util.Map;

     

    import org.apache.commons.collections.BidiMap;

    import org.apache.commons.collections.Factory;

    import org.apache.commons.collections.MultiHashMap;

    import org.apache.commons.collections.MultiMap;

    import org.apache.commons.collections.bidimap.DualHashBidiMap;

    import org.apache.commons.collections.map.LazyMap;

    import org.apache.commons.lang.StringUtils;

     

    public class MapUsage {

     

        public static void main(String[] args) {

            demoBidiMap();

            demoMultiMap();

            demoLazyMap();

        }

     

        public static void demoBidiMap() {

            System.out.println(StringUtils.center(" demoBidiMap ", 40, "="));

            BidiMap bidiMap = new DualHashBidiMap();

            bidiMap.put("BJ", "Beijing");

            bidiMap.put("SH", "Shanghai");

            bidiMap.put("GZ", "Guangzhou");

            bidiMap.put("CD", "Chengdu");

            System.out.println("Key-Value: BJ = " + bidiMap.get("BJ"));

            System.out.println("Value-Key: Chengdu = " + bidiMap.getKey("Chengdu"));

            System.out.println(StringUtils.repeat("=", 40));

        }

     

        public static void demoMultiMap() {

            System.out.println(StringUtils.center(" demoMultiMap ", 40, "="));

            MultiMap multiMap = new MultiHashMap();

            multiMap.put("Sean", "C/C++");

            multiMap.put("Sean", "OO");

            multiMap.put("Sean", "Java");

            multiMap.put("Sean", ".NET");

            multiMap.remove("Sean", "C/C++");

            System.out.println("Sean's skill set: " + multiMap.get("Sean"));

            System.out.println(StringUtils.repeat("=", 40));

        }

     

        public static void demoLazyMap() {

            System.out.println(StringUtils.center(" demoLazyMap ", 40, "="));

            // borrowed from Commons Collection's Javadoc

            Factory factory = new Factory() {

                public Object create() {

                    return new Date();

                }

            };

            Map lazy = LazyMap.decorate(new HashMap(), factory);

            System.out.println(lazy.get("NOW"));

            System.out.println(StringUtils.repeat("=", 40));

        }

     

    }

     

    以下是运行结果:

     

    ============= demoBidiMap ==============

    Key-Value: BJ = Beijing

    Value-Key: Chengdu = CD

    ========================================

    ============= demoMultiMap =============

    Sean's skill set: [OO, Java, .NET]

    ========================================

    ============= demoLazyMap ==============

    Wed Aug 03 12:44:56 CST 2005

    ========================================

     

    简单说一下这个Factory,它是定义在org.apache.commons.collections包下面的一个接口,用于自定义对象的创建过程。这个有点像是后面我们要讲的Transformer的简化版本,但是也更直接也很好用,至少Commons Collections通过它向开发人员开放了一个可以方便控制对象创建细节的接口。

     

     

    posted @ 2005-08-05 12:23 laogao 阅读(4047) | 评论 (0)编辑 收藏

     

    来看Buffer组。

     

    Buffer

    BlockingBuffer

    BoundedFifoBuffer

    PriorityBuffer

    UnboundedFifoBuffer

    BufferUtils

     

    Buffer是定义在org.apache.commons.collections包下面的接口,用于表示按一定顺序除去成员对象的collection如队列等。具体的实现类在org.apache.commons.collections.buffer包下可以找到。

     

    BufferUtils提供很多静态/工具方法装饰现有的Buffer实例,如将其装饰成BlockingBuffer、执行类型检查的TypedBuffer、或者不可改变的UnmodifiableBuffer等等。

     

    最简单直接的Buffer实现类是UnboundedFifoBuffer,提供先进先出的大小可变的队列。而BoundedFifoBuffer则是对其大小进行了限制,是固定大小的先进先出队列。BlockingBuffer要在多线程的环境中才能体现出它的价值,尤其是当我们需要实现某种流水线时这个BlockingBuffer很有用:每个流水线上的组件从上游的BlockingBuffer获取数据,处理后放到下一个BlockingBuffer中依次传递。BlockingBuffer的核心特色通俗点说就是如果你向它要东西,而它暂时还没有的话,你可以一直等待直至拿到为止。PriorityBuffer则提供比一般的先进先出Buffer更强的控制力:我们可以自定义Comparator给它,告诉它怎么判定它的成员的先后顺序,优先级最高的最先走。

     

    为了方便和清晰的需要,我在这里只举一个BoundedFifoBuffer,包装成TypedBuffer,看看在具体的代码中通常如何使用Buffer:(还是沿用上次的Book类)

     

    package sean.study.commons.collections;

     

    import java.util.Iterator;

     

    import org.apache.commons.collections.Buffer;

    import org.apache.commons.collections.BufferUtils;

    import org.apache.commons.collections.buffer.BoundedFifoBuffer;

    import org.apache.commons.lang.StringUtils;

     

    public class BufferUsage {

     

        public static void main(String[] args) {

            demoBufferUsage();

        }

     

        public static void demoBufferUsage() {

     

            System.out.println(StringUtils.center(" demoBagUsage ", 40, "="));

     

            // data setup

            Book book1 = new Book("Refactoring Workbook", "7-5083-2208-8", 29.8);

            Book book2 = new Book("J2EE Design Patterns", "7-5083-3099-4", 45);

            Book book3 = new Book("Agile Software Development", "7-5083-1503-0", 59);

            Book book4 = new Book("Professional JSP", "7-5053-8005-2", 100);

     

            // create a Buffer

            Buffer buffer =

                BufferUtils.typedBuffer(new BoundedFifoBuffer(3), Book.class);

            buffer.add(book1);

            buffer.add(book2);

            buffer.add(book3);

            Book removed = (Book) buffer.remove();

            System.out.println("Removed:");

            System.out.println(removed);

            buffer.add(book4);

           

            // get items in buffer

            for (int i = 0; i < 3; i++) {

                System.out.println(buffer.get());

                buffer.remove();

            }

     

            System.out.println(StringUtils.repeat("=", 40));

     

        }

     

    }

     

    以下是运行结果:

     

    ============= demoBagUsage =============

    Removed:

    sean.study.commons.collections.Book@e09713[

      name=Refactoring Workbook

      ISBN=7-5083-2208-8

      retailPrice=29.8

    ]

    Remaining:

    sean.study.commons.collections.Book@e09713[

      name=J2EE Design Patterns

      ISBN=7-5083-3099-4

      retailPrice=45.0

    ]

    sean.study.commons.collections.Book@47b480[

      name=Agile Software Development

      ISBN=7-5083-1503-0

      retailPrice=59.0

    ]

    sean.study.commons.collections.Book@19b49e6[

      name=Professional JSP

      ISBN=7-5053-8005-2

      retailPrice=100.0

    ]

    ========================================

     

    我们可以看到,Bufferaddremove方法分别添加新成员和删除最先加入的成员。由于我们的Buffer定义为只能装3Book类的实例,所以不论我们试图加入其他类型的对象,或者加入超过3个,操作都将失败。如果我们在遍历时使用get()而不调用remove(),那么我们将得到3个相同的拷贝,而这正是我们期望的FIFO队列的行为。假如你需要遍历并保留数据,可以使用标准的Iterator机制。

     

     

    posted @ 2005-08-04 12:49 laogao 阅读(2047) | 评论 (0)编辑 收藏

     

    首先来看Bag组。

     

    Bag

    HashBag

    BagUtils

     

    Bag是在org.apache.commons.collections包中定义的接口,它extends java.util.Collection,而它的实现类都被放在下面的bag包中。之所以有这样一组类型,是因为我们有时候需要在Collection中存放多个相同对象的拷贝,并且需要很方便的取得该对象拷贝的个数。需要注意的一点是它虽然extends Collection,但是如果真把它完全当作java.util.Collection来用会遇到语义上的问题,详细信息参考Javadoc

     

    HashBagBag接口的一个标准实现。而BagUtils提供一组static的方法让调用者获取经过不同装饰后的Bag实例。

     

    还是举例子来看:

     

    /** Book.java */

     

    package sean.study.commons.collections;

     

    import org.apache.commons.lang.builder.ToStringBuilder;

    import org.apache.commons.lang.builder.ToStringStyle;

     

    public class Book {

       

        private String name;

        private String isbn;

        private double retailPrice;

       

        public Book() {

        }

       

        public Book(String name, String isbn, double retailPrice) {

            this.name = name;

            this.isbn = isbn;

            this.retailPrice = retailPrice;

        }

       

        public String toString() {

            return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)

            .append("name", name)

            .append("ISBN", isbn)

            .append("retailPrice", retailPrice)

            .toString();

        }

     

        public String getIsbn() {

            return isbn;

        }

     

        public void setIsbn(String isbn) {

            this.isbn = isbn;

        }

     

        public String getName() {

            return name;

        }

     

        public void setName(String name) {

            this.name = name;

        }

     

        public double getRetailPrice() {

            return retailPrice;

        }

     

        public void setRetailPrice(double retailPrice) {

            this.retailPrice = retailPrice;

        }

       

    }

     

    /** BagUsage.java */

     

    package sean.study.commons.collections;

     

    import org.apache.commons.collections.Bag;

    import org.apache.commons.collections.BagUtils;

    import org.apache.commons.collections.bag.HashBag;

    import org.apache.commons.lang.StringUtils;

     

    public class BagUsage {

     

        public static void main(String[] args) {

            demoBagUsage();

        }

     

        public static void demoBagUsage() {

     

            System.out.println(StringUtils.center(" demoBagUsage ", 40, "="));

     

            // data setup

            Book book1 = new Book("Refactoring Workbook", "7-5083-2208-8", 29.8);

            Book book2 = new Book("J2EE Design Patterns", "7-5083-3099-4", 45);

            Book book3 = new Book("Agile Software Development", "7-5083-1503-0", 59);

     

            // create a bag

            Bag myBag = BagUtils.typedBag(new HashBag(), Book.class);

            myBag.add(book1, 360);

            myBag.add(book2, 500);

            myBag.add(book3, 170);

     

            // calculations for a bag

            double price1 = book1.getRetailPrice();

            double price2 = book2.getRetailPrice();

            double price3 = book3.getRetailPrice();

            int book1Count = myBag.getCount(book1);

            int book2Count = myBag.getCount(book2);

            int book3Count = myBag.getCount(book3);

            double totalValue = (price1 * book1Count) + (price2 * book2Count)

                    + (price3 * book3Count);

     

            // dispaly results

            System.out.println("There are " + book1Count + " copies of "

                    + book1.getName() + ".");

            System.out.println("There are " + book2Count + " copies of "

                    + book2.getName() + ".");

            System.out.println("There are " + book3Count + " copies of "

                    + book3.getName() + ".");

            System.out.println("The total value of these books is: " + totalValue);

     

            System.out.println();

     

        }

     

    }

     

    以下是运行结果:

     

    ============= demoBagUsage =============

    There are 360 copies of Refactoring Workbook.

    There are 500 copies of J2EE Design Patterns.

    There are 170 copies of Agile Software Development.

    The total value of these books is: 43258.0

     

    需要说明的是,以上的代码仅仅为了演示如何使用Bag,实际应用不建议像这样硬编码。

     

     

    posted @ 2005-08-03 12:36 laogao 阅读(2599) | 评论 (2)编辑 收藏

     

    Commons Collections,又是一个重量级的东西,为Java标准的Collections API提供了相当好的补充。我不知道其他人,就我自己而言,让我用java.util.Collection及其子类,加上java.util.Collections类提供的操作方法,处理一些简单的数据结构问题还可以,稍微复杂一点的就觉得有点头痛,很多细节的地方需要我插入这样那样的小逻辑,或者感觉它太死板,不够灵活,再或者确实有点晦涩吧。再说了,如果我只是处理一般的数据结构问题,为什么不自己用数组或者自定义的链表来做,再加上Jakarta CommonsLang提供的ArrayUtilsStringUtils等,已经基本够了,性能可以保证,那么还要这个Collections API干嘛。当然,说到这里有些偏激了,Collections当然有它存在的道理,能够把常用的数据结构归纳起来,以通用的方式去维护和访问,这应该说是一种进步,但是用起来似乎不够友好。这个时候我就会想,如果Java比现在做得更好用些,或者有一套第三方的API把我的这些需求抽象出来,实现了,该多好。Commons Collections就是这样一套API

     

    在这里可以找到下载链接:(binarysrc都有)

    http://jakarta.apache.org/site/downloads/downloads_commons-collections.cgi

     

    目前Commons Collection发布的最新版本是3.1。建议下载这个3.1版本,页面上出现的2.1.1是针对2.1不兼容3.0而发布的升级维护版。

     

    我们先来浏览一下它的包结构。一共是12个:

     

    org.apache.commons.collections – Commons Collections自定义的一组公用的接口和工具类

    org.apache.commons.collections.bag – 实现Bag接口的一组类

    org.apache.commons.collections.bidimap – 实现BidiMap系列接口的一组类

    org.apache.commons.collections.buffer – 实现Buffer接口的一组类

    org.apache.commons.collections.collection – 实现java.util.Collection接口的一组类

    org.apache.commons.collections.comparators – 实现java.util.Comparator接口的一组类

    org.apache.commons.collections.functors – Commons Collections自定义的一组功能类

    org.apache.commons.collections.iterators – 实现java.util.Iterator接口的一组类

    org.apache.commons.collections.keyvalue – 实现集合和键/值映射相关的一组类

    org.apache.commons.collections.list – 实现java.util.List接口的一组类

    org.apache.commons.collections.map – 实现Map系列接口的一组类

    org.apache.commons.collections.set – 实现Set系列接口的一组类

     

    用过Java Collections API的朋友大概或多或少会同意我如下的划分:在JavaCollections API中,不狭义的区分语法上的接口和类,把它们都看作是类的话,大致我们可以发现三种主要的类别:

     

    1- 容器类:如CollectionListMap等,用于存放对象和进行简单操作的;

    2- 操作类:如CollectionsArrays等,用于对容器类的实例进行相对复杂操作如排序等;

    3- 辅助类:如IteratorComparator等,用于辅助操作类以及外部调用代码实现对容器类的操作,所谓辅助,概括而通俗的来讲,就是这些类提供一种算法,你给它一个对象或者一组对象,或者仅仅是按一定的规则调用它,它给你一个运算后的答案,帮助你正确处理容器对象。比如Iterator会告诉你容器中下一个对象有没有、是什么,而Comparator将对象大小/先后次序的算法逻辑独立出来。

     

    同样,Jakarta Commons Collections我们细细看来,也能够找出类似的划分:

     

    1- 作为容器类的补充,我们可以找到BagBufferBidiMapOrderedMap等等;

    2- 作为操作类的补充,我们可以找到CollectionUtilsIteratorUtilsListUtilsSetUtils等等;

    3- 作为辅助类的补充,我们可以找到MapIteratorClosurePredicateTransformer等等;

     

    对于这样的一个大包,当然不可能一个类一个类的讲了,找一些常用的和有用的当做接下来讨论的话题吧。大概列个清单:

     

    Bag

    HashBag

    BagUtils

     

    Buffer

    BlockingBuffer

    BoundedFifoBuffer

    PriorityBuffer

    BufferUtils

     

    MultiMap

    BidiMap

    CaseInsensitiveMap

    LazyMap

    MapUtils

     

    TypedCollection

    CollectionUtils

     

    ReverseComparator

    ComparatorChain

    NullComparator

    FixedOrderComparator

    ComparatorUtils

     

    Predicate

    AndPredicate

    OrPredicate

    AllPredicate

    OnePredicate

    NonePredicate

    PredicateUtils

     

    Transformer

    ChainedTransformer

    SwitchTransformer

    TransformerUtils

     

    Closure

    ChainedClosure

    IfClosure

    WhileClosure

    ClosureUtils

     

    LoopingIterator

    ArrayListIterator

    FilterIterator

    UniqueFilterIterator

    IteratorUtils

     

    总共9组,在接下来的笔记中我们一起慢慢的看。

     

     

    posted @ 2005-08-03 09:07 laogao 阅读(3325) | 评论 (1)编辑 收藏

         摘要:   假定我们有如下两个标准的JavaBean:   /** Address.java */   package sean.study.commons.beanutils;   public class Address {       private String zipCode;  &nb...  阅读全文

    posted @ 2005-08-02 17:57 laogao 阅读(3336) | 评论 (1)编辑 收藏

     

    Jakarta Commons项目提供了相当丰富的API,我们之前了解到的Commons Lang只是众多API的比较核心的一小部分而已。Commons下面还有相当数量的子项目,用于解决各种各样不同方向的实际问题,BeanUtils就是其中的一个,用于处理JavaBeans。它利用Java的反射机制,从动态的生成对beangettersetter的调用代码,到模拟创建一个动态的bean,等等。这个包看似简单,却是很多开源项目的基石:如在著名的StrutsSpring Framework中,我们都能找到BeanUtils的影子。大家猜猜看,有哪位名人是BeanUtils的作者之一?没错,就是Struts的创始人Craig McClanahan

     

    BeanUtils最核心的好处在于:我们在编码时,并不需要知道我们处理的JavaBeans具体是什么类型,有哪些属性,这些信息是可以动态获取的,甚至我们都可以不必去关心事实上是否存在这样一个具体的JavaBean类。我们只需要知道有一个JavaBean的实例,我们需要从中取得某个属性,设定某个属性的值,或者仅仅是需要一个属性表。要做到这些,依靠Sun提供的JavaBean规范似乎找不到一个很直接的方式,除非硬编码,将getXxxx()setXxxx()直接写进我们的程序。但是这样就大大增加了代码的复杂度、耦合性和维护成本。还好Commons BeanUtils对这个问题提供了一种优雅的解决方案。

     

    我们有两种途径获取Commons BeanUtilsbinary

    1- StrutsSpring或者任何依赖BeanUtils的开源产品的发行包中找到相应的jar文件;

    2- http://www.apache.org/dist/jakarta/commons/beanutils/binaries/下载。

     

    Commons BeanUtils的源码下载地址:

    http://www.apache.org/dist/jakarta/commons/beanutils/source/

     

    Commons BeanUtils一共包括如下5个包:

     

    org.apache.commons.beanutils – 核心包,定义一组Utils类和需要用到的接口规范

    org.apache.commons.beanutils.converters – 转换String到需要类型的类,实现Converter接口

    org.apache.commons.beanutils.locale – beanutilslocale敏感版本

    org.apache.commons.beanutils.locale.converters – converterslocale敏感版本

    org.apache.commons.collections – beanutils使用到的Collection

     

    其中需要我们特别关注的是这个org.apache.commons.beanutils包,其他包都是起辅助作用的。接下来我们就仔细看一看这个包都有些什么东东:

     

    [4个接口]

     

    Converter

    该接口定义了如下方法:

    public java.lang.Object convert(java.lang.Class type, java.lang.Object value);

    只要实现了这个Converter接口并注册到ConvertUtils类即可被我们的BeanUtils包所使用,它的主要目的是提供将给定的Object实例转换为目标类型的算法。我们可以在beanutils.converters包中找到相当多的已经实现的转换器。

     

    DynaBean

    该接口定义的是一个动态的JavaBean,它的属性类型、名称和值都是可以动态改变的。

     

    DynaClass

    该接口定义的是针对实现了DynaBean接口的类的java.lang.Class对象,提供如getName()newInstance()等方法。

     

    MutableDynaClass

    该接口是对DynaClass的扩展,使得动态bean的属性可以动态增加或删除。

     

    [24个类]

     

    BasicDynaBean

    DynaBean接口的最精简实现

     

    BasicDynaClass

    DynaClass接口的最精简实现

     

    BeanUtils

    提供通过反射机制填写JavaBeans属性的工具/静态方法

     

    BeanUtilsBean

    BeanUtils类的实例化实现,区别于BeanUtils的静态方法方式,使得自定义的配置得以保持

     

    ConstructorUtils

    MethodUtils类似,不过专注于构造方法

     

    ContextClassLoaderLocal

    针对每个classloader的唯一标识

     

    ConvertingWrapDynaBean

    包含了标准JavaBean实例的DynaBean实现,使得我们可以使用DynaBeanAPI来访问起属性,同时提供设定属性时的类型转换,继承自并区别于WrapDynaBean

     

    ConvertUtils

    提供工具/静态方法,用于将String对象及其数组转换为指定的类型的对象及其数组。

     

    ConvertUtilsBean

    ConvertUtils类的实例化实现,区别于ConvertUtils的静态方法方式,使得自定义的配置得以保持

     

    DynaProperty

    用于描述DynaBean的属性

     

    JDBCDynaClass

    DynaClassJDBC实现提供公用的逻辑

     

    LazyDynaBean

    懒载入DynaBean,自动往DynaClass添加属性并提供懒载入List和懒载入Map的功能

     

    LazyDynaClass

    实现MutableDynaClass接口的类

     

    LazyDynaMap

    Map实例提供一个轻量级的DynaBean包装

     

    MappedPropertyDescriptor

    用于描述映射的属性

     

    MethodUtils

    包含了针对一般意义上的方法而非特定属性的反射工具/静态方法

     

    MethodUtils.MethodDescriptor

    描述通过反射查找某个方法所使用的键值

     

    PropertyUtils

    提供利用Java反射API调用具体对象的gettersetter的工具/静态方法

     

    PropertyUtilsBean

    PropertyUtils类的实例化实现,区别于PropertyUtils的静态方法方式,使得自定义的配置得以保持

     

    ResultSetDynaClass

    包装java.sql.ResultSet中的java.sql.Row实例的DynaBean所对应的DynaClass实现

     

    ResultSetIterator

    针对ResultSetDynaClassjava.util.Iterator实现

     

    RowSetDynaClass

    DynaClass的一种实现,用于在内存中创建一组表示SQL查询结果的DynaBeans,区别于ResultSetDynaClass,它不需要保持ResultSet打开

     

    WrapDynaBean

    DynaBean的一种实现,包含一个标准的JavaBean实例,以便我们可以使用DynaBeanAPI去访问它的属性,区别于ConvertingWrapDynaBean,它不做专门的类型转换

     

    WrapDynaClass

    DynaClass的一种实现,针对那些包装标准JavaBean实例的DynaBeans

     

    [3Exception]

     

    (略)

     

    看到这么多东西是不是有点头晕?不要慌,看几个例子就明白了。只要把握好BeanUtils本身要完成的事,就不难理解这些类存在的道理。我们不妨把BeanUtils的基础应用分解成:访问JavaBean的属性、设定JavaBean的属性、以及创建和使用DynaBeans。这样来看BeanUtils,你就会觉得简单清晰得多。

     

    // 例子将在下一节单独放出。

     

     

    posted @ 2005-08-02 12:40 laogao 阅读(5313) | 评论 (3)编辑 收藏

     

    好了,来看我在Common Lang中最后要讲的一个包:org.apache.commons.lang.time。这个包里面包含了如下5个类:

     

    DateFormatUtils – 提供格式化日期和时间的功能及相关常量;

    DateUtils – CalendarDate的基础上提供更方便的访问;

    DurationFormatUtils – 提供格式化时间跨度的功能及相关常量;

    FastDateFormat – java.text.SimpleDateFormat提供一个的线程安全的替代类;

    StopWatch – 是一个方便的计时器。

     

    我们还是在一个例子中来看上述各个类的用法吧:

     

    package sean.study.jakarta.commons.lang;

     

    import java.util.Calendar;

    import java.util.Date;

     

    import org.apache.commons.lang.StringUtils;

    import org.apache.commons.lang.time.DateFormatUtils;

    import org.apache.commons.lang.time.DateUtils;

    import org.apache.commons.lang.time.FastDateFormat;

    import org.apache.commons.lang.time.StopWatch;

     

    public class DateTimeUsage {

     

        public static void main(String[] args) {

            demoDateUtils();

            demoStopWatch();

        }

       

        public static void demoDateUtils() {

            System.out.println(StringUtils.center(" demoDateUtils ", 30, "="));

            Date date = new Date();

            String isoDateTime = DateFormatUtils.ISO_DATETIME_FORMAT.format(date);

            String isoTime = DateFormatUtils.ISO_TIME_NO_T_FORMAT.format(date);

            FastDateFormat fdf = FastDateFormat.getInstance("yyyy-MM");

            String customDateTime = fdf.format(date);

            System.out.println("ISO_DATETIME_FORMAT: " + isoDateTime);

            System.out.println("ISO_TIME_NO_T_FORMAT: " + isoTime);

            System.out.println("Custom FastDateFormat: " + customDateTime);

            System.out.println("Default format: " + date);

            System.out.println("Round HOUR: " + DateUtils.round(date, Calendar.HOUR));

            System.out.println("Truncate HOUR: " + DateUtils.truncate(date, Calendar.HOUR));

            System.out.println();

        }

       

        public static void demoStopWatch() {

            System.out.println(StringUtils.center(" demoStopWatch ", 30, "="));

            StopWatch sw = new StopWatch();

            sw.start();

            operationA();

            sw.stop();

            System.out.println("operationA used " + sw.getTime() + " milliseconds.");

            System.out.println();

        }

       

        public static void operationA() {

            try {

                Thread.sleep(999);

            }

            catch (InterruptedException e) {

                // do nothing

            }

        }

     

    }

     

    以下是运行结果:

     

    ======= demoDateUtils ========

    ISO_DATETIME_FORMAT: 2005-08-01T12:41:51

    ISO_TIME_NO_T_FORMAT: 12:41:51

    Custom FastDateFormat: 2005-08

    Default format: Mon Aug 01 12:41:51 CST 2005

    Round HOUR: Mon Aug 01 13:00:00 CST 2005

    Truncate HOUR: Mon Aug 01 12:00:00 CST 2005

     

    ======= demoStopWatch ========

    operationA used 1000 milliseconds.

     

    具体的调用细节和完整的API请参阅Commons LangJavadoc

     

     

    posted @ 2005-08-01 13:19 laogao 阅读(7330) | 评论 (11)编辑 收藏

     

    Jakarta Commons中,专门处理数学计算的类分别可以在两个地方找到:一是Commons Langorg.apache.commons.lang.math包中,二是在Commons Math这个单独的子项目中。由于后者主要是处理复数、矩阵等,相对使用比较少,在我的笔记中就只简单讲讲Commons Lang中的math包。对后者感兴趣的可以看看

    http://jakarta.apache.org/commons/math/

     

    org.apache.commons.lang.math包中共有10个类,这些类可以归纳成四组:

    1- 处理分数的Fraction类;

    2- 处理数值的NumberUtils类;

    3- 处理数值范围的RangeNumberRangeIntRangeLongRangeFloatRangeDoubleRange类;

    4- 处理随机数的JVMRandomRandomUtils类。

     

    下面我举个例子分别说明上述四组的使用方法:

     

    package sean.study.jakarta.commons.lang;

     

    import org.apache.commons.lang.ArrayUtils;

    import org.apache.commons.lang.BooleanUtils;

    import org.apache.commons.lang.StringUtils;

    import org.apache.commons.lang.math.DoubleRange;

    import org.apache.commons.lang.math.Fraction;

    import org.apache.commons.lang.math.NumberUtils;

    import org.apache.commons.lang.math.RandomUtils;

    import org.apache.commons.lang.math.Range;

     

    public class LangMathUsage {

     

        public static void main(String[] args) {

            demoFraction();

            demoNumberUtils();

            demoNumberRange();

            demoRandomUtils();

        }

     

        public static void demoFraction() {

            System.out.println(StringUtils.center(" demoFraction ", 30, "="));

            Fraction myFraction = Fraction.getFraction(144, 90);

            // Fraction myFraction = Fraction.getFraction("1 54/90");

            System.out.println("144/90 as fraction: " + myFraction);

            System.out.println("144/90 to proper: " + myFraction.toProperString());

            System.out.println("144/90 as double: " + myFraction.doubleValue());

            System.out.println("144/90 reduced: " + myFraction.reduce());

            System.out.println("144/90 reduced proper: "

                    + myFraction.reduce().toProperString());

            System.out.println();

        }

     

        public static void demoNumberUtils() {

            System.out.println(StringUtils.center(" demoNumberUtils ", 30, "="));

            System.out.println("Is 0x3F a number? "

                    + StringUtils.capitalize(BooleanUtils.toStringYesNo(NumberUtils

                            .isNumber("0x3F"))) + ".");

            double[] array = { 1.0, 3.4, 0.8, 7.1, 4.6 };

            double max = NumberUtils.max(array);

            double min = NumberUtils.min(array);

            String arrayStr = ArrayUtils.toString(array);

            System.out.println("Max of " + arrayStr + " is: " + max);

            System.out.println("Min of " + arrayStr + " is: " + min);

            System.out.println();

        }

     

        public static void demoNumberRange() {

            System.out.println(StringUtils.center(" demoNumberRange ", 30, "="));

            Range normalScoreRange = new DoubleRange(90, 120);

            double score1 = 102.5;

            double score2 = 79.9;

            System.out.println("Normal score range is: " + normalScoreRange);

            System.out.println("Is "

                    + score1

                    + " a normal score? "

                    + StringUtils

                            .capitalize(BooleanUtils.toStringYesNo(normalScoreRange

                                    .containsDouble(score1))) + ".");

            System.out.println("Is "

                    + score2

                    + " a normal score? "

                    + StringUtils

                            .capitalize(BooleanUtils.toStringYesNo(normalScoreRange

                                    .containsDouble(score2))) + ".");

            System.out.println();

        }

     

        public static void demoRandomUtils() {

            System.out.println(StringUtils.center(" demoRandomUtils ", 30, "="));

            for (int i = 0; i < 5; i++) {

                System.out.println(RandomUtils.nextInt(100));

            }

            System.out.println();

        }

     

    }

     

    以下是运行结果:

     

    ======== demoFraction ========

    144/90 as fraction: 144/90

    144/90 to proper: 1 54/90

    144/90 as double: 1.6

    144/90 reduced: 8/5

    144/90 reduced proper: 1 3/5

     

    ====== demoNumberUtils =======

    Is 0x3F a number? Yes.

    Max of {1.0,3.4,0.8,7.1,4.6} is: 7.1

    Min of {1.0,3.4,0.8,7.1,4.6} is: 0.8

     

    ====== demoNumberRange =======

    Normal score range is: Range[90.0,120.0]

    Is 102.5 a normal score? Yes.

    Is 79.9 a normal score? No.

     

    ====== demoRandomUtils =======

    75

    63

    40

    21

    92

     

    以上就是Commons Langmath包通常的用法。提一下NumberUtils.inNumber(String)方法,它会正确判断出给定的字符串是否是合法的数值,而我在前面的笔记中提到的StringUtils.isNumeric(String)只能判断一个字符串是否是由纯数字字符组成。Commons Langmath包的各个类都还有很多实用的方法,远不止我在例子中用到的这些,如果你感兴趣,参照一下Commons LangJavadoc吧。

     

     

    posted @ 2005-08-01 13:18 laogao 阅读(3958) | 评论 (3)编辑 收藏

     

    在前面的专题文章中,我们一起过了一遍org.apache.commons.lang包,接下来我们继续看org.apache.commons.lang.builder这个包。在这里面我们可以找到7个类,用于帮助我们实现Java对象的一些基础的共有方法。这7个类分别是:

     

    CompareToBuilder – 用于辅助实现Comparable.compareTo(Object)方法;

    EqualsBuilder – 用于辅助实现Object.equals()方法;

    HashCodeBuilder – 用于辅助实现Object.hashCode()方法;

    ToStringBuilder – 用于辅助实现Object.toString()方法;

    ReflectionToStringBuilder – 使用反射机制辅助实现Object.toString()方法;

    ToStringStyle – 辅助ToStringBuilder控制输出格式;

    StandardToStringStyle – 辅助ToStringBuilder控制标准格式。

     

    我们知道,在实际应用中,其实经常需要在运行过程中判定对象的知否相等、比较、取hash、和获取对象基本信息(一般是产生log日志)。然而实现这些compareToequalshashCodetoString其实并非那么直截了当,甚至稍有不注意就可能造成难以追踪的bug,而且这些方法手工维护的话,比较繁琐,也容易出错。于是Commons Langbuilder这个包中提供了上述辅助类,为我们简化这些方法的实现和维护。

     

    来看一个例子:

     

    package sean.study.jakarta.commons.lang;

     

    import java.util.Date;

     

    import org.apache.commons.lang.builder.CompareToBuilder;

    import org.apache.commons.lang.builder.EqualsBuilder;

    import org.apache.commons.lang.builder.HashCodeBuilder;

    import org.apache.commons.lang.builder.ToStringBuilder;

    import org.apache.commons.lang.builder.ToStringStyle;

     

    public class BuilderUsage {

     

        public static void main(String[] args) {

           

            Staff staff1 = new Staff(123, "John Smith", new Date());

            Staff staff2 = new Staff(456, "Jane Smith", new Date());

           

            System.out.println("staff1's info: " + staff1);

            System.out.println("staff2's info: " + staff2);

            System.out.println("staff1's hash code: " + staff1.hashCode());

            System.out.println("staff2's hash code: " + staff2.hashCode());

            System.out.println("staff1 equals staff2? " + staff1.equals(staff2));

     

        }

     

    }

     

    class Staff implements Comparable {

     

        private long staffId;

        private String staffName;

        private Date dateJoined;

     

        public Staff() {

        }

     

        public Staff(long staffId, String staffName, Date dateJoined) {

            this.staffId = staffId;

            this.staffName = staffName;

            this.dateJoined = dateJoined;

        }

     

        public int compareTo(Object o) {

            int res = -1;

            if (o != null && Staff.class.isAssignableFrom(o.getClass())) {

                Staff s = (Staff) o;

                res = new CompareToBuilder()

                        .append(dateJoined, s.getDateJoined())

                        .append(staffName, s.getStaffName()).toComparison();

            }

            return res;

        }

     

        public boolean equals(Object o) {

            boolean res = false;

            if (o != null && Staff.class.isAssignableFrom(o.getClass())) {

                Staff s = (Staff) o;

                res = new EqualsBuilder()

                        .append(staffId, s.getStaffId())

                        .isEquals();

            }

            return res;

        }

     

        public int hashCode() {

            return new HashCodeBuilder(11, 23).append(staffId).toHashCode();

        }

     

        public String toString() {

            return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)

                    .append("staffId", staffId)

                    .append("staffName", staffName)

                    .append("dateJoined", dateJoined)

                    .toString();

        }

     

        public Date getDateJoined() {

            return dateJoined;

        }

     

        public void setDateJoined(Date dateJoined) {

            this.dateJoined = dateJoined;

        }

     

        public long getStaffId() {

            return staffId;

        }

     

        public void setStaffId(long staffId) {

            this.staffId = staffId;

        }

     

        public String getStaffName() {

            return staffName;

        }

     

        public void setStaffName(String staffName) {

            this.staffName = staffName;

        }

    }

     

    以下是运行结果:

     

    staff1's info: sean.study.jakarta.commons.lang.Staff@190d11[

      staffId=123

      staffName=John Smith

      dateJoined=Sat Jul 30 13:18:45 CST 2005

    ]

    staff2's info: sean.study.jakarta.commons.lang.Staff@1fb8ee3[

      staffId=456

      staffName=Jane Smith

      dateJoined=Sat Jul 30 13:18:45 CST 2005

    ]

    staff1's hash code: 376

    staff2's hash code: 709

    staff1 equals staff2? false

     

    这些builder使用起来都很简单,new一个实例,append需要参与的信息,最后加上toComparisonisEqualstoHashCodetoString这样的结尾即可。相应的,如果你不需要这样级别的控制,也可以使用利用反射机制的版本自动化实现需要的功能,如:

     

        public int compareTo(Object o) {

            return CompareToBuilder.reflectionCompare(this, o);

        }

     

        public boolean equals(Object o) {

            return EqualsBuilder.reflectionEquals(this, o);

        }

     

        public int hashCode() {

            return HashCodeBuilder.reflectionHashCode(this);

        }

     

        public String toString() {

            return ReflectionToStringBuilder.toString(this);

        }

     

    尤其当我们在项目中不希望过多的参与到对这些对象方法的维护时,采用Commons提供的利用反射的这些API就成了方便而相对安全的一个方案。

     

     

    posted @ 2005-07-30 15:38 laogao 阅读(6069) | 评论 (0)编辑 收藏

     

    处理文本对Java应用来说应该算是家常便饭了,在1.4出现之前,Java自身提供的API非常有限,如StringStringTokenizerStringBuffer,操作也比较单一。无非就是查找substring、分解、合并等等。到1.4的出现可以说Java的文字处理上了一个台阶,因为它支持regular expression了。这可是个重量级而方便的东东啊,缺点是太复杂,学习起来有一定难度。相较而言,Jakarta Commons提供的StringUtilsWordUtils至今还维持着那种简洁而强大的美,使用起来也很顺手。来看一个例子:

     

    package sean.study.jakarta.commons.lang;

     

    import org.apache.commons.lang.StringUtils;

     

    public class StringUtilsAndWordUtilsUsage {

     

        public static void main(String[] args) {

           

            // data setup

            String str1 = "";

            String str2 = " ";

            String str3 = "\t";

            String str4 = null;

            String str5 = "123";

            String str6 = "ABCDEFG";

            String str7 = "It feels good to use Jakarta Commons.\r\n";

           

            // check for empty strings

            System.out.println("==============================");

            System.out.println("Is str1 blank? " + StringUtils.isBlank(str1));

            System.out.println("Is str2 blank? " + StringUtils.isBlank(str2));

            System.out.println("Is str3 blank? " + StringUtils.isBlank(str3));

            System.out.println("Is str4 blank? " + StringUtils.isBlank(str4));

           

            // check for numerics

            System.out.println("==============================");

            System.out.println("Is str5 numeric? " + StringUtils.isNumeric(str5));

            System.out.println("Is str6 numeric? " + StringUtils.isNumeric(str6));

           

            // reverse strings / whole words

            System.out.println("==============================");

            System.out.println("str6: " + str6);

            System.out.println("str6 reversed: " + StringUtils.reverse(str6));

            System.out.println("str7: " + str7);

            String str8 = StringUtils.chomp(str7);

            str8 = StringUtils.reverseDelimited(str8, ' ');

            System.out.println("str7 reversed whole words : \r\n" + str8);

           

            // build header (useful to print log messages that are easy to locate)

            System.out.println("==============================");

            System.out.println("print header:");

            String padding = StringUtils.repeat("=", 50);

            String msg = StringUtils.center(" Customised Header ", 50, "%");

            Object[] raw = new Object[]{padding, msg, padding};

            String header = StringUtils.join(raw, "\r\n");

            System.out.println(header);

     

        }

    }

     

    输出的结果如下:

     

    ==============================

    Is str1 blank? true

    Is str2 blank? true

    Is str3 blank? true

    Is str4 blank? true

    ==============================

    Is str5 numeric? true

    Is str6 numeric? false

    ==============================

    str6: ABCDEFG

    str6 reversed: GFEDCBA

    str7: It feels good to use Jakarta Commons.

     

    str7 reversed whole words :

    Commons. Jakarta use to good feels It

    ==============================

    print header:

    ==================================================

    %%%%%%%%%%%%%%% Customised Header %%%%%%%%%%%%%%%%

    ==================================================

     

    从代码中我们可以大致了解到这个StringUtils类简单而强大的处理能力,从检查空串(对null的情况处理很得体),到分割子串,到生成格式化的字符串,使用都很简洁,也很直截了当。

     

     

    posted @ 2005-07-30 11:37 laogao 阅读(5015) | 评论 (0)编辑 收藏

     

    数组是我们经常需要使用到的一种数据结构,但是由于Java本身并没有提供很好的API支持,使得很多操作实际上做起来相当繁琐,以至于我们实际编码中甚至会不惜牺牲性能去使用Collections API,用Collection当然能够很方便的解决我们的问题,但是我们一定要以性能为代价吗?ArrayUtils帮我们解决了处理类似情况的大部分问题。来看一个例子:

     

    package sean.study.jakarta.commons.lang;

     

    import java.util.Map;

    import org.apache.commons.lang.ArrayUtils;

     

    public class ArrayUtilsUsage {

     

        public static void main(String[] args) {

     

            // data setup

            int[] intArray1 = { 2, 4, 8, 16 };

            int[][] intArray2 = { { 1, 2 }, { 2, 4 }, { 3, 8 }, { 4, 16 } };

            Object[][] notAMap = {

                    { "A", new Double(100) },

                    { "B", new Double(80) },

                    { "C", new Double(60) },

                    { "D", new Double(40) },

                    { "E", new Double(20) }

            };

     

            // printing arrays

            System.out.println("intArray1: " + ArrayUtils.toString(intArray1));

            System.out.println("intArray2: " + ArrayUtils.toString(intArray2));

            System.out.println("notAMap: " + ArrayUtils.toString(notAMap));

     

            // finding items

            System.out.println("intArray1 contains '8'? "

                    + ArrayUtils.contains(intArray1, 8));

            System.out.println("intArray1 index of '8'? "

                    + ArrayUtils.indexOf(intArray1, 8));

            System.out.println("intArray1 last index of '8'? "

                    + ArrayUtils.lastIndexOf(intArray1, 8));

     

            // cloning and resversing

            int[] intArray3 = ArrayUtils.clone(intArray1);

            System.out.println("intArray3: " + ArrayUtils.toString(intArray3));

            ArrayUtils.reverse(intArray3);

            System.out.println("intArray3 reversed: "

                    + ArrayUtils.toString(intArray3));

     

            // primitive to Object array

            Integer[] integerArray1 = ArrayUtils.toObject(intArray1);

            System.out.println("integerArray1: "

                    + ArrayUtils.toString(integerArray1));

     

            // build Map from two dimensional array

            Map map = ArrayUtils.toMap(notAMap);

            Double res = (Double) map.get("C");

            System.out.println("get 'C' from map: " + res);

     

        }

     

    }

     

    以下是运行结果:

     

    intArray1: {2,4,8,16}

    intArray2: {{1,2},{2,4},{3,8},{4,16}}

    notAMap: {{A,100.0},{B,80.0},{C,60.0},{D,40.0},{E,20.0}}

    intArray1 contains '8'? true

    intArray1 index of '8'? 2

    intArray1 last index of '8'? 2

    intArray3: {2,4,8,16}

    intArray3 reversed: {16,8,4,2}

    integerArray1: {2,4,8,16}

    get 'C' from map: 60.0

     

    这段代码说明了我们可以如何方便的利用ArrayUtils类帮我们完成数组的打印、查找、克隆、倒序、以及值型/对象数组之间的转换等操作。如果想了解更多,请参考Javadoc

     

     

    posted @ 2005-07-30 11:36 laogao 阅读(3578) | 评论 (0)编辑 收藏

     

    我们首先来看org.apache.commons.lang包,这个包提供了一些有用的包含static方法的Util类。除了6Exception类和2个已经deprecated的数字类之外,commons.lang包共包含了17个实用的类:

     

    ArrayUtils – 用于对数组的操作,如添加、查找、删除、子数组、倒序、元素类型转换等;

    BitField – 用于操作位元,提供了一些方便而安全的方法;

    BooleanUtils – 用于操作和转换boolean或者Boolean及相应的数组;

    CharEncoding – 包含了Java环境支持的字符编码,提供是否支持某种编码的判断;

    CharRange – 用于设定字符范围并做相应检查;

    CharSet – 用于设定一组字符作为范围并做相应检查;

    CharSetUtils – 用于操作CharSet

    CharUtils – 用于操作char值和Character对象;

    ClassUtils – 用于对Java类的操作,不使用反射;

    ObjectUtils – 用于操作Java对象,提供null安全的访问和其他一些功能;

    RandomStringUtils – 用于生成随机的字符串;

    SerializationUtils – 用于处理对象序列化,提供比一般Java序列化更高级的处理能力;

    StringEscapeUtils – 用于正确处理转义字符,产生正确的JavaJavaScriptHTMLXMLSQL代码;

    StringUtils – 处理String的核心类,提供了相当多的功能;

    SystemUtils – java.lang.System基础上提供更方便的访问,如用户路径、Java版本、时区、操作系统等判断;

    Validate – 提供验证的操作,有点类似assert断言;

    WordUtils – 用于处理单词大小写、换行等。

     

    接下来我准备用两个例子来分别说明ArrayUtilsStringUtils的常见用法。

     

     

    posted @ 2005-07-30 11:35 laogao 阅读(3736) | 评论 (0)编辑 收藏

     

    java.lang这个包的作用类似,Commons Lang这一组API也是提供一些基础的、通用的操作和处理,如自动生成toString()的结果、自动实现hashCode()equals()方法、数组操作、枚举、日期和时间的处理等等。目前这组API的版本是2.1,下载地址如下:

     

    http://apache.justdn.org/jakarta/commons/lang/binaries/commons-lang-2.1.zip

    http://apache.justdn.org/jakarta/commons/lang/source/commons-lang-2.1-src.zip

     

    其中后一个是源代码。

     

    这一组API的所有包名都以org.apache.commons.lang开头,共有如下8个包:

     

    org.apache.commons.lang

    org.apache.commons.lang.builder

    org.apache.commons.lang.enum

    org.apache.commons.lang.enums

    org.apache.commons.lang.exception

    org.apache.commons.lang.math

    org.apache.commons.lang.mutable

    org.apache.commons.lang.time

     

    其中的lang.enum已不建议使用,替代它的是紧随其后的lang.enums包。 lang包主要是一些可以高度重用的Util类;lang.builder包包含了一组用于产生每个Java类中都常使用到的toString()hashCode()equals()compareTo()等等方法的构造器;lang.enums包顾名思义用于处理枚举;lang.exception包用于处理Java标准API中的exception,为1.4之前版本提供Nested Exception功能;lang.math包用于处理数字;lang.mutable用于包装值型变量;lang.time包提供处理日期和时间的功能。

     

    由于Commons的包和类实在很多,不可能一个一个讲了,在接下来的专题文章中我就只分别过一下langlang.builderlang.mathlang.time这几个包和常见的用法,其他的我们可以在用到时临时参考一下Javadoc。位置就在安装路径的

    …\commons-lang-2.1\docs\api\index.html

     

     

    posted @ 2005-07-29 18:10 laogao 阅读(5000) | 评论 (0)编辑 收藏

     

    Java的世界,有很多(成千上万)开源的框架,有成功的,也有不那么成功的,有声名显赫的,也有默默无闻的。在我看来,成功而默默无闻的那些框架值得我们格外的尊敬和关注,Jakarta Commons就是这样的一个框架。如果你至少参与了一个中型规模的Java项目,那么我想有超过一大半的机会你都接触和使用到了Jakarta Commons,不管你自己有没有察觉。就我所知,除了Apache Jakarta其他许多开源框架之外,不少所谓的商业框架其实内部有些模块是借用Commons的,甚至有一些完全就是对Commons的类进行了简单的封装。如果真的没有接触过也不要紧,当你看到它时,你自然会被它的简单而强大所吸引。

     

    要提高Java编程水平,一条可以走的路就是学习优秀的开源框架。这又要分两个层面:应用层面和源码层面。从应用来说,开源的框架大都可以给你带来生产力和/或代码质量的大幅提升;从源码来说,Java开源框架,尤其是那些大型的优秀的框架,其源码对广大Java爱好者来说都是一笔巨大的财富,你可以从中学到许多课本上学不到的东西:编码习惯、代码组织、注释、文档、如何用Java解决实际问题、特定问题的算法,等等。而这些对于我们的作为软件开发者的实际工作而言,相当有意义。

     

    熟悉Jakarta Commons的朋友可能会觉得现在是不是有点过时,因为有很多功能在J2SE 5.0中已经包含了。其实这个问题看你怎么去看,一方面,J2SE 5.0毕竟是刚出现不久的Java版本,实际应用中,很多时候我们需要把代码兼容等级维持在1.3或者1.4,所以很多5.0的功能我们暂时还不能放开手脚去使用;另一方面,鉴于Jakarta在一定程度上反映了一线Java开发人员的实际需求,而目前5.0已经采纳了其中许多特性,我们当然也有理由相信未来的Java版本还会继续参照Jakarta Commons的内容。有这么一套开发源码、免费使用、商业友好的优秀API作为Java自带API的补充,何乐而不为呢?

     

    我打算在近期陆续做一些Jakarta Commons的学习笔记放上来,供大家参考。

     

    有关Jakarta的最新动态和详细信息,可以参考:

    http://jakarta.apache.org/commons/index.html

     

     

    posted @ 2005-07-29 12:59 laogao 阅读(4444) | 评论 (0)编辑 收藏


    在Artima Developer上看到一则关于Jonathan Schwartz提到的Sun计划将其所有软件免费提供以促进使用Sun技术的社区发展的消息,有兴趣的看看原文吧:

    http://www.artima.com/forums/flat.jsp?forum=270&thread=120325

    posted @ 2005-07-27 17:48 laogao 阅读(449) | 评论 (1)编辑 收藏


    昨天看了Brad Pitt和Angelina Jolie合演的新片:Mr. & Mrs. Smith。说实在的,我原本对这部片子的期待并不高,一方面我猜想这是just another Hollywood movie而已,另一方面女主演Jolie的风格好像并不是我欣赏的风格,尤其是看了电影公司如何用她糟踏了我曾经一度是我的偶像的Lara Croft之后。然而,事实并非我想象的那样糟,甚至完全相反,大大超出我的预期不说,还相当让我喜欢。

    说到这里我插一点题外话:国内的进口电影片名翻译总是那么不能忠实原著,如果你想不出一个"信、达、雅"的中文名称,索性就直译一个"信"的就好,总比一个完全不沾边的名字强上百倍。在电影院和路边的宣传海报上出现的中文片名是:"史密斯行动",而在网上我们看到大陆之外的中文国家、地区通常都采用了"史密斯夫妇"这个忠于原文的中文片名。在中国大陆,最典型的一个例子就是"Enemy At the Gates",我们翻译成"决战中的较量",而其它地区都是"兵临城下",一相比较,孰优孰劣立见分晓。

    话说回来,这部片子虽然也充满了Hollywood和商业的味道,但是并不让人反感,至少我不觉得排斥。这部片子演员够级别,剧本写得也好,美工和动作特效的处理也很到位,毕竟是2005年的新片大片。总的来说,这部片子够性感、够幽默、够夸张、够暴力美学。

    贴一张海报和一张很多地方都引用到的剧照:
    mrandmrssmith3.jpg

    mrandmrssmith02.jpg

    posted @ 2005-07-26 09:37 laogao 阅读(419) | 评论 (0)编辑 收藏


    这个是上个月照的了,由于一直没时间整理,就搁在一边。今天心血来潮又翻出来,发现这一张虽然很随意,但是感觉还不错:

    Perfume.jpg

    全部的光源就是一盏40W的台灯,器材为Canon EOS 5、SIGMA 28-70 EX 2.8,Fujifilm 200负片,2.8光圈,1/30秒,手持拍摄。后期底扫后调整过色阶,分别按黑、白、灰三处取样。

    posted @ 2005-07-25 13:20 laogao 阅读(375) | 评论 (0)编辑 收藏

      

    J2EE应用中有一些常见的毛病和错误的观念,按照时下流行的说法,叫反模式。稍不注意,我们自己也会犯,所以大概整理一下,一个是备忘,也是供需要的朋友参考:

     

    1- EJB不叫J2EE

    EJB一直发展到今天的2.1仍然被广为诟病,它提供了很多时候我们并不需要的东西,而且我们在很多情况下一旦选用EJB就没有其他的方式不去使用那些笨重的功能。但是很多所谓范例让我们有一种错觉,好像不用EJB就不是J2EE应用。有一些折中的方案是使用Session Façade模式,Entity Bean采用BMP + 本地接口,然后提供一层无状态的Session Bean,采用远程和本地接口,这样的设计模式,我想,多半是出于无奈。如今,甚至我们经常都能看到不使用EJB的言论,炒得很火的Spring则为这种完全不用EJB开发J2EE项目提供了实际的、强有力的佐证。

     

    2- 过度分层

    J2EE这个规范肤浅的来看,就是为我们定义了很多“层”,然后还有很多分工明确的“角色”,加上J2EE的蓝本应用程序就分了很多“层”,以至于大家都觉得J2EE的应用就应该是很多层的,其实不然,需要具体情况具体分析。

     

    3- 频繁的往返调用

    EJB的看似简单造成我们经常忽略可能在使用过程中出现的远程调用,比如有时候为了更新一条记录,每个字段都是远程的去set,大大增加了不必要的开销,于是我们意识到在调用中使用DTO是一个建议遵循的方案。

     

    4- 过度使用有状态的Session Bean

    一般来讲,一个Session Bean实例,如果它是有状态的,那么它只对某个固定的用户服务,如果是无状态的,则可以满足不同用户的调用。这有点类似(只是有点类似)一个类的静态方法和非静态方法的区别。我们在实际应用中,应该尽量避免使用有状态的Session Bean,除非特别必要。我们可以把状态保留在Session Bean之外,如Web容器的session对象或者我们自定义的类中,而不是完全依赖有状态的Session Bean去帮我们做。

     

    5- 过度会话

    Web容器的session对象是个好东西,用起来也很方便和直截了当,这造成了我们很多人对它的滥用,什么东西都往里面放。这有两个突出的问题,一个是资源浪费;另一个,万一Web服务器崩溃,那些本来需要持久化的数据就丢失了。我们需要考虑好,哪些数据本可以用request的,哪些数据又是需要持久化到数据库的,等等,不能一味依赖session

     

    6- 万能Servlet或者万能JSP

    J2EE为我们提供了Web层丰富的技术选择,Servlet或者JSP都只是其中一种,虽然它很强大,但是也不应该由它一个来承担所有MVC三个部分的功能。现实中我们的Struts很好的规范了这个问题:Servlet负责调度,专门的Action负责处理逻辑,而JSP用于用户界面显示。JSPServlet本质上是同一个东西,只是从不同的角度来处理问题,它们各有所长,互为补充。

     

     

    posted @ 2005-07-23 17:01 laogao 阅读(3273) | 评论 (0)编辑 收藏


    眼看做了一年多的项目总算要上线了,自己也该计划一下项目结束以后要系统学习的东东,粗略地想了一下,应该包括下面这些:

    Eclipse (SWT/JFace/PDE/RCP)
    Hibernate
    JDO
    EJB 3.0 (以及Java EE 5 的其他部分)
    Spring Framework
    JSF
    Tapestry
    XML
    MySQL
    PHP
    Linux

    希望我还不算太贪心。

    posted @ 2005-07-23 15:22 laogao 阅读(690) | 评论 (4)编辑 收藏


    今天在JDJ上面看到一篇文章,说起一个在Java社区还算是比较新鲜的话题:XML Rich-Client,用XML替代传统的HTML作为服务器端返回给客户端的数据载体,它的基本思想有点类似微软的XAML,在Longhorn (Vista)中将要采用的一种界面配置技术,通过XML文档构建用户界面。

    相信大家多少有这种感觉,在服务器端,Java是老大,而客户端则被MS牢牢控制着。.NET出来以后MS更是利用客户端(桌面)的优势向服务器端发起了猛攻,开发.NET应用越来越简单,功能也越来越强大。现在提的这个XML Rich-Client并不需要很深的Java以及OO的知识,只需修改XML即可改变UI,甚至可以是独立于特定语言和平台的(虽然文中没提,但是笔者认为这就像是Web Services一样,理论上是平台中立的),不需要在客户端下载安装。也许这就是未来Java在客户端同MS竞争的一个重要方向?

    原文见:http://java.sys-con.com/read/111208_1.htm
    关于XAML,可以参考:http://www.ondotnet.com/pub/a/dotnet/2004/01/19/longhorn.html

    posted @ 2005-07-23 14:59 laogao 阅读(1177) | 评论 (0)编辑 收藏


    经过一段时间试用TM,效果并不理想:

    1- 可能是网络原因,TM的断线率同样很高,经常可以看见它在尝试重新登录,或者消息发送失败;
    2- 不知道是Windows还是TM处理窗口的方式有问题,经常在你处理其他事务的时候,从你的当前窗口跳转到TM的窗口,导致你所在的窗口失去焦点,这在你用中文输入法时尤其让人不爽;
    3- 偶尔TM会与我的金山词霸冲突导致系统死机。

    看来要做一款好用而又大众接受的IM即时通讯软件想必不是那么容易的一件事吧。

    posted @ 2005-07-13 15:49 laogao 阅读(494) | 评论 (2)编辑 收藏


    一段时间以来大家的MSN都多少出现了无法登陆的情况,这对于依赖MSN作为团队内部沟通的主要工具的我们来说实在是一件很恼火的事情。再加上我们经常有异地开发的情况,出现MSN的问题那就更糟了。

    在这个时候我的目光投向了腾讯的TM,没错,就是做QQ的那一家腾讯。其实我们在安装QQ的时候就自动装上了TM,这个东东看上去真的就是MSN+QQ的混血儿,个人觉得更加贴近中国人的需求,只不过由于MSN的历史背景和由捆绑带来的庞大的用户群,使用者甚少:虽然QQ很多人都在用,但是用TM界面的真有点凤毛麟角的味道,至少在我周围很少见到。TM可以选择和MSN一样使用邮件地址作为帐号(其实是把邮箱绑定到一个新的QQ号码上),并且可以和QQ服务器来回切换。

    很多功能都还来不及尝试,因为需要有人跟我一起beta一下才知道是不是真的好用。好的话可以考虑在公司内部使用。目前尝试过的两个比较好玩的功能是在线金山词霸和小I机器人。在线词霸你可以输入要查询的单词,然后就好像有人回复你解释一样;小I机器人是一个具备一定AI的自动聊天"机器人",当作消遣还是不错的。看看它都说了些什么:

    某某某 12:18:42
    hi
    小I机器人 12:18:44
    hi,我是来自2029年的最新t700型终结者,我现在的任务不是保护约翰-康纳,而是和你聊天! 
    某某某 12:18:58
    really?
    小I机器人 12:19:00
    yes
    某某某 12:19:07
    what can you do?
    小I机器人 12:19:08
    what is your job?
    某某某 12:19:29
    are you a cop?
    小I机器人 12:19:31
    i’m fine and u?
    某某某 12:20:10
    你在说什么哦?我问你做什么的,你回答说我很好?
    小I机器人 12:20:11
    你说我说什么,就说什么
    某某某 12:20:29
    。。。
    小I机器人 12:20:32
    淹到了?我说的吧,不会游泳就不要下水。这水可是要交费的
    某某某 12:21:08
    算了,跟你说不明白。走了,拜拜
    小I机器人 12:21:09
    那就别说了

    呵呵,接下来找些感兴趣的朋友测试一下。:)

    posted @ 2005-06-20 14:39 laogao 阅读(459) | 评论 (0)编辑 收藏


    经常看见网上许多人对SWT的认识无非就是说它运行速度快,其实这是个误区。在SWT诞生之初,也许运行速度是它的一项主要目标,但是它真正的优势其实并非这么简单,让它真正发光的是它对宿主操作系统的忠诚度,一方面,对用户来说,他们操作的界面表现形式,包括外观、快捷键等等可以和他们常用的软件高度一致;另一方面,由于它直接封装操作系统API的这个特性,任何你发现的界面上的问题或者说某个控件特殊的处理方式,你都可以在操作系统这一层的文档中找答案,而不是在SWT中间找。这跟Swing很不一样,Swing追求界面在所有平台的一致性,而不是对当前平台的其他本地应用的一致性。给我的感觉,Swing这样的做法实际上是瞄着一个移动的靶子,永远在赶路,因为它总是需要不停的跟着操作系统的变化和创新而变化与模仿。在这一点上,SWT的做法的确要高明得多。

    顺便来看一个WOW魔兽世界的XP界面风格下的Eclipse的截屏:
    WOW_Style_Eclipse_Snapshot.jpg

    这个界面风格可以随时跟你自己默认的XP风格对换,这样的效果和方便的更替如果要Swing来实现岂不是有点勉为其难?我不是说SWT是万能的,只是想让大家知道,Swing有它好的地方,SWT同样也有。

    posted @ 2005-06-20 13:55 laogao 阅读(4542) | 评论 (9)编辑 收藏


    空姐也RAP

    沪语其实还是蛮好听的叻

    posted @ 2005-06-16 12:36 laogao 阅读(1527) | 评论 (6)编辑 收藏


    依稀记得多年以前,刚接触编程的时候,就看见老爸成天都在用一种工具,主体是一堆16进制的数据,右边是解析出来的ASCII字符。后来知道这个是一种Hex Editor,用来看二进制文件的。其实它什么文件都可以看,只是你可以很方便的看到文件的内部结构和数据,一个字节不差。

    后来进入Windows时代,很多东西都可以用工具方便的完成,而不必关心内部细节,这样的二进制阅读工具也就渐渐远离了我的视线,直到最近,发觉在有些时候,你真的需要看看一个文件里面到底是放了些什么东西,怎么放的。然而网上一搜,10个有9个不是功能太庞杂就是license不友好[1]。拜托,我只想看看一个文件的Hex,难道要我自己用VC或者Java写?这个时候我想到了Eclipse,不论是开源的插件,还是自己写,都是很好的选择。果然,一搜即得,EHEP - Eclipse Hex Editor Plugin。试用一下,完全满足我的需求。看看截图:

    EHEP_snapshot_s.jpg

    插件主页:http://ehep.sourceforge.net/
    Update Site: http://ehep.sourceforge.net/update

    注:
    [1] 了解我的人可能都知道,我最讨厌那些license来license去的小工具/应用软件。UltraEdit、EditPlus这些东东(我想它们一定都支持HEX吧)不是不好,只是我不喜欢用而已。

    posted @ 2005-06-08 11:13 laogao 阅读(2299) | 评论 (2)编辑 收藏


    最近被同事问起一道SCJP的题目,是跟继承和多态有关的。具体的题目我就不重复了,来看一段我自己敲的代码:

     1package sean.work.test;
     2
     3public class DoYouReallyUnderstandPolymorphism {
     4    
     5    public static void main(String[] args) {
     6        A a = new A();
     7        B b = new B();
     8        a.s = "[AA]";
     9        b.s = "[BB]";
    10        System.out.println(a.s);      // prints "[AA]"
    11        System.out.println(b.s);      // prints "[BB]"
    12        System.out.println(a.getS()); // prints "[AA]"
    13        System.out.println(b.getS()); // prints "[BB]"
    14        System.out.println("====================");
    15        a = b; // a now refers to object b
    16        System.out.println(a.s);      // prints "[A]"  <<--1-- the class A copy
    17        System.out.println(b.s);      // prints "[BB]"
    18        System.out.println(a.getS()); // prints "[BB]"
    19        System.out.println(b.getS()); // prints "[BB]"
    20        System.out.println("====================");
    21        ((A)b).s = "[AA]"// <<--2-- changes the class A copy in object b 
    22        System.out.println(a.s);      // prints "[AA]" <<--3-- class A copy changed
    23        System.out.println(b.s);      // prints "[BB]"
    24        System.out.println(a.getS()); // prints "[BB]"
    25        System.out.println(b.getS()); // prints "[BB]"
    26    }

    27
    28}

    29
    30class A {
    31    String s = "[A]";
    32    String getS() {
    33        return s;
    34    }

    35}

    36
    37class B extends A{
    38    String s = "[B]";
    39    String getS() {
    40        return s;
    41    }

    42}

    43

    这里我们的B类继承自A类,重写了getS()方法,于是我们可以利用到多态。如果你留意15、16、21、22这几行的话,你也许就会知道我在说什么了。假如你觉得这样的打印结果是理所当然,那么我想你可以完全忽略这篇随笔,因为我要讲的就集中在这几行,而你已经很清楚的理解背后的含义。

    下面跟感兴趣的朋友们说说我的理解:

    直观的讲,我们很容易轻信当"a = b;"以后,变量a指向的对象是B类的b那个对象,自然a.s就应该等同于b.s,然而事实并非如此。当B继承A时,父类A的字段s并没有被B的字段s取代,而是保留了一份拷贝,所谓重写(Override),那是对方法而言的。于是,当我们new B()时,在实际创建的对象中,包含了两个版本的字段s,一个"[A]"(属于A类)一个"[B]"(属于B类)。而方法getS()只有一个版本。这就是在继承过程中字段和方法的区别。也就是说,重写的概念和字段无关。在第16行,我们通过a.s访问的是b这个对象中保留的A类的字段s;而在21行,我们改变的正是这个A类版本的s字段。

    多态的精髓在于动态确定对象的行为,而对象的行为体现在方法而非字段,字段代表的更多的是对象的状态。于是只有方法的多态而没有字段的多态。从上面的代码可以看出,不管你用什么类型的变量存放对象b的引用,最终调用的方法版本都是b的真实类型那个版本,这就是多态的威力。

    从编译的角度来看,上面代码中的s字段和getS()方法的不同在于:s字段是在编译期静态链接(你可以改变它的值,但是它在对象中的相对地址已经确定好),而getS()方法是在运行期动态链接的。

    说了这么多,真的不知道我表达清楚没有,毕竟没有系统研究过OO和编译原理,说得不当的地方还请多多包涵。最后,请不要学我这里的编码风格,因为很显然应该对main方法中的代码段执行Extract Method重构了,我这里只是为了注释方便。

    // BTW,时不时抽空想想这样的问题感觉真不错。

    posted @ 2005-06-07 15:18 laogao 阅读(7656) | 评论 (14)编辑 收藏

    前不久重装机器,偶然间发现一款挺方便的Eclipse插件。我们工作中用的是Oracle,于是经常会用到SQLPlus/Worksheet这样的东西,TOAD当然也有,但是SQLPlus用上去确实不方便,TOAD的安装也很麻烦并且我没有license。算了吧,既然一直在用Eclipse,就看看Eclipse上有没有好一点的替代工具吧。于是我发现了SQLExplorer。

    这个插件理论上支持所有提供了JDBC的数据库,其实就是把Java代码调用JDBC的操作进行了图形界面的封装。用上去的感觉就是比使用命令行操作数据库确实方便和直观了许多,甚至比某些专门的GUI管理工具要好用不少。

    下面是一幅截图,供参考:Eclipse SDK 3.0.2 + SQLExplorer 2.2.3

    SQLExlporer_snapshot_s.jpg

    当然,这个插件也有不少缺陷,比如不能兼容Eclipse3.1版本(至少M7上跑起来有问题),SQL编辑器的关键字颜色转换,对类似Oracle的RAW格式支持不好,等等,还有一些使用便捷性上的缺陷。并且因为是通过SQL/JDBC的方式操作,有很多数据库专有的特性无法体现。不过总的来说,它是一款不错的SQL浏览器,当你需要在同一个环境操作多个数据库,或者你觉得数据库提供的管理界面不方便,甚至仅仅因为你是Eclipse的狂热爱好者,这个插件都值得一试。

    可以在这里找到下载链接:http://sourceforge.net/projects/eclipsesql/

    posted @ 2005-06-06 16:15 laogao 阅读(2501) | 评论 (3)编辑 收藏

    不知不觉间,Struts已经五岁了,这是一个相当成熟的Web框架,事实上的标准,至今还有很广泛的应用。

    我忍不住想,其实像Struts、Spring、TestNG这样的东西背后的核心思想很简单、清晰、直截了当,(当然也有不少创新和大胆的设计)而且多数是业余时间完成的第一个版本,为什么我们中国的程序员就不能做到呢?思维方式?体制?环境?不管是什么,这都是中国软件行业的悲哀。

    期待中国原创的开源框架/工具。

    posted @ 2005-06-01 09:36 laogao 阅读(679) | 评论 (3)编辑 收藏

    目前我们每个人的页面标题前,都有BlogJava字样,这个我没意见,但是我觉得格式并不好。就拿我自己的blog来说,现在的格式是"BlogJava-Sean's stack trace",我觉得从美观和习惯上讲最好能加两个空格:"BlogJava - Sean's stack trace"。

    大家的意见呢?

    posted @ 2005-05-27 11:05 laogao 阅读(927) | 评论 (6)编辑 收藏

    http://www-128.ibm.com/developerworks/opensource/library/os-jface1/

    这里有一篇很好的SWT入门文章。

    posted @ 2005-05-25 16:35 laogao 阅读(2512) | 评论 (1)编辑 收藏

    谢谢kukoo提供的链接,在这篇eWeek的报道中,Eclipse Foundation的executive director,Mike Milinkovich这样形容Eclipse阵营对Sun的心态:“We're not focused on hurting them; we're focused on helping us.” - 我们的注意力并非在如何伤害他们,而是如何帮助自己。我想这很好的诠释了Eclipse对Sun的心态。

    最近看到太多的关于NetBeans和Eclipse的争吵,其中很多都是NetBeans的支持者出于对NetBeans项目组的辛勤劳动的肯定和也许是某种意义上的同情,或者真的喜欢使用NetBeans,指出Eclipse有什么什么地方不好,而NetBeans又有多好多好。但是醒醒吧,我觉得整件事是NetBeans阵营太过将Eclipse作为对手和参照物,而Eclipse似乎没有太理会,它有更大的目标。两相比较,两个平台也好IDE也好的竞争是什么结论也就不言而喻了。

    对于Sun的开源策略,有行家分析说Sun只是想从开源得到社区支持等好处而并不愿意做出太多贡献和牺牲。这些从近年Sun对JDK/JRE采取的相对严格的发行机制、Solaris的开放源代码、对JCP的控制、同微软的合作、以及最近有关Harmony的争执中都能找到很好的佐证。Sun到底在想什么呢?也许从Sun的角度,他们有足够的理由这样做,我们还是不要过多地妄加猜测了吧。

    时间会证明一切。

    posted @ 2005-05-25 15:38 laogao 阅读(3957) | 评论 (19)编辑 收藏

    刚才忘了说,在3.1M7这个版本中,已经自动支持类似KeepResident插件的功能,当我们在Windows环境最小化Eclipse窗口的时候,Eclipse使用的这一块内存不会再被Windows无聊的回收了。好处是显而易见的,我们不再会碰到离开Eclipse再回来的时候那烦人的等待了。

    posted @ 2005-05-25 15:09 laogao 阅读(1484) | 评论 (6)编辑 收藏

    下到Eclipse3.1M7后的第一件事当然是看看那个Ctrl-Z回滚的小bug,以前的stable或release版本都存在这样的问题:当你对文件修改但未保存,按下Ctrl-Z可以回到上次保存的状态但Eclipse仍然认为该文件是改动过的。经过测试这个bug确实fix掉了。

    另外我还无意中发现一个有趣的新功能。我们知道通常一个包含CVS信息的连接字符串是类似如下的样子:

    :pserver:anonymous@cvs.sourceforge.net:/cvsroot/azureus

    当我们在Eclipse的CVS Repository视图下面添加Repository Location的时候,我们必须分别手动的填写上面的字符串中包含的信息。在3.1M7中,只需要Ctrl-V粘贴这个字符串到新建Repository Location的对话框,所有信息都会被自动分解和填充,这样对我来说真的方便多了。

    Good job, Eclipse!

    posted @ 2005-05-25 15:08 laogao 阅读(699) | 评论 (0)编辑 收藏


    经常使用Eclipse的朋友大约都知道,Eclipse的文本编辑器一直有一个小小的bug:当你做了修改,但是没保存的话,就算你使用Ctrl+Z回退到改动前的版本,该文件仍然是标记为"*",除非你再次Ctrl+S保存,或者选择关闭然后选择不保存。

    这个Bug虽然小,但是当你的项目是多方开发并使用CVS等版本控制的时候就变得很麻烦:你想看别人的代码,但是写的很糟糕,于是你为了自己看得方便就重新排版或者做一些格式修改,或者你不小心做了什么修改,如果你回退回去,编辑器还是认为你修改了,于是你很容易一不小心按了保存,这样CVS便当作改动将本地版本号增长了一次,当你接下来同步的时候就会出现出局更改,当然,如果你只看入局更改,问题倒不大,但是等下次别人再次修改那个文件并上传以后,这个文件同步的时候就会被处理成冲突,而且很可能你就忘记了你改过什么,这就带来了不必要的麻烦,你可能面临做一次文本比较。

    通常我的习惯是如果看了某个文件又不小心自己保存了的话,我会立即从CVS拿最新的覆盖,但是毕竟这应该是IDE可以在一定程度上帮我避免的。

    现在好了,这个bug已经被fix掉,在所有版本号大于20050420的build中间,我们可以不必再理会它了。

    https://bugs.eclipse.org/bugs/show_bug.cgi?id=21493

    posted @ 2005-04-22 09:03 laogao 阅读(1021) | 评论 (4)编辑 收藏


    Not likely, but the prospect may NOT look as good for JBuilder. Here's an interview transcript with Borland's Raaj Shinde:

    http://www.itwriting.com/jbuilderfutures.php

    posted @ 2005-04-13 23:18 laogao 阅读(825) | 评论 (2)编辑 收藏


    自从接触J2SE 5.0以来,似乎Cedric Beust这个名字就在脑海中挥之不去,大约是跟他在java.sun.com的一篇对J2SE 5.0新特性的介绍文章有关吧,其实这个法国人给人留下印象最深的是他基于JUnit和J2SE 5.0的注解(Annotation)的思想创作的测试工具:TestNG。

    用过JUnit的朋友,尤其是经常使用的朋友大概会跟他有同感,那就是JUnit有些时候功能显得太单调,不够灵活,但是很少有人像他那样自己另起炉灶去写一个自己的测试框架。也许这就是我们跟发达国家在技术创新上的差距吧,我想这至少是意识上的差距。

    国外各大网站已经前前后后做了不少介绍,国内网站则似乎还没有十分重视这个看上去不起眼的家伙。这究竟是个什么样的工具呢?有些什么特色?大致总结一下就是:

    对Java注解的支持
    利用XML配置测试过程
    不需要实现接口或继承类(如JUnit的TestCase/TestSuite)
    支持独立的方法和分组
    支持并行测试
    测试方法支持传入参数
    任意制定的调用次数和成功率统计

    现在,我们有机会在Eclipse环境尝试这个测试框架了,还要多多感谢TestNG插件的作者Alexandru Popescu牺牲掉那么多自己的时间。怎么样?跃跃欲试?该插件的update site是:http://beust.com/eclipse/,需要注意的是它目前只支持Eclipse 3.1版本,因为Java注解的原因。

    为了简单做一个演示,我随便写了一些代码:

    [FooCalculator.java]

    package sean.home.test;

    public class FooCalculator {
        
        
    public static int increaseByOne(int origVal) {
            
    return ++origVal;
        }


    }


    [FooCalculatorTest.java]

    package sean.home.test;

    import com.beust.testng.annotations.
    *;

    public class FooCalculatorTest {
        
        
    private int origVal;
        
        @Configuration (beforeTestClass 
    = true)
        
    public void setUp() {
            origVal 
    = Integer.MAX_VALUE;
        }

        
        @Test
        
    public void testIncreasByOne() {
            
    int result = FooCalculator.increaseByOne(origVal);
            assert result 
    > 0;
        }

        
    }


    [TestFooCalculator.xml]

    <!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >

    <suite name="Custom Suite" >
        
    <test name="To Test FooCalculator" >
            
    <classes>
                
    <class name="sean.home.test.FooCalculatorTest" />
            
    </classes>
        
    </test>
    </suite>


    完成以后,我们可以在Eclipse中右键选中我们的测试类或者配置文件,选运行TestNG,这样我们就能看到Console视图和TestNG视图中显示的结果了。

    更多信息,参考:http://beust.com/testng/

    posted @ 2005-04-13 22:10 laogao 阅读(1181) | 评论 (3)编辑 收藏


    在Eclipse下面画UML是不是听上去比较像是很高阶的任务?我曾经简单的用过Borland的Together和它在Eclipse的插件,以及JBuilder里面的相关工具,给我的印象并不是很好,而且并不是免费的,印象中提供UML的工具都需要lisence。一直听说有一款eclipseUML插件不错,就下载了一个试试看,性能和功能都还是不错的,参考下图:

    eclipseUML_screen.jpg

    该插件支持多种UML图绘制和相关的代码生成的功能,我还在试用阶段,从现在使用情况看,除了有时候一些小bug之外,还比较顺手。

    这个插件需要Eclipse的EMF、GEF和UML2工具包的支持,如果感兴趣可以上http://www.eclipseuml.com/download/free/eclipse_3x/index.html,有详细版本说明和下载链接。需要特别说明的是:这个插件的下载版本是JAR包,也许对于已经习惯直接解压到plugins或者通过update site来安装插件的朋友有些不适应,那个站上也没有说出具体怎么安装,可能会有暂歇性茫然出现,没关系,很简单的:

    打开命令提示符,敲java -jar XXXX.jar (这个就是你下载下来的jar文件名) 即可,会出现安装向导,前提是你的path和classpath都设置正确。

    如果你正在找免费的Java UML工具,你还在等什么呢?

    posted @ 2005-04-12 16:17 laogao 阅读(28362) | 评论 (29)编辑 收藏


    记得很早以前其实就有朋友推荐在Eclipse上使用KeepResident插件,这个插件可以帮助我们在Windows平台更好的使用Eclipse这个Java应用程序。

    下载地址:
    http://suif.stanford.edu/pub/keepresident/keepresident-0.2.zip

    安装方法:
    解压到Eclipse安装目录,它实际上会增加一个plugins目录下的子目录,然后重启Eclipse,对于3.1版本的Eclipse,建议使用-clean命令行参数启动,这样会明确告诉Eclipse刷新插件等的配置。

    使用:
    在Eclipse工作台的Windows->Preferences中会看到新增的KeepResident选项页,在这里我们可以配置三个东东,最小工作集大小、最大工作集大小、VirtualLock,分别指定希望Windows分配给Eclipse的最小物理内存、最大物理内存和是否强制保持这部分内存。具体设置因人而异,可以给大家参考我个人的配置:我的环境是Windows XP SP2,256MB内存,三个选项分别是:80MB、128MB、选中。最使用情况来看,运行很顺畅。

    简单原理:
    首先,我们知道,Windows的内存实际上是物理内存+虚拟内存,必要的时候它会把应用程序占用的物理内存page到硬盘;其次,对于普通的应用程序Windows默认只会分配少量物理内存,并且这对需要相对大量内存的Eclipse来说是不能接受的;再次,一旦Eclipse窗口最小化,Windows默认就会认为它暂时不再被使用,于是会将它使用的物理内存挪出来给其他的进程使用,这样我们最小化和再次打开就会感到严重的延迟。KeepResident非常小,其实就是调用Windows的SetProcessWorkingSetSize()和VirtualLock()这两个API来实现指定Eclipse运行时内存分配的具体设置。

    更多信息:
    http://suif.stanford.edu/pub/keepresident/faq.html

    posted @ 2005-04-10 23:03 laogao 阅读(2765) | 评论 (2)编辑 收藏


    随着Eclipse的流行,我们越来越多的看到插件给现代应用程序带来的新的活力。这里有一篇很好的文章,是由来自Eclipse的IBM资深工程师Dorian Birsan发表在近期(三月)ACM Queue杂志上的。本想用中文转述一遍,苦于没有时间,又想让大家知道,只好将链接贴于此,希望能给大家对当今的插件体系结构,尤其是Eclipse的体系结构,一个比较宏观的认识:

    http://www.acmqueue.org/modules.php?name=Content&pa=showpage&pid=286

    posted @ 2005-04-08 21:51 laogao 阅读(702) | 评论 (0)编辑 收藏


    如果你在决定使用并下载这一新版本之前,想了解一下M6跟正式发布的3.0在性能上有什么区别的话(应该说比上一个里程碑版本M5a好了不少,但是仍不如3.0稳定),可以参考如下网址:

    http://download.eclipse.org/eclipse/downloads/drops/S-3.1M6-200504011645/performance/performance.php

    如果你对该版本有哪些新的特色感兴趣,可以参考:

    http://download.eclipse.org/eclipse/downloads/drops/S-3.1M6-200504011645/eclipse-news-part1-M6.html
    http://download.eclipse.org/eclipse/downloads/drops/S-3.1M6-200504011645/eclipse-news-part2-M6.html
    http://download.eclipse.org/eclipse/downloads/drops/S-3.1M6-200504011645/eclipse-news-part3-M6.html

    posted @ 2005-04-03 20:35 laogao 阅读(527) | 评论 (0)编辑 收藏


    这是我刚刚在eclipse.org站上看到的。目前由主下载站点提供下载,其他分站,如我喜欢的Pacific Internet还没有这个版本,大家赶紧下啊,我是等不及了,呵呵。

    主站下载地址:
    http://download.eclipse.org/eclipse/downloads/drops/S-3.1M6-200504011645/eclipse-SDK-3.1M6-win32.zip

    posted @ 2005-04-03 18:45 laogao 阅读(500) | 评论 (0)编辑 收藏


    TheServerSide今后将更多的关注的脚本语言,如PHP、Ruby等。这是我今天在TheServerSide.com上看到的消息。

    原文:
    http://www.theserverside.com/news/thread.tss?thread_id=33028

    posted @ 2005-04-03 13:19 laogao 阅读(405) | 评论 (1)编辑 收藏


    今天在Gmail上看到New Features,说:

    G is for growth
    Storage is an important part of email, but that doesn't mean you should have to worry about it. To celebrate our one-year birthday, we're giving everyone one more gigabyte. But why stop the party there? Our plan is to continue growing your storage beyond 2GBs by giving you more space as we are able. We know that email will only become more important in people's lives, and we want Gmail to keep up with our users and their needs. From Gmail, you can expect more.

    哈,Gmail真是做得越来越好了。

    /* BTW */

    You are currently using 7 MB (0%) of your 1712 MB. 这个是我的Gmail邮箱中的一段文字,从它看来现在的空间大小是1712MB,不知道是不是具体容量增长幅度因人而异?

    posted @ 2005-04-02 09:22 laogao 阅读(787) | 评论 (6)编辑 收藏

     

    今天在TheServerSide.com上闲逛的时候发现首页又多了一个免费电子书节选的链接:由Manning Publications出版的Jakarta Commons Online Bookshelf中的第六个模块 – Validating data with Validator。下载地址:

    http://www.theserverside.com/articles/content/JakartaCommons_Chapter6/JakartaCommons_Chapter6.pdf

    虽然只是节选,但是我们不妨还是拿下来看一看,其实就这一章节来讲,还是比较有意思的。另外,通过浏览这部分电子书,我发现它除了讲Validator之外,至少还给我带来了两样东西:

    1-      它提供了一份Jakarta Commons组件的清单,在Jakarta Commons项目都有哪些组件,以及每一个组件大致实现什么功能,单从官网上看要整理出一份这样的清单也不是很直接。这些有价值的组件包括:HttpClientFileUploadNetDigesterJXPath and BetwixtValidatorCollectionsBeanUtils and LangPool and DBCPCodecModelerCLIChainLogging and Discovery

    2-      它让我对如何到官网上很快的找到相关资料和尽快掌握这些工具组件有了一个比较新的视角和出发点,它们在我眼中已不再是一堆老气而死板的代码。

    从最近看的一些东西判断,我大概是越来越喜欢TheServerSide.comManning Publications了,呵呵。

     

    posted @ 2005-04-01 22:05 laogao 阅读(724) | 评论 (0)编辑 收藏


    近来发觉CSDN的blog实在是太不稳定了,打开10次可能有9次都是运行时错误,郁闷,再不敢依赖它了。

    posted @ 2005-04-01 21:34 laogao 阅读(498) | 评论 (3)编辑 收藏

     

    今天偶然在TheServerSide.com上发现一篇挺有意思的文章,大意是讲在软件开发项目中类似日构建这样的工作为什么重要,通过它我们要达到的目的是什么。虽然文章的背景是讲一个叫做BuildMonkey的东东,但是很大的篇幅实在是我们日常很容易忽略的问题。如果你在公司做项目经理或者负责配置管理,建议你看一看这篇文章,说不定会有启发。

     

    原文见:

    http://www.theserverside.com/articles/article.tss?l=BuildManagement

     

    posted @ 2005-03-30 15:16 laogao 阅读(545) | 评论 (0)编辑 收藏


    今天在
    ADTmag.com上看到一篇文章,大意是说Eclipse虽然给IDE市场带来了非常大的冲击,但它并非是商用IDE的杀手。正如我上一篇随笔Eclipse创世纪》引用Eclipse CON 2005Lee Nackman所说,Eclipse的出现是为了提供一套被广泛认可和接受的实现了基本功能的平台,然后在这个基础上大家来开发真正满足市场具体需求的产品,同Visual Studio等竞争,而不是在底端为了一些开发人员普遍需要而大同小异的功能点各做各的一套,重复建设。这样传统的IDE提供商可以试着换一个角度看Eclipse:我们可以在一个相对成熟的基准平台上开发更高附加值的东西。文中还提到一些公司如Borland是怎样应对Eclipse的存在。

    原文见:

    http://www.adtmag.com/article.asp?id=10789

     

    posted @ 2005-03-30 13:56 laogao 阅读(939) | 评论 (2)编辑 收藏


    http://comment.news.sina.com.cn/comment/gj-61780841-0.html

    posted @ 2005-03-27 12:20 laogao 阅读(622) | 评论 (5)编辑 收藏


    今天无意中在TheServerSide.com上闲逛时发现一条有趣的调查结果。作为今年TheServerSide举办的Java研讨会活动的一部 分,每天上午组委会都会向与会代表做一些问卷调查,其中有一项叫做:What is your preferred Java IDE? 你最喜欢的Java IDE是什么?下面是这项调查的结果:

    What is your preferred Java IDE?
       
    Eclipse 53.3%
    emacs 2.1%
    IDEA 19.8%
    Java Studio 0.8%
    JBuilder 6.6%
    JDeveloper 3.3%
    Netbeans 2.5%
    vim 3.3%
    WSAD 7.4%
    other 0.8%
    Vote count: 242

    我们可以看到,总共有242人参与了调查,超过半数选择了Eclipse,算上WSAD这个数字甚至超过了60%,IDEA紧随其后占到了近五分之一,而NetBeans只有可怜的2.5%,甚 至连JDeveloper都比不上,Java Studio则更惨,还不到1%。参加这次大会的515人大都是Java界的重量级人物和业界精英,他们和整个TheServerSide社区一起构成了 推动Java技术,尤其是服务器端技术不断前进的一支重要力量。上面的结果能不能说明什么问题大家就自己作判断吧。


    原文见:
    http://www.theserverside.com/articles/article.tss?l=TSSJS2005

    posted @ 2005-03-26 19:39 laogao 阅读(744) | 评论 (0)编辑 收藏

     

    仅仅是为了好玩,我们来看一个EclipseC#插件,该插件由一家法国公司Improve Technologies开发和维护,目前支持Eclipse 3.0.NET Framework 1.1

    首先,我们需要在本机安装.NET Framework SDKEclipse

    接下来我们通过Eclipse和一个update site来下载和安装该插件:在Eclipse的工作台选择Help -> Software Updates -> Find and Install...,选择Search for new features to install,选下一步,点New Remote Site...,输入一个名称和如下的URL

    http://www.improve-technologies.com/alpha/updates/site.xml

    点完成,这时Eclipse就会开始载入上述XML文档并查找相关信息。需要注意的是这个site.xml实际上同时包含了Improve Technologies的其他插件,我们并不需要。在接下来的Search Results页面,我们只用勾选C Sharp的条目即可。选好以后点Finish,这个时候Eclipse就会开始安装这个插件,完成后会提示是否重启Eclipse,选是。

    重启Eclipse之后,我们作最后的一些配置。打开Window -> Preferences,我们可以看到新增的C# Preferences,在这里可以指定C#编译器类型和位置,如:C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\csc.exe

    大功告成,我们来试验一把。

    新建一个空白项目,在项目中选New -> Other,或者用快捷键Ctrl + N,选择C#目录的C# File创建一个新的C#文件,输入一些测试代码,选保存,这时默认会自动编译该文件,我们可以在下方的%cSharpConsoleView中看到编译器的信息,如果一切顺利,在我们的Project目录下面就会多出来一个exe文件,双击这个exe文件,我们的C#程序就可以跑起来了。补充说明:我们可以右键cs文件,选PropertiesAlt + Enter)来指定输出文件类型和其他命令行参数等。

    这个插件实现的功能其实相当有限,基本上只是利用现有的compiler,然后把一些操作简化了,然后有一些syntax highlight的功能,甚至也结合compiler做了一些代码级的简单错误提示。但是它不失为一个有趣的插件。

    我用作测试的代码如下:

    using System;

    namespace MainNamespace {

           
    public class MainEntry {

                  
    public static void Main() {
                         
    // Add your code here
                         Console.WriteLine("To test C# plugin in Eclipse");
                         
    for (int i = 0; i < 10; i ++ ) {
                                Console.WriteLine(
    " # " + i + " # ");
                         }

                         Console.ReadLine();
                  }


           }


    }


    Just for fun.

    用这个插件来做一些简单的验证和思路整理是可以的,如果真的要选一款免费的C# IDE做开发用,我想我会考虑SharpDevelop。

    posted @ 2005-03-22 22:49 laogao 阅读(1654) | 评论 (0)编辑 收藏