脚本的未来
1. 编程模型的比较
下面是一些关于多态、灵活性的简单例子。假设我们有如下类型定义。
class Dog {
run();
};
class Car {
run();
};
class Chair{
stand();
};
dog, car, chair 分别是这些类型的实例 instance.
我们有个公用函数。
makeItRun( param){
param.run();
}
分别调用这些实例的Run方法
A. 解释脚本,如JavaScript, Python, Ruby, FP
makeItRun( dog); // OK
makeItRun( car); // Ok
makeItRun( chair); // Runtime Error
特点: 根据符号、名字进行绑定, 运行期松耦合. 相当于语法直接支持Reflection。
B. 虚拟机编译语言,如 Java, C#
makeItRun(param){
param.run();
}
makeItRun( dog); // Compilation Error
makeItRun( car); // Compilation Error
makeItRun( chair); // Compilation Error
我们必须 让Dog 和 Car 实现相同的接口比如Runnable.
interface Runnable{
run();
}
并且这么定义
makeItRun(Runnable param){
param.run();
}
这样.
makeItRun( dog); // Ok
makeItRun( car); // Ok
makeItRun( chair); // Compilation Error
特点: 根据类型契约绑定. 编译期类型检查
C. Reflection API
我们可以使用 Reflection API 达到类似于解释脚本的效果.
makeItRun(Object param){
methodInvoke(param, “run”);
}
makeItRun( dog); // Ok
makeItRun( car); // Ok
makeItRun( chair); // Runtime Error
特点: 语法本身不支持名称符号绑定,需要使用Reflection API, 这些API由Class 结构元数据支持.
D. C++ Template
<class T>
makeItRun(T param){
param.run();
}
makeItRun( dog); // Ok
makeItRun( car); // Ok
makeItRun( chair); // Compilation Error
特点: 编译期名称、符号绑定. Very cool.
注意: Java范型不支持这种方式。Java范型进行编译期类型检查。也是类型绑定的。C++ Template并不是真正的范型编程,只是一种代码生成机制。
总结:
运行期名称符号绑定,并不适合大规模复杂系统开发,因为没有编译期类型检查,不支持Java Interface那样的契约编程。
至于Ruby on Rails, 很像一个简单的代码生成器.
对于大型系统,比起运行期名字绑定,C++ Template 的编译期绑定也许更适合,至少有编译期检查。
解释脚本最适合哪些领域?
解释脚本是运行期名称绑定,松耦合。
什么系统需要这样的特性?
对了. SOA, Web Services, such buzzwords – 定位服务名称,调用注册的对象方法.
2. 脚本的可能未来
(1) 服务器段流程控制
JavaScript, Ruby, Python, FP 支持Continuation. 有时用作状态机流程控制。
Continuation 甚至比状态机. 可以跳到运行栈的任何一层。 (类似于Exception Throw/Handling).
个人观点,并不欣赏这种使用方法。因为web-based services应该设计为尽量无状态的。状态应该尽量保持在客户端,比如AJAX/Flex. 有人说,如果有人刷新了URL,客户端保存的所有的中间状态都会丢失,最好服务器段记录所有的中间状态,这样用户下次可以回到上次的断点。对于long-session 的应用,这是对的. 但是对于long-session 的应用来说,为了均衡负载,系统更应该被设计为无状态的。所以,使用脚本的Continuation特性,仍然没有太大的意义。
(2) Web Service 客户端
AJAX/Flex 也可以看作Web Service 客户端.
脚本调用Web Service,我欣赏这种用法。用脚本表达Web服务调用非常方便清楚,不需要Reflection API 和 Code 生成。
(3) 把Mobile Code 从 客户端迁移到 服务端
假设我们有如下的Web Service客户端脚本,
If(service.do() == ok) {
nextService.do();
nextService2.do();
}else{
backService.do();
backService2.do();
}
这通常意味着要访问三次Web Service Server. 每一次需要组装一次SOAP 或者XML-RPC 消息.
把整个Script一次发送过去如何?
服务器解释整个脚本,一次执行所有的服务请求,一次返回最终结果。
这涉及到安全问题。幸好脚本比机器码或者VM指令更容易管理和控制,解决这个问题应该不难。
(4) DSL, LOP ?
Domain Specific Languages 如Business Rule, Workflow Definition 要求用户友好,更加像英语,而不是编程语言。
普通用户喜欢 关键字,而不是 API。
If a greater-than b then do … // keywords way
If(greater(a, b)) { … // API way
脚本是更高级的语言,通常比编译语言更加友好。一些脚本(如 Lisp, Scheme, etc)可以定义更多的关键字。
1. 编程模型的比较
下面是一些关于多态、灵活性的简单例子。假设我们有如下类型定义。
class Dog {
run();
};
class Car {
run();
};
class Chair{
stand();
};
dog, car, chair 分别是这些类型的实例 instance.
我们有个公用函数。
makeItRun( param){
param.run();
}
分别调用这些实例的Run方法
A. 解释脚本,如JavaScript, Python, Ruby, FP
makeItRun( dog); // OK
makeItRun( car); // Ok
makeItRun( chair); // Runtime Error
特点: 根据符号、名字进行绑定, 运行期松耦合. 相当于语法直接支持Reflection。
B. 虚拟机编译语言,如 Java, C#
makeItRun(param){
param.run();
}
makeItRun( dog); // Compilation Error
makeItRun( car); // Compilation Error
makeItRun( chair); // Compilation Error
我们必须 让Dog 和 Car 实现相同的接口比如Runnable.
interface Runnable{
run();
}
并且这么定义
makeItRun(Runnable param){
param.run();
}
这样.
makeItRun( dog); // Ok
makeItRun( car); // Ok
makeItRun( chair); // Compilation Error
特点: 根据类型契约绑定. 编译期类型检查
C. Reflection API
我们可以使用 Reflection API 达到类似于解释脚本的效果.
makeItRun(Object param){
methodInvoke(param, “run”);
}
makeItRun( dog); // Ok
makeItRun( car); // Ok
makeItRun( chair); // Runtime Error
特点: 语法本身不支持名称符号绑定,需要使用Reflection API, 这些API由Class 结构元数据支持.
D. C++ Template
<class T>
makeItRun(T param){
param.run();
}
makeItRun( dog); // Ok
makeItRun( car); // Ok
makeItRun( chair); // Compilation Error
特点: 编译期名称、符号绑定. Very cool.
注意: Java范型不支持这种方式。Java范型进行编译期类型检查。也是类型绑定的。C++ Template并不是真正的范型编程,只是一种代码生成机制。
总结:
运行期名称符号绑定,并不适合大规模复杂系统开发,因为没有编译期类型检查,不支持Java Interface那样的契约编程。
至于Ruby on Rails, 很像一个简单的代码生成器.
对于大型系统,比起运行期名字绑定,C++ Template 的编译期绑定也许更适合,至少有编译期检查。
解释脚本最适合哪些领域?
解释脚本是运行期名称绑定,松耦合。
什么系统需要这样的特性?
对了. SOA, Web Services, such buzzwords – 定位服务名称,调用注册的对象方法.
2. 脚本的可能未来
(1) 服务器段流程控制
JavaScript, Ruby, Python, FP 支持Continuation. 有时用作状态机流程控制。
Continuation 甚至比状态机. 可以跳到运行栈的任何一层。 (类似于Exception Throw/Handling).
个人观点,并不欣赏这种使用方法。因为web-based services应该设计为尽量无状态的。状态应该尽量保持在客户端,比如AJAX/Flex. 有人说,如果有人刷新了URL,客户端保存的所有的中间状态都会丢失,最好服务器段记录所有的中间状态,这样用户下次可以回到上次的断点。对于long-session 的应用,这是对的. 但是对于long-session 的应用来说,为了均衡负载,系统更应该被设计为无状态的。所以,使用脚本的Continuation特性,仍然没有太大的意义。
(2) Web Service 客户端
AJAX/Flex 也可以看作Web Service 客户端.
脚本调用Web Service,我欣赏这种用法。用脚本表达Web服务调用非常方便清楚,不需要Reflection API 和 Code 生成。
(3) 把Mobile Code 从 客户端迁移到 服务端
假设我们有如下的Web Service客户端脚本,
If(service.do() == ok) {
nextService.do();
nextService2.do();
}else{
backService.do();
backService2.do();
}
这通常意味着要访问三次Web Service Server. 每一次需要组装一次SOAP 或者XML-RPC 消息.
把整个Script一次发送过去如何?
服务器解释整个脚本,一次执行所有的服务请求,一次返回最终结果。
这涉及到安全问题。幸好脚本比机器码或者VM指令更容易管理和控制,解决这个问题应该不难。
(4) DSL, LOP ?
Domain Specific Languages 如Business Rule, Workflow Definition 要求用户友好,更加像英语,而不是编程语言。
普通用户喜欢 关键字,而不是 API。
If a greater-than b then do … // keywords way
If(greater(a, b)) { … // API way
脚本是更高级的语言,通常比编译语言更加友好。一些脚本(如 Lisp, Scheme, etc)可以定义更多的关键字。