降低选择的数量

Saturday, September 6th, 2008 9 views

如果我们要设计一个系统(或者框架,或者程序设计语言),我们是让它对实现一个功能有一种解决方案好,还是有20种解决方案好(对系统的使用者而言)?这个问题似乎很容易回答,显然是有20种方案更好些。20种不同的方案显然都有着不同的优缺点,可以使得方案的效果更加的可控,挑选的余地更大。一般情况下是是这样的,不过我最近看书的时候常常想一个问题:假使从20个方案挑选一个需要的难度和花费,比直接使用第一种方案要高很多,那么有着更多的解决办法还是一件好事么?

我的观点是否定的。我从程序设计语言的角度来举个例子。假如有一天我设计了一种新的程序设计语言,名字叫SuperPERL(我不是要讽刺Perl),其最大的特点就是自由。实现每个功能都可以有无数的写法,使得不同背景的程序员都能够轻松过渡到SuperPERL。比如,打开文件这样的操作,有如下几种写法:

//方法1:
File file=new file("path");
InputStream is=new FileInputStream(file);
Scanner s=new Scanner(is);
 
//方法2:%%表示调用shell命令
StringBuffer fb=new StringBuffer();
StringBuffer.addContent("%%echo $myfile>$fb");
 
//方法3:
 
File *file=open_file("myfile")
//方法4:
.....

看着其实很不错,SuperPERL能把各种语言都能融会贯通,程序员能够随心所欲的写出正确的代码,一个C程序或者一个Java程序员,或者Basic程序员都能顺利的使用这种语言。但是如果我们面对的是一位初学者呢?他买了A书,然后学到SuperPERL打开文件是按方法1做的,买了B书,然后学到打开文件是按方法4作的,然后他的老师告诉他应该按方法2做,他同学,一位大牛告诉他SuprePERL中最具效率的打开文件的方法应该是第二种,其他方法都是土鳖做法……如果在学习SuperPERL中的每一个功能都要发生以上的故事,我想他肯定会放弃这种编程语言的。
其次是沟通的困难,一个C转过来的程序员,很快乐的编写着SuperPERL程序:用着自己熟悉的语法,写出非常时尚的代码。但是他同事可能以前是一位Pascal程序员,不难想象这两位用着同一种编程语言共同开发项目时会产生的困境——互相之间看不懂对方的代码。

功能不是越多越方便,选择不是越多越好,对于程序设计语言,对于各种应用框架而言,尤其如此。如果我是某个语言或者框架的设计师,我的设计准则肯定会有一条是:公开的概念(也就是使用者需要学习的概念)越少越好,拥有的选择越少越好。少的概念有利于初学者的学习,也有利于开发者之间的沟通。

想想Java世界无数需要理解与学习的概念吧,Java世界正朝着相反的方向前进。

再考虑singleton在Java中的实现的一些问题

Monday, August 25th, 2008 61 views

之前的一篇文章:设计模式学习笔记:单例(singleton)模式主要介绍了单例模式的概念,及在Java中的实现,并给出了多线程环境的解决方法。

习惯上,保证一个类的实例是唯一的,主要通过使得构造器私有,通过静态工厂方法来控制实例的产生。这样做常常是有效的。但是,它并不能够真正保证类的实例是唯一的,因为,要产生一个类的实例,不一定需要经过构造器(Java语言的前提下)。

假使这个类或者其父类实现了Serializable接口,要保证该类实例的唯一性就不是那么简单了。首先,在Java1.2之前的版本中,我们是没有办法保证它唯一性的。因此,一个单例的类不应当实现Serializable接口。在Java1.2和之后的版本,开始有了解决的方法。我们需要提供一个readResolve方法,在Effective Java第57条建议中,保证singleton的readResolve方法如下:

1
2
3
private Object readResolve() throws ObjectStreamException{
             return INSTANCE;
}

还有一种创建实例不需要经过构造器的情况是类或者父类声明了Cloneable接口,这个时候有必要重载clone方法来保证唯一性。

1
2
3
4
public Object clone(){
           return this;
           // or throw CloneNotSupportedException;
}

对象与实例的区别

Monday, August 18th, 2008 132 views

在网上随便逛,看到一个有趣的讨论:对象与实例的区别。作者是这样认为的:

表现出来是这样的
String 类
String str str是对象
String str = “abc”; “abc”是实例,也是对象.
这样也能解释instance of object这种说法 str的实例是”abc”

文章是在Java的背景下讨论的,我觉得这样的理解是不对的。说他不对,是因为这样的理解违反常识。”对象”,”实例”这两个词在Java中并没有非常严格,细致的定义。因此,应当从常识的角度去理解他们。

我的理解是这样的:对象是某个东西的实例。这句话简化一下,就是对象是实例。任何一个对象,它必定是某个东西的实例。而”某个东西”,我们在Java语言中,可以认为它是类(Class),而在其他地方,比如Semantic Web的一些规范中,如RDF我们可以将其认为是一个概念。在RDF中,概念的一个实例依然是一个概念。

在Java语言的前提下,我觉得对象实例所指向的东西是没有分别的。

而在更宽广的条件下(比如,机器学习中的一些概念),那就不一定了。实例这个词表达了一种特化的过程。而对象,只是简单的是这种特化的产物。比如这样的一个概念特化过程:Thing->Animal->Human->Chinese->Chen Ju,我们可以看到Animal是Thing的一个实例,它是一个对象。同时Human是Animal的一个实例,它也是一个对象。也就是说,一个对象可以是另外一个对象的实例。

关于Eclipse将Java APP项目打包成jar的问题

Saturday, July 26th, 2008 151 views

前两天有位师弟问我,如何将写完的Java代码打包?由于他的源代码中使用了不少第三方的lib,因此有必要将lib也一并打包进去。他用Eclipse的Export功能直接打包到.jar文件,第三方lib是打包进来了,可是使用的时候还是提示找不到相应的包。

其实,为了自己的便利将别人发布的lib打包进自己project的包中不是一种合适的做法。这样做之前务必要检查一下对方的license,但不管是不是将对方的lib包括进来,既然自己的代码用到了,为了让它们正常工作,指明哪些包在那是必不可少的。师弟其实需要一个MANIFEST.MF文件,利用Eclipse生成jar文件的时候,请不要让其自动生成MANIFEST.MF,而是应当由你自己写好一个MANIFEST.MF,然后告诉 Eclipse:请使用这个文件。想了解细节,请阅读SUN的这篇规范(VIA),或者是IBM网站上的这篇JAR文件揭秘,偶这里就不多写了。

另外,Eclipse其实还有一个输出到可执行jar的功能,该功能能够帮你编写合适的MANIFEST.MF文件,帮你将你引用的第三方lib一并打包(注意license哦)。

关于

我叫陈炬,正在天津大学计算机学院->知识工程与科学研究所攻读硕士研究生。今年应届。您可以在我的自我介绍获得更多关于我的信息

订阅我的Blog


本站RSS地址| [这是什么?]
订阅到Google Reader | 订阅到 抓虾 阅读器 | 订阅到 鲜果 阅读器

其他blog

我还有一个英文blog,非常的无聊,琐碎,许多的语法错误。请谨慎访问。
Find entries :