桃之夭夭
知天之所为,知人之所为者,至矣。知天之所为者,天而生也;知人之所为者,以其知之所知以养其知之所不知,终其天年而不中道夭者:是知之盛也。
BlogJava | 首页 | 发新随笔 | 发新文章 | 联系 | 聚合 | 管理

A Walk On JSR220 Persistent API...More Ugly More Cool

Frank and I collected some Hibernate tips, and we named them with some sexy names ;-) This afternoon I tried to replace hibernate by JSR220 persistent API in a typical web application, and I found some new tips in JSR220 Persisntent API (Frank, I'm here waiting your names).

btw: I'm a believer in Peter Coad's Color Modeling approach, all the following tips are modeled in the approach. I recommend you the greate book 'Java Modeling in Color with UML' if you'd no idea about the Color UML.

1. Annotating Description with @Embeddable, and the Thing it describe with @Entity

Take Product and ProductDescription for example.

 1@Embeddable
 2class ProductDescription {
 3 private String name;
 4 private String description;
 5  . and getters and setters
 6}

 7
 8@Entity(access = AccessType.FIELD)
 9class Product {
10
11 private ProdcutDescription description;
12
13}

14

In hiberante, we could make the ProductDescription as an embedded persistent object of Product via the component tag.If the ProductDescription should be embedded in another object, we've to declare it once more.
Things become more convenient in JSR 220, because non-transite fields, whose class is annoated with @Embeddable, are treated as embedded persistent objects automatically, we'd have fine-grained persistent objects without long-winded config file.

2.Avoiding Database Field in Domain Model Using @AttributeOverride

It's claimed that Annotaton could simplify development, but considering the cost of hard-coding mapping information in source codes I prefer some other complicated ways.It's too ugly to write code like following.

1@Entity(access = AccessType.FIELD)
2@Table(name="TAB_PRODUCT")
3class Product {
4
5   @Basic
6   @Column(name="NAME", nullable=false, length=512)
7   private String name;
8}

It's sucks but could be avoided.

 1@EmbeddableSuperclass
 2class Product {
 3
 4  @Basic
 5  private String name;
 6}

 7
 8@Entity
 9@AttributeOverride(name="name", column=@Column(name="Name"))
10@Table(name="TAB_PRODUCT")
11class PersistentProduct extends Product {
12}

We could separate the domain model and the persistent model by inheritance.Although we could do the same thing in hiberante too, we have to provide lots of configuration files.Once more we'd have hierachical persistent objects without long-winded config file.

3.Avoiding Database Primary Key in Domain Model

In most O/R mapping framework, we are always asked to give a primary key or identifier to our domain model, and we are suggested using meanless identifier instead of domain-specified identifer.It's kinda of Domain Pollution.Although we couldmake the domain model more clearer via inheritance, it's pointless for common usages.
Fortunately, we HAVE TO separate domain model and persistent model(as above mentioned), so that we can throw this bad habit away conviniently :D

1@EmbeddableSuperclass
2class Product {
3}

4
5@Entity
6class PersistentProduct extends Product{
7
8   @Id private long primaryKey;
9}

Conclusion

After two hours walking around JSR220 persistent API, I figured out that JSR220 mixed ugly into convenience... and it's quite easy to write ugly codes in jsr220...so that we've to insist on using OO and the convenience jsr220 provided to make our domain model as clear as possible.
Although JSR220 is more ugly than hibernate, we could get clearer domain model in jsr220 rather than hibernate, because we could not stand the unly in jsr220...weird way to make us keeping more OO...cool isn't it...

posted @ 2005-12-13 19:25 Raimundox 阅读(3218) | 评论 (1) | 编辑 收藏
 
A Walk on JSR220

从BJUG的maillist里发掘一个我以前的旧帖出来,嘿嘿

以前我和limo同志做过一个Hibernate技巧情色版....嘿嘿,这次发动大家收集一下J2SE 5和JSR 220里的改进design的tips.我下午试验JSR220的时候,找到几个

1. Implement Moment-Interval and Moment-Interval-Details Using Iterable<T>

例子, 比如Order和OrderItem,典型的一对多,一般我们这么做

1class Order {
2
3  private List<OrderItem> items;
4
5  public List<OrderItem> getItems() {
6     
7  }

8}


在J2SE5里面,

 1class Order implements Iterable<OrderItem> {
 2
 3       private List<OrderItem> items;
 4
 5       public Iterator<OrderItem> iterator() {
 6               return items.iterator;
 7       }

 8
 9      public int getItemCount() {
10             
11      }

12      // and addItem removeItem and others
13}

就可以直接来处理,

1for (OrderItem item : order) {
2}

从某种程度上利用enhanced for的语法,来简化语法。

trade-off: 不适合多个details 聚合,适合于简单的moment-interval和moment-interval-details。

2. Annotate Description with @Embeddable, and the Thing it describe with @Entity

例子,Product和ProductDescription

 1@Embeddable
 2class ProductDescription {
 3  private String name;
 4  private String description;
 5  . and getters and setters
 6}

 7
 8@Entity(access = AccessType.FIELD)
 9class Product {
10  private ProdcutDescription description;
11}

在JSR220里,如果一个field是embeddable,而且对该field没有标注为@Transite,以及使用keyword transite,自动按Embedded处理,这一点是很方便的。

这个基本没发现trade-off


3. Avoid Database Primary Key in Domain Model Using @EmbeddableSuperclass

例子,在hibernate里,总是要给Domain加一个primary key,非常的不爽.
虽然也可以通过继承结构来避免,但是配置文件太多, JSR220里,通过自动处理的annotation ,可以节约很大的工作量。

 1@EmbeddableSuperclass
 2class DomainModel {
 3//  modeling your model here
 4}

 5
 6@Entity
 7class PersistentDomainModel extends DomainModel {
 8
 9   private long primaryKey;
10}

这个大家就一目了然了

4. Avoid Database Field in Domain Model Using @AttributeOverride


Annotation虽然简化了开发,但是仍然有一个问题,就是修改mapping的时候需要修改代码,这个很不好,而且影射的时候需要在domain里硬编码field
name,这个简直就是恶心,但是还是由办法避免的。

 1@EmbeddableSuperclass
 2class DomainModel {
 3//  modeling your model here
 4}

 5
 6
 7@Entity
 8@AttributeOverride(name="property", column=@Column(name="fieldName"))
 9class PersistentDomainModel extends DomainModel {
10
11   private long primaryKey;
12}

同样,通过继承来隔离技术和Domain,然后在子类里作部署相关的动作。然后把DomainModel和PersistentDomainModel 分包,针对DomainModel编程,就Ok了。这个时候Domain会异常的干净.....

5. Model Place as Factory

其实这个是一个通则,以前好像也讨论过。

1public interface Store {
2  Order newOrder();
3  // and others;
4}

基本上下午2个小时的成果就这么多,我是在尝试用JSR220 API代替以前我和limo写的那个珍珠商城订单部分得到的一些tips。总体而言,JSR220还是挺好的,我们可以很自然的运用一些模式和OO的手段还避免它的不足。同时上述做法在hibernate里也可以做,但是由于比较麻烦,大家一般还是做不到。JSR220里,正是通过它的毛病强迫我们这么做.....(汗),也算体现出约定了。

posted @ 2005-12-12 11:08 Raimundox 阅读(1999) | 评论 (1) | 编辑 收藏
 
Why Inconsistent Concepts Considered Harmful

Tao Wen , a friend of mine and a new ThoughtWorker, put a comment on my last article.

so, you think the consistent thing means a lot? But how do you think the gracious or elegant feeling mean to the real expressiveness of business requirements? We can see lisp is very successful in researching area because of the simplicity nature inside which is also true to Smalltalk. But why they aren't successful in biz world? I think that is the problem you should further study, "how can the consistent feeling mean something to our everyday programming life?".

First of all, I should admit that I'd never thought about this question before, becasuse I think hankering after consistent concepts is some nature of us. The question enlightens me to thinking deep. Here are my points.

1.Complexity

Inconsistent concepts bring complexity.I'll give two examples.

First one is something in Lisp. Lisp has a very simple computing model called λ Calculation. There are three elements in this computing model: Function, λ Operator and · Operator. λ Operator picks up free variable from the function, and · Operator applies the variable with a concrete value. The whole evaluation-application thing is what we called symbolic algebra in math.For example, if we've a function whose expression is x + y.

((λx (λy . x + y)·3)·4)
=((λx. x+3)·4)
=4 + 3
=7

Since Lisp is kinda implementation of λ Calculation in computer, we could do the same thing in Lisp (and its dialects).

(define f (lambda x (lambda y (+ x y))))
(apply (apply f 
3) 4)

or we could use some syntax sugar

(define (f x y) (+ x y))
((f 
3) 4)

Most of things in Lisp are focus on evaluation, and the evaluation should be done in a simple consistent way: evaluating, applying value and then returning the value without any change to enviroment. It is the very same way that we do something in math.
But variable assignment was introduced to Lisp, so some functions  which change enviroment instead of simple evaluating came to Lisp.For example:

(define (bad-f x y) 
  (begin 
     (set
! z 5)
     (
+ x y)))

That bad function changes value of symbol 'z' while evaluating x + y. It is the variable assignment which breaks the consistent concepts. The consistent concepts suggests that function should do and only do evaluation. We must find a more complicated computing model to replace the simple elegant mathematical one.Here inconsistent brings complexities in computing model.

The other example comes from Java. Java is considered to be an object-oriented programming language with single root type system. Conceptually speaking, everything should be an object.But for some perfermance reason, Java has some primitive types (such as int, double, float etc.) too.Those primitive types introduced a algebraic world which paralleled to the object world, and broke the consistent concepts.Althought Java has some wrapper classes for those primtive types, they are not enough for filling the gulf between object and algebra.
We could use new Integer(3) to represent 3 in object world, but we could not simply translate

3 + 4 * 5

to

new Integer(3) + new Integer(4) * new Integer(5)

Algebraic calculation and  object message sending are totally different. Although we could do that in Java 5, it also has lots of differences.Auto-boxing treats object as primitive instead of operator overloading in C++ which treats operator as object message sending.So in my opinion, auto-boxing in java5 is awful. Assginments and storage of primitive type and object have lots inconsistent semantics too. This inconsistent would bring complexity when we use Collection API(Remember Primitive Collection in Commons Collection Project? )

2. Side-Effect

The mainly cause of side-effect is  putting some inconsistent concepts together. I'll also give two examples.

First example is the well-known side-effect in functional programming, which is caused by mixing Von-Nouma-style-things into λ Calculation. There are lots of discussion about this topic in functional programming community.It's meanless to repeat that again.

Second example comes from half-blooded object-oriented languages, for we'll find both object-oriented things and procedure-oriented things in these languages, and it'll be much more easier to write code in procedural way instead of object-oriented way.For example, we'd write code like this:

1if (order.getState() == Order.CANCEL)
2   do something for cancel;
3else if(order.getState() == Order.PAID)
4   do something for paid;
5else if(order.getState() == Order.DELIVERY)
6   do something for delivery

instead of :

 1public abstract OrderState {
 2
 3   protected Order _order;
 4   
 5   protected OrderState(Order order){
 6      _order = order;
 7   }

 8    
 9   public abstract void handler();
10}

11
12class CancelState extends OrderState {
13
14   public void handler() {
15      do something for cancel;
16   }

17}

18
19order.getState().handle();

For the keywords, it's convenient to write procedural codes as first segment, but for easy maintenance, it's better to write object-oriented codes as the second one.There are two inconsistent way to write code, and the side-effect is depend on how object-oriented the language is. It's more easy to write code like first one in C++ , and more easy to write code like second one in Ruby and Smalltalk. Actually, it's very hard for me to write code like first one in Smalltalk.

3. Constructing Software in a Recursive Way

There is a more large topic, maybe I'd better talk about this latter.

4. Elegance

Some aesthetic feelings comes from consistent concepts.I'll have the feeling of elegance if I could understand some complicated things via some consistent concepts.Take Newtonian System and Maxwell formula for example, they both are the elegant way to resolve problem via few consistent concepts.
posted @ 2005-12-11 01:59 Raimundox 阅读(2726) | 评论 (1) | 编辑 收藏
 
Why Inconsistent Concepts Considered Harmful

小tao给我找了一个非常好的题目:

so, you think the consistent thing means a lot? But how do you think the gracious or elegant feeling mean to the real expressiveness of business requirements? We can see lisp is very successful in researching area because of the simplicity nature inside which is also true to Smalltalk. But why they aren't successful in biz world? I think that is the problem you should further study, "how can the consistent feeling mean something to our everyday programming life?".


我承认以前没有考虑到这个问题,因为我以为追求概念一致性是一种不言自明的天性。那么为什么要一致性很重要呢?我有这样一些想法。

1. 复杂性

概念不一致产生首先产生的一个恶果就是复杂性,这里我将举两个例子。

第一个关于Lisp的。Lisp本身具有一个很一致很简单的计算模型——λ 演算。在这个计算模型中,基本元素是函数,λ运算符,·运算符。语义也是简单明确的,lambda运算符提取出函数中的自由变量,然后再由apply对自由变量赋值。整个计算过程就是函数(符号)求值的过程。例如对于函数x + y,我们可以这样来求值。

((λx (λy . x + y)·3)·4)
=((λx. x+3)·4)
=4 + 3
=7

由于Lisp多少可以认为是λ 演算的一种实现,我们可以类似写出Lisp代码

(define f (lambda x (lambda y (+ x y))))
(apply (apply f 
3) 4)

或者更加简单的写为

(define (f x y) (+ x y))
(f 
3 4)

所有在Lisp中的程序,我们都可以用一种一致的概念来表达,就是符号求值,我们对一个符号应用一些值,然后这个符号完成计算并把结构返回给我们,在计算的过程中,符号对外部环境没有任何破坏和依赖。但是Lisp中引入了赋值,于是存在一些符号,不仅仅是来计算,同时他们还能改变环境。

(define (bad-f x y) 
  (begin 
     (set
! z 5)
     (
+ x y)))

这个函数不仅仅求x + y的值,同时修改了符号Z的值。赋值的引入破坏了函数只求值而不影响环境这个概念的一致性。于是我们不得不寻找一个更加复杂的也更加混乱的计算模型,来代替简单优雅的λ 演算。于是不一致的概念带来了思维上的复杂性(不过Lisp中的概念不一致除了产生了复杂之外,还激发了人们对于简单计算模型的向往从而产生了函数式编程风格,这也是我最爱的编程风格之一)。

概念不一致带来的复杂性距离我们最近的应该是Java中的简单类型,Java本身是一个单根的面向对象语言,从概念上讲一切都应该是对象,而且由于性能考虑而出现的简单类型,引入了代数性的世界观的同时,破坏了面向对象的一致概念。Java中虽然有包装类来做补偿,但是仍然不能弥补概念上的断裂。我们可以用

1new Integer(3)

来代表对象概念中的3,但是

3 + 4 * 5

不能对等的翻译为:

1new Integer(3) + new Integer(4) * new Integer(5)

简单类型具有的运算符和对象类型的消息发送概念上是不一致的。虽然我们可以在Java 5中使用上述的代码,但是Java 5的Auto-Boxing更多的把对象类型当作简单类型进行数据运算,而不是像C++中的运算符重载一样把数据运算当作一种特殊消息传递,虽然语法上有相似的功能,但是概念上大异其趣,对于我这个OO分子而言,Java 5的Auto-Boxing实在是恶心到不行。同时简单类型和对象类型在赋值语义和存储模型上也存在很大的不一致,这种不一致性在使用Collection API的时候带来了一些复杂度。(还记得Commons Collection里那些Primitive Collection吧?)

2.副作用

概念不一致产生的第二个恶果就是副作用,我大概想了一下都有哪些可能的副作用,结果让我很寒,我能想到的副作用,大多数是由于在另一种模型中引入了冯语言的因素从而造成了概念上的不一致而引起的。其中最为人知的....还是赋值在函数式编程中的副作用...这个在函数式编程社区有很广泛的讨论,我只说一点,为什么命令语言是有害的。

冯语言或者说命令式语言主要用于刻画对计算机操作的序列,并不关心序列的内在关系。也就是说,我们可以把一些完全没有联系的指令写在一起。因此冯语言在语义上毫无建树,同时在抽象上也止步于子程序(一砣指令和另一砣指令)。冯语言具有很强的时间耦合性在存储上也强烈的倾向于线性存储。目前大多数难处理的问题,可以归结为计算模型和操作语义的不一致,甚至有些学者认为是冯结构严重制约了计算机的发展。因此冯语言被函数社区看作一个很危险的副作用,极力避免之。

概念的不一致产生的副作用在混血的OO语言中也很明显,尤其是在命令式语言中加入面向对象机制,而且使用面向对象作为类型系统的扩展,使用过程式的方法来控制流程。过程和对象的不一致本身就给了程序员一种暗示,你可以使用对象技术来构造类型系统,然后使用过程的方法来操作他。明显的副作用们很容易使用过程化程序,从而使得对象带来的好处被很大的削弱了(当然我们有重构来弥补这个错误),比如下面一个例子,我们很容易从写出下面的代码:

1if (order.getState() == Order.CANCEL)
2   do something for cancel;
3else if(order.getState() == Order.PAID)
4   do something for paid;
5else if(order.getState() == Order.DELIVERY)
6   do something for delivery

而不是

 1public abstract OrderState {
 2
 3   protected Order _order;
 4   
 5   protected OrderState(Order order){
 6      _order = order;
 7   }

 8    
 9   public abstract void handler();
10}

11
12class CancelState extends OrderState {
13
14   public void handler() {
15      do something for cancel;
16   }

17}

18
19order.getState().handle();

因为存在过程性的关键字if, while,处于方便的考虑,我们会写出第一种风格的代码,而考虑到易于维护,我们应该写第二种风格的代码。存在两种不一致的书写代码的风格,这个时候,副作用取决于使用的语言OO的程度,比如在C++里更容易写出第一种风格的代码,而在Ruby和Smalltalk中,更容易写出第二种风格的代码。

3.递归的构造软件

这个虽然跟概念一致有关,但是一个更大的主题,待续吧。

4.优雅,美感和无名品质

概念的一致性会产生一种优雅的美感,我觉得我们都有这种感觉,如果我们能用一种一致的容易理解且统一的方式来处理多种不同的复杂的问题,那么我们就会觉得这种方法很优雅,也很具有美感。类比物理中的牛顿定律,开普勒定律,麦克斯韦方程,都是这种简单一致而解决复杂问题的完美示例。我们更容易感觉到一致的感念产生的美感,而不一致的概念往往很难令我欣赏。或许无名品质是我对一致的概念的一种模糊的审美吧。

我大抵能想到的就这么多,不知小tao是否满意我的答卷。

 

posted @ 2005-12-10 02:17 Raimundox 阅读(1149) | 评论 (2) | 编辑 收藏
 
Say sorry to Object-Oriented Methodology

Recently I came to know and started to learn Smalltalk, an age-old pure Object-Oriented programming language. I fell in love with it quickly. Smalltalk is a very small language with some consistent concepts and abundant class libraries. I was puzzled at the very begining,  as Smalltalk has very few keywords(maybe 5 I think), and those keywords don't include any control structure(a.k.a if, while, for), how could we write programs? Althougth I know we could implement iterative sturucture via recursion, how about conditional execution? Finally I figured out that Smalltalk provides control strucutre in its class library only using some basic OO concepts. Followings are the codes from Smalltalk class library.


 1Boolean>>ifTrue: alternativeBlock 
 2  self subclassResponsibility
 3
 4Boolean>>ifFalse: alternativeBlock
 5  self subclassResponsibility
 6
 7"and True and False are subclasses of Boolean."
 8
 9True>>ifTrue: alternativeBlock 
10  ^alternativeBlock value
11
12True>>ifFalse: alternativeBlock
13  ^nil
14
15False>>ifTrue: alternativeBlock 
16  ^nil
17
18False>>ifFalse: alternativeBlock
19  ^alternativeBlock value

and then in some codes, we could do the conditional execution as follows

14 > 3 ifTrue: [Transcript show: 'Hello']


In Smalltalk, everything is Object, so that the code above means sending a message named '>' to an Integer object, whose value is 4, with an Integer object parameter. And '>' would return a Boolean object, and then we sent a message  named 'ifTrue' to it. This is a typical usage of State Pattern. Here are the equivalent Java codes.


 1public class abstract Boolean {
 2   public static final TRUE = new True();
 3   public static final FALSE = new False();
 4
 5   public abstract Object ifTrue(Block aBlock);
 6   public abstract Object ifFalse(Block aBlock);
 7}

 8
 9class True extends Boolean {
10
11   public Object ifTrue(Block aBlock) {
12       return aBlock.execute();
13   }

14
15   public Object ifFalse(Block aBlock) {
16       return null;
17   }

18}

19
20class False extends Boolean {
21
22   public Object ifTrue(Block aBlock) {
23       return null;
24   }

25
26   public Object ifFalse(Block aBlock) {
27       return aBlock.execute();       
28   }

29}

30
31public class Integer{
32  
33   public Boolean greaterThan(Integer anInteger) {
34      
35   }

36}

37

So that we could get the following code

 

14 〉3 ifTrue: [Transcript show: 'Hello']

 

which could be translated in Java like this:

  

new Integer(4).isGreaterThan(new Integer(3)).ifTrue(new BlockClosure() {

   
public Object value() {
      System.out.println(
"Hello");
      
return null;
   }


}
);

 

That's quite simple(some dynamic languages on JVM ,e.g. Groovy, do the same thing), but it indeed brings some profound changes to my thought.


First, considering that 'if','for' and 'while' are no longer pre-defined keywords, we could define our own control structures. For example, we could define Order has its own way to do something.

 

1anOrder ifExpired: [ do reactive order]
2        ifCanceled: [do something else]

 

Taking no account of performance and semantic speaking, there is no difference between the code above and undermentioned:

 

1   4 >3 ifTrue: [do something]
2        ifFalse: [do somthing]

 

More fancy, we could define a new test structure like this:

 

1anOrderTest should: [some assert] when: [do some initalize].

 

So we could have programmable control structure in Smalltalk ( something like we do in Lisp via continuation:) ), and define our own DSL easily.That's the amazing lightweight syntax feature in Smalltalk!

 

Second, we could get full capability of Von Nouma Style Programming Language via pure OO concepts.We could construct software in consistent OO concepts.

 

I began my adventure in Object technology by using C++ in 1995, and then I chose Java as my main working language. All my experiences about OO come from half-blooded OO language.So that for a long time, I thought Object-Oriented Programming is a big patch to imperative languages. The imperative languages are desgined  to record the sequence of instruments which are used to manipulate the computer, so they are lack in semantic, and poor in abstraction. Though the Object technology introduces a successful type system and provides some abstraction mechanism, I still feel sucks to program in inconsistent concepts, because I should be careful about keeping programming more in OO-style rather than in procedural-style(something like Domina Model or not, sucks!).

Once I accused Object-Oriented Methodology of all the fault, I blamed imperfection on Object-Oriented Methodology.But now, I found out it's only because that I have little talent and learning in OO, it turned out to be my fault, I should say sorry to Object-Oriented Methodology.

posted @ 2005-12-08 20:39 Raimundox 阅读(3053) | 评论 (4) | 编辑 收藏
 
Apologize to Object-Oriented Methodology

最近学习了一下Smalltalk,然后深深的喜欢上了这个古老的语言。Smalltalk语言只具有一个很小的语言核心,这个核心由大约10几个关键字和一些基础的面向对象语义构成。而且关键字都是象: . ; ( ) [ ] | := 之类的简单符号,并没有提供最基本控制的流程。最开始的时候这让我很迷惑,虽然循环结构可以用递归表示,但是分支怎么办?然后发现了一个很酷的特性,Smalltalk可以仅仅通过面向对象的语义来实现分支结构(其实就是State Pattern),具体的代码如下

Boolean>>ifTrue: aBlock
  self subclassResponsibility

Boolean>>ifFalse: aBlock
  self subclassResponsibility

True>>ifTrue: aBlock
  ^aBlock value.

True>>ifFalse: aBlock
  ^nil.

False>>ifTrue: aBlock
  ^nil.

False>>ifFalse: aBlock
  ^aBlock value.

然后就可以,

4 〉3 ifTrue: [Transcript show: 'Hello']

因为在Smalltalk里,一切皆对象且从左到右求值,于是4 > 3 返回true,true是类True的唯一实例,然后就可以对它发送消息,ifTrue:,于是调用了^aBlock value.来对传进去的BlockClosure求值。


下面是类似的java的类似代码。

 

 1public class abstract Boolean {
 2   public static final TRUE = new True();
 3   public static final FALSE = new False();
 4
 5   public abstract Object ifTrue(Block aBlock);
 6   public abstract Object ifFalse(Block aBlock);
 7}

 8
 9class True extends Boolean {
10
11   public Object ifTrue(Block aBlock) {
12       return aBlock.execute();
13   }

14
15   public Object ifFalse(Block aBlock) {
16       return null;
17   }

18}

19
20class False extends Boolean {
21
22   public Object ifTrue(Block aBlock) {
23       return null;
24   }

25
26   public Object ifFalse(Block aBlock) {
27       return aBlock.execute();       
28   }

29}

30

4 〉3 ifTrue: [Transcript show: 'Hello']就可以对应翻译为:

 

1Boolean condition = new Integer(4).isGreaterThan(new Integer(3));
2condition.ifTrue(new BlockClosure() {
3   public Object execite() {
4      System.out.println("Hello");
5      return null;
6   }

7}
);
8
9

这个看似简单的应用,却带来了两个有深刻影响的性质。

第一,由于if,else等结构不再是预定义的语法了,而与我们自己写的代码一样,属于莫一个类的特定消息,那么也就意味着,我们可以像ifTrue一样,定义自己的分支结构。
比如
   aUser ifNotRegistered: [ do redirect to register page ]
         ifExpired: [ do redirect to active page ]

在不考虑性能优化的前提下,Smalltalk认为和
   4 >3 ifTrue: [do something]
        ifFalse: [do somthing]

是具有一样的语义的。并不因为Boolean属于Kernel就有什么不同。因此控制结构也属于一个可编程的因素,这就是Smalltalk的轻语法特性。

第二,在简单的语法和完全的面向对象语义中,构造与冯诺依曼式语言完全等价的能力(这种能力在语法上表现为赋值,分支,迭代和子程序调用),于是我们可以完全用一致的面向对象的方法来构造软件。

很长一段时间以来,我都认为面向对象方法论是在命令式的冯诺依曼式语言的基础上,通过引入类型系统然后修修补补的得到的,由于冯诺依曼语言式的语言是面向操作层面上的,只是为了更好的刻画操作计算的一个命令的序列,因此冯语言不可避免的具有不完备的语义,混乱的抽象表达以及等等一系列的问题。作为冯语言的一个大补丁的面向对象方法,我也想当然的以为他虽然有了些进步,但是基础问题上面还是不能避免的,加之面向对象缺乏一种一致的构造方法,很多时候我们不得不回归到命令式或者过程式的方法来构造系统,从而破坏掉一种一致清晰的思路,在过程和对象之间不住地权衡(比如Domain Model之争),这个让人非常的不爽。在尝试了一些面向对象语言之后(我是在95年接触C++的时候开始了解面向对象的,而后主要使用Java做为开发语言),我发现这个问题是很难避免,于是我断言这是面向对象技术本身的问题,现在看来不过自己所学有限,没有真正用过纯面向对象语言而已,汗颜得很啊。这里向面向对象方法道个歉,嘿嘿。

posted @ 2005-12-08 15:11 Raimundox 阅读(1939) | 评论 (2) | 编辑 收藏
 
仅列出标题
共4页: 上一页 1 2 3 4 
随笔:36 文章:0 评论:93 引用:0
<2025年8月>
日一二三四五六
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456

常用链接

  • 我的随笔
  • 我的评论
  • 我的参与
  • 最新评论

留言簿(21)

  • 给我留言
  • 查看公开留言
  • 查看私人留言

随笔分类

  • ThoughtBlog(21) (rss)
  • 学而篇第一(15) (rss)

随笔档案

  • 2009年3月 (1)
  • 2007年11月 (1)
  • 2007年9月 (2)
  • 2007年8月 (1)
  • 2007年7月 (1)
  • 2007年6月 (1)
  • 2007年5月 (2)
  • 2007年3月 (8)
  • 2007年1月 (1)
  • 2006年10月 (1)
  • 2006年8月 (1)
  • 2006年3月 (1)
  • 2006年1月 (3)
  • 2005年12月 (12)

搜索

  •  

最新评论

  • 1. re: 丧钟为谁鸣?(4)
  • 通讯模型!
  • --ic
  • 2. re: A Patch for Ruby Watir Test Framework
  • 忘记附上我的邮箱(如果能得到你的答复,万分感谢)
    mac_cf@163.com
  • --mac_cf
  • 3. re: A Patch for Ruby Watir Test Framework
  • 评论内容较长,点击标题查看
  • --mac_cf
  • 4. re: 丧钟为谁鸣?(1)
  • 反复研究了几遍SICP。同时看了录像和书(感谢曹老师下的Video),是什么?求~
  • --qixinkui@qq.com
  • 5. re: Apologize to Object-Oriented Methodology
  • 拜读!开阔了视野!
  • --qixinkui@qq.com

阅读排行榜

  • 1. Selenium Better Pratice(8148)
  • 2. Feng Shui for Standard ML Programmers(7121)
  • 3. 丧钟为谁鸣?(1)(6946)
  • 4. Erlang Ring Benchmark(6716)
  • 5. The Keyword 'end' Drives Me Crazy(6688)

评论排行榜

  • 1. Selenium Better Pratice(11)
  • 2. 丧钟为谁鸣?(1)(11)
  • 3. A Day of Two Pragmatic Programmers' Life(9)
  • 4. ANTLR Lexer Tips(4)
  • 5. A Patch for Ruby Watir Test Framework(4)

Powered by: 博客园
模板提供:沪江博客
Copyright ©2025 Raimundox