软件设计从最原始的机器指令走到今天企业级这一步,经历了无数革命性的演进和变革. 由计算机运算能力和普及程度的高速发展所推动的软件生产业的屡屡不适,正给各种新思想,新事物的诞生创造了土壤,使得这个领域的创造性活动非常活跃.
从机器语言到汇编语言,从汇编语言到类自然语言; 从头到尾的单条控制流到归纳出重用函数的结构化方法,再到进一步封装和重用的面向对象方法. 每一次进步都是激动人心的变革.
然而面向对象方法如日中天,极尽辉煌的今天,面对新生的很多挑战和问题,也开始显得苍白无力; 睿智的架构师和程序开发者都在为这些问题的解决寻找着更先进有效的方案, 层出不穷的体系架构,开发框架,包括J2EE等很"官方"的规范, 无不是这些努力的一个个生动体现.
然而OSI的7层模型最终没有代替TCP/IP的5层模型, 虽然它更为先进和完美. 我觉得众多厂商和用户的偏向支持是一个表象的原因, 这个原因的原因, 是因为7层模型毕竟没有比5层模型有本质的优势, 商业环境一直是追求性价比的效率优先原则,我们可以说是用7层替换5层的代价太大,但也可以说是这么做的好处不够大.
那么在程序设计方法学领域,我们会不会像互联网基础设施一样,最终找不到一个本质性演进的出路呢? 我们能发明并且实现出比现有这些架构和框架有压倒性优势的编程语言级别的机制,有所突破吗?
我的答案是: 有! 但是绝非易事. 同时, 我希望这一次本质性的演进,能够由中国人来完成.
企业级软件工程的新特性,我认为核心在于规模的可伸缩性,以及人力资源角色的细分所带来的协作要求.
对于应用规模的可伸缩性,需要一系列核心技术来支持,可能通过群集,网格等等,这些技术已经足够高深到没法让一个企业要求它的大部分开发人员都熟悉和掌握相关的开发技巧和能力. 这其实可以归结为需要把掌握这些核心技术的外部专业团队作为企业本身开发队伍的一个角色来看待和协调的问题. 所以最终, 开发人力资源的多元化, 如何分配其角色,如何协调他们之间的交流和合作,成为企业级软件开发过程的主体问题.
那么现在我们就可以发现,与迎面而来的多角色化软件开发需求相比,面向对象的程序设计方法已经相形见拙,它所知道能够打交道的角色只有一个: 程序员.
逻辑注入是解决这个问题的一种方法, 也就是更聪明的程序员担当起其中一个角色, 那就是小心的在普通应用程序员不知道的情况下, 让他的代码有一些新的功能和表现. 然而这需要极大的技巧和悟性, 同时冒不小的风险. 从AOP的成功可见很多人已经选择了这种方式.
J2EE EJB实现的本质其实还是逻辑注入, 只是它通过官方的"规范", 比较好的约束了应用程序员的作风, 降低了窜改代码的风险. 但是对于实现支持的应用服务器/容器来讲, 代码生成几乎是唯一的手段.
当然,我也知道接口是个很好的东西,在很大程度上也能解决这个问题. 但是别忘了,接口中的东西必须全部是public修饰的,在java中你即使不这么写,编译器也会给你自动加上去. 这带来的是一种退化, 好像回到了C语言的时代,没有权限修饰符,有人给你一个struct,里面全是函数指针.
现在让我们来设想一下,如果下一代程序设计语言被设计为有角色概念,同时能够支持不同角色的代码之间通过一定的接口进行交互的话,程序将会怎么变化.
我们以一个餐馆,它营业过程中需要洗脏盘子的案例来模拟程序的各种写法:
1. 最初,这个餐馆很小,盘子都是由一个洗完工(DishWasher)自己来洗.
public class Dish
{
private boolean dirty=false;
public boolean isDirty()
{
return dirty;
}
public void use()
{
dirty = true;
}
public void wash()
{
dirty = false;
}
}
public class Food
{
private String kind;
private double amount;
Food(String kind, double amount)
{
this.kind = kind;
this.amount = amount;
}
public String getKind()
{
return kind;
}
public double getAmount()
{
return amount;
}
}
public class Restaurant
{
public class Meal
{
private Dish dish;
private Food food;
Meal(Dish dish, Food food)
{
this.dish = dish;
dish.use();
this.food = food;
}
public void eat()
{
food = null;
}
public void recycle()
{
dirtyDishes.enqueue(dish);
}
}
private Queue<Dish> dirtyDishes = new BlockingQueue<Dish>();
private Queue<Dish> cleanDishes = new BlockingQueue<Dish>();
private final int NUM_DISHES_BOUGHT = 50;
Restaurant()
{
for(int i=0; i<NUM_DISHES_BOUGHT; i++)
cleanDishes.enqueue(new Dish());
new DishWasher.start(); // 雇的一个洗碗工
}
public Meal serve(String kindOfFood, double amount)
{
Dish dish = cleanDishes.dequeue();
Meal meal = new Meal(dish, new Food(kindOfFood, amount));
return meal;
}
private class DishWasher extends Thread
{
public void run()
{
Dish dish = dirtyDishes.dequeue();
dish.wash();
cleanDishes.enqueue();
}
}
}
public Customer
{
private void dine()
{
String kindOfFood = wantingFood();
double amount = nowAppetite();
Restaurant restaurant = selectOneRestaurant();
Meal meal = restaurant.serve(kindOfFood, amount);
meal.eat();
meal.recycle();
}
public void main(String[] args)
{
new Customer().dine();
}
}
2. 后来,餐馆规模有所扩张,一个洗碗工忙不过来,就又雇了两个,同时又多买了原来2倍的盘子,于是变成这样:
private final int NUM_DISHES_BOUGHT = 150;
Restaurant()
{
for(int i=0; i<NUM_DISHES_BOUGHT; i++)
cleanDishes.enqueue(new Dish());
new DishWasher.start(); // 雇的一个洗碗工
new DishWasher.start(); // 新雇的洗完工
new DishWasher.start(); // 新雇的洗完工
}
3. 经过不断努力,餐馆生意突飞猛进,为了满足需要又买了更多盘子,多雇了更多的洗碗工. 但是这个时候,老板发现,这个方法不像以前那么有效了,因为餐馆的空间有限(只有一个JVM),多出来的盘子堆得很挤(内存紧张),同时洗碗工越多,他们之间就越显得碍手碍脚的(线程太多了互相竞争CPU时间). 老板为此几度扩建餐馆(买更好的服务器), 但是到了最后实在无法再扩建了-- 周围的地皮很变得贵,邻居也都开出天价的拆迁费(CPU已经装了16个,内存也已经没法再大了). 再多买盘子,多雇洗碗工,餐馆的业绩反而下降了(超出服务器负载容量,导致了系统颠簸).
4. 于是老板又想到开一家专门洗碗的分支机构(添加独立的洗碗专用服务器), 但是老板对管理分支机构和协调这样的业务往来并没有什么经验,他又是个很谨慎的企业家,所以开始了解相关的信息和技术. 经过调查研究,他发现以下这些情况:
a. 有一些大小和布局合适的厂房正在出售或者出租(服务器+基本操作系统).
b. 还有一些房产商提供进一步的解决方案,包括给厂房安装工业洗碗机和捆绑销售有一定防震性能,防止盘子被颠碎的卡车(系统集成商).
c. 还有一些专业提供洗碗服务的公司(服务提供商),但是你必须自己把脏盘子送过去,再把干净盘子领回来,他们规定送盘子和取盘子的地点(API).
各家都有一定的销售业绩和客户群. 不过经过对他们客户的观察和总结发现:
a. 他们的用户基本都是一些老手, 他们自己都非常精于厂房和里面设备的管理. 餐馆老板知道自己并不像他们那样深刻掌握了这方面的路子,如果采用这个方法学习成本和风险都很大.
b. 他们的用户在这个特定方面的需求规模一般都比较小, 比较平常和容易管理; 有几家规模大的企业使用他们的服务过程中发现漏洞百出,被搞得焦头烂额.
c. 好像大部分大规模的用户都选择了这样的服务,不过他们也不得不自己聘请了一些专业人员来和这些公司联络,处理日常事务. 这些专业人员有时候会跳槽,留下一些棘手的问题.
5. 正当老板为仅有的几个选择举棋不定的时候,从一个偶然的机会,他听说现在有一家叫做 众能(Capabilities) 的集团公司, 旗下有一家 洗刷家(Washers) 子公司, 他们宣称提供这样的服务:
他们会给你一套标志物, 其中一个是脏盘子地点标志,另一个是干净盘子地点标志, 你只要把它们分别放在你想扔脏盘子的地方和想取干净盘子的地方就行了, 他们会处理其他的问题, 同时餐馆也不用再自己买盘子, 洗碗速度非常之快, 吞吐量足以满足这样规模餐馆的需要, 取用的时候可以保证总是能马上得到干净盘子.
于是老板决定一试,同时也学会和开始使用起支持角色的程序设计语言,最后变成这样:
public class Dish implements Washable
{
private boolean dirty=false;
public boolean isDirty()
{
return dirty;
}
// 由 role (...) 修饰的类成员,只能由列表中的角色或者本身类来访问.
role (Kitchener) void use()
{
dirty = true;
}
role (WasherPartner) void wash()
{
dirty = false;
}
}
public role Kitchener
{
}
public class Restaurant employs WasherPartner<Dish>
{
role (WasherPartner<Dish>) implements
Dish getCleanDish() as getClean();
role (WasherPartner<Dish>) implements
void putDirtyDish(Dish dish) as putDirty(dish);
public class Meal as Kitchener
{
private Dish dish;
private Food food;
Meal(Dish dish, Food food)
{
this.dish = dish;
dish.use(); // 必须是 Kitchener 角色才能调用这个方法.
this.food = food;
}
public void eat()
{
food = null;
}
public void recycle()
{
putDirtyDish(dish);
}
}
Restaurant()
{
}
public Meal serve(String kindOfFood, double amount)
{
Dish dish = getCleanDish();
Meal meal = new Meal(dish, new Food(kindOfFood, amount));
return meal;
}
}
之所以能够这样写是因为众能集团为洗刷业制定了如下标准:
public interface Washable
{
role (WasherPartner) void wash();
}
public role WasherPartner<T implements Washable>
{
implements T getClean();
implements void putDirty(T o);
}
这看起来有点像C++的多继承,但是差别在于: role WasherPartner 是一个接口而不是具体的类, 这样 洗刷家(Washers) 公司就有绝对的自由来决定如何实现洗刷的细节,可以针对不同的情况提供完全不同的实现方式.
6. 老板非常高兴,因为这样修改以后对他的顾客来说没有丝毫的变化,消费习惯完全得以保留; 同时洗刷家(Washers)公司凭借雄厚的技术实力一直服务得的非常稳定可靠,在接下来又出现的几次餐馆营业规模急速攀升的冲击下依然没有造成效率瓶颈,洗刷家(Washers)公司本身场地的扩建和设备的扩充因为专业的管理也没有影响到餐馆的正常营业. 但是美中不足的是, 因为众能集团和洗刷家公司最开始时业务量很小,所以成本相对较高,收费也比较昂贵. 但是餐馆老板知道这个模式是唯一能够有效解决他眼前经营规模增长上的方式,不然只能限制企业的规模成长. 所以为了持续发展企业规模,他一直购买使用洗刷家公司的服务. 在后来的几年间,所有业务迅速增长的企业也逐渐发现这种模式的优势,给众能集团带来了快速增长的业务,集团的运行成本迅速降低,使得这种运作模式最终成为专业服务领域的主流模式,同时使用这种模式的企业也表现出前所未有的增长潜力,整个社会经济又向前迈进了一大步.
结论:
当我们在无奈的容许AspectJ只涵盖编译范围的代码时, 当我们还在殚精竭虑的论证AOP到底应不应该访问目标类的私有成员时, 当我们还在因为编译产生的字节码会在自己不知情的情况下被改编而担心时, 当我们在为了搞清楚看到的一个public接口或者方法到底能不能调用而狂翻资料文档时, 当我们被相邻领域的名词和海量的资料折磨得狼狈不堪时, 当我们想方设法一遍一遍的给另一个同事解释自己接口中的几个方法必须遵循的调用顺序时, 当完全不知道一个方法会做什么事,却还不得不决定它是否需要事务支持时, 当因为没时间仔细阅读J2EE规范而屡犯错误时, 当不得不把java,SQL,JS,和HTML等等代码混为一谈时, 我们是不是能够获得一些动力, 来把各个方向,各种技术,各个团队,各个成员,他们的角色来理理清楚, 让它成为一种更直接,更准确,更简洁,更纯粹的语言表达方式?
相关推荐
本教程“C#程序设计语言与面向对象基础精简教程”旨在帮助初学者掌握C#的核心概念,以及如何运用面向对象的思想进行程序设计。 在C#中,面向对象编程(OOP)是其核心特性之一。OOP基于类和对象的概念,它将数据和...
面向对象程序设计是计算机科学中的核心概念,尤其在C++编程语言中得到了广泛的应用。本文主要探讨了C++中的一些关键知识点,适用于长春理工大学面向对象程序设计课程的期末复习。 1. **多态性(Polymorphism)**:...
面向对象程序设计(Object-Oriented Programming,OOP)是一种编程范式,它基于“对象”的概念,将数据和操作这些数据的方法封装在一起。在C++这种语言中,OOP的特点包括类(Class)、对象(Object)、继承...
而在面向对象的模式下,则会将程序设计成多个对象间的交互,如“棋子”对象拥有颜色属性和走步行为,“棋盘”对象负责绘制棋盘,而“规则”对象用于判断输赢情况。 #### 类与对象 - **类**是一种抽象的概念,代表...
C++是一种广泛应用于软件开发、系统编程以及游戏制作等领域的高级编程语言,它以其强大的功能、高效的性能和灵活的面向对象特性而闻名。邵兰洁版的《C++程序设计》是一本深入介绍C++语言的教材,其课后习题是学习...
面向对象思想是编程领域中的一个重要概念,它是一种模拟现实世界中对象和类的抽象思维方式,使得代码更加结构化、模块化。本资源“面向对象思想学习(精华版)”汇集了多位资深程序员的经验心得,旨在帮助初学者和有...
《Java语言程序设计案例教程》是由郑莉和刘兆宏两位专家编著的教材,旨在帮助初学者和进阶者深入理解Java编程语言。这本书通过丰富的案例,详细讲解了Java语言的各种核心概念和技术,使读者能够掌握实际编程技能。源...
面向对象程序设计综合实践任务书1是针对使用Java语言进行迷宫问题解决的一份实践指导。该任务旨在设计和实现一款电脑鼠走迷宫的软件,涵盖了算法设计、实现以及界面展示两个主要部分。 首先,算法设计和实现部分是...
### JAVA技术61条面向对象设计的经验原则 #### 原则一:避免冗余代码 - **描述**:在面向对象设计时,应避免重复的代码,这有助于提高代码的可维护性和可读性。 - **应用**:通过继承、封装等机制减少不必要的重复...
习题集内容覆盖面广,包括:Java言的基本常识、基本语法、面向对象的基本概念、数组、字符串、异常处理、文件和数据流、图形用户界面设计、小应用程序、线程、编程规范、网络程序设计、多媒体民图形学程序设计以及...
《C++Builder程序设计范例——中国象棋》是一本专为C++Builder开发者准备的实战教程,旨在通过实现中国象棋游戏的编程实例,帮助读者深入理解和掌握C++Builder的编程技巧。这本书的核心在于将理论知识与实际操作相...
同时,要理解封装、继承和多态等面向对象特性,以便创建游戏中的各种元素,如玩家、迷宫、墙壁等。 2. **数据结构**:设计迷宫通常涉及到数据结构的选择。可能的选择包括二维数组或矩阵来表示迷宫,链表用于路径...
3. **面向过程**:C语言主要基于函数,通过函数调用来实现程序的流程控制,而非面向对象的语言结构。 4. **可移植性**:由于C语言的标准化,编写的代码可以在不同平台上轻松移植,只需适配相应的编译器。 5. **丰富...
在这个项目中,开发者选择使用C++语言,这是一种强大的、面向对象的编程语言,尽管在当今有许多可视化编程工具,但C++因其底层控制能力和高效性能仍被广泛用于系统级和高性能应用。 1. C++语言:C++是C语言的扩展,...
在Java程序设计中,类和对象是核心概念,它们构成了面向对象编程的基础。面向对象编程(OOP)是一种编程范式,它基于“类”和“对象”的概念,将数据和操作数据的方法封装在一起。Java语言完全支持面向对象编程,其...
面向对象编程是一种程序设计范式,它基于“对象”的概念,这些对象封装了数据和操作这些数据的方法。 在Swift中,类(Class)是实现面向对象编程的基础。类定义了一组属性(Attributes),用于存储数据,以及一组...
本文以C++作为编程语言,利用面向对象编程思想,进行了一款五子棋游戏的毕业设计。五子棋是一种简单而策略丰富的双人对弈游戏,它的规则简单,但深入研究则需要复杂的思考和决策。 1.1 五子棋介绍 五子棋,又称连珠...
接下来,我们要讨论Java语言在这个项目中的应用。Java是一种面向对象的编程语言,具有良好的跨平台性和丰富的类库,这使得它成为实现迷宫求解器的理想选择。在代码中,我们可以定义类来表示迷宫中的节点和边,使用...
在本压缩包“Java语言程序设计与数据结构(基础篇)编程练习题第6章.rar”中,我们聚焦于Java编程语言与数据结构的基础知识,特别是第6章的相关练习题。这一章节通常会涵盖数组、链表、栈、队列等核心数据结构,以及与...