来源:http://mzrj.itpub.net/ 

 

      面向对象技术很好地解决了软件系统中角色划分的问题。借助于面向对象的分析、设计和实现技术,开发者可以将问题领域的“名词”转换成软件系统中的对象,从而很自然地完成从问题到软件的转换.
      但是,问题领域的某些需求却偏偏不是用这样的“名词”来描述的.我的一个朋友就曾经遇到这样的问题:需要对系统中的某些方法进行日志记录,这种需要记录方法散布在40多个类中。面对这种需求,应该怎么办呢?最直接的办法就是:创建一个起类(或接口),将日志的功能放在其中,并让所有需要日志功能的类继承这个起类(或接口).如果这个需求是后期提出的.需要修改的地方就会分散在40多个文件(如果是C+十,这个数量还可能加倍)中。这样大的修改量,无疑会增加出错的几率,并且加大系统维护的难度。
      人们认识到,传统的程序经常表现出一些不能自然地适合单个程序模块或者几个紧密相关的程序模块的行为 例如日志记录、对上下文敏感的错误处理、性能优化以及设计模式等等、我们将这种行为称为“横切关注点(crosscuttingconcern)”,因为它跨越了给定编程模型中的典型职责界限。如果使用过用于核切关注点的代码,您就会知道缺乏模块性所带来的问日。因为横切行为的实现是分散的,开发人员发现这种行为难以作逻辑思维、实现和更改.
因此,面向方面的编程(Aspect-OrientedProgramming,AOP)应运而生。AOP为开发者提供了一种描述横切关注点的机制,并能够自动将横切关注点织入到面向对象的软件系统中,从而实现了横切关注点的模块化.通过划分Aspect代码,横切关注点变得容易处理。开发者可以在编译时更改、插入或除去系统的Aspect,甚至重用系统的Aspect.
      更重要的是,AOP可能对软件开发的过程造成根本性的影响。我们可以想象这样一种情况:OOP只用于表示对象之间的泛化一特化(generalization-specialization)关系(通过继承来表现),而对象之间的校向关联则完全用AOP来表现。这样,很多给对象之间横向关联增加灵活性的设计模式(例如Decorator、Role Object等)将不再必要.
      一种编程思想是否真正优秀,只有从实现语言上才能看到。施乐公司帕洛阿尔托研究中心(Xerox PARC)开发了第一个AOP的开发环境——AsPectJ ,这个工具提供了一整套的语法,能够清楚地描述横切关注点,并将其织入到Java源代码中。织入后的代码仍是标准Java代码,因此AspectJ不会影响Java的移植能力。此外,AspectJ提供了一个独立的IDE,并且能够嵌入到Jbuilder、Forte等Java开发环境之中,无缝地提供AOP的能力。关于AspectJ,读者可以在http://www.aspectj.org找到更多的信息。
      但是,现在的AOP还处于相当不完善的阶段:它只能应用于很少的几种语言环境下,并且必须掌握源代码才能进行织入.但以RUP之父Ivar Jacobson为代表的科学家们仍对AOP推崇备至:他认为AOP将最终改变整个软件开发的方式,并且更完美地实现“用例驱动”的开发思想.

利用AOP分离软件关注点

      一个关注点(concern)就是一个特定的目的,一块我们感兴趣的区域。从技术的角度来说,一个典型的软件系统包含一些核心的关注点和系统级的关注点。举个例子来说,一个信用卡处理系统的核心关注点是借贷/存入处理,而系统级的关注点则是日志、事务完整性、授权、安全及性能问题等,许多关注点——我们叫它横切关注点(crosscutting concerns)——会在多个模块中出现,使用现有的编程方法,横切关注点会横越多个模块,结果是使系统难以设计、理解、实现和演进。
AOP能够比上述方法更好地分离系统关注点,从而提供模块化的横切关注点。
      在这篇文章里,我首先会解释横切关注点在软件系统中引起的问题,接着我会介绍AOP是怎样解决横切关注点问题的。 
      软件编程方法的演进在计算机科学的早期阶段,开发人员使用简单的机器级代码来编程。不幸的是,程序员得花费更多时间来考虑一种特定机器的指令集而不是手中需要解决的问题本身。慢慢地,我们转而使用允许对底层机器做某种抽象的高级语言。然后是结构化语言,我们可以把问题分解成一些必要的过程来完成任务。但是,随着复杂程度的增加,我们又需要更适合的技术。面向对象的编程方式(OOP)使我们可以把系统看作是一批相互合作的对象。类允许我们把实现细节隐藏在接口下。多态性为相关概念提供公共的行为和接口,并允许特定的组件在无需访问基础实现的前提下改变特定行为。
编程方法和语言决定了我们和计算机交流的方式。每一种新的方法学都提出一种新的分解问题的方法:机器码、伪代码、过程和类等。每种新的方法学都使得从系统需求到编程概念的映射更加自然。编程方法学的发展让我们可以建立更加复杂的系统,这名话反过来说也地,我们能够建立更加复杂的系统是加为这些技术允许我们处理这种复杂度。
      现在,大多数软件项目都选择OOP的编程方式。确实,OOP已经表明了它处理一般行为的能力,但是,我们将会看到(或许你已经感觉到了):OOP不能很好地处理横越多个——经常是不相关的——模块的行为。相比之下,AOP填补了这个空白,它很可能会是编程方法学发展的一个里程碑。
把系统看作一批关注点我们可以把一个复杂的系统看作是由多个关注点来组合实现的。一个典型的系统可能会包括几个方面的关注点,如业务逻辑、性能,数据存储、日志和调度信息、授权、安全、线程、错误检查等,还有开发过程中的关注点,如易懂、易维护、易追查、易扩展等,图1演示了由不同模块实现的一批关注点组成一个系统。


图2把需求比作一束穿过三棱镜的光。我们让需求之光通过鉴别关注点的三棱镜,就会区别出每个关注点。


      开发人员建立一个系统以满足多个需求,我们可以大致地把这些需求分类为核心模块级需求和系统组需求。很多系统级需求一般来说是相互独立的,但它们一般都会横切许多核心模块。举个例子来说,一个典型的企业应用包含许多横切关注点,如验证、日志、资源地、系统管理、性能及存储管理等,每一个关注点都牵涉到几个子系统,如存储管理关注点会影响到所有的有状态业务对象。
让我们来看一个简单的例子,考虑一个封装了业务逻辑的类的实现框架:

public class SomeBusinessClass  extends otherBusinessClass{
    
//核心数据成员
    
//其它数据成员:日志流,保证数据完整性的标志位等
    
//重载基类的方法
    public void performSomeOperation (OperationInformation info) {
        
//安全性验证
        
//检查传入数据是否满足协议
        
//锁定对象以食品店当其他线程访问时的数据完整性
        
//检查缓存中是否为最新信息
        
//记录操作开始执行时间
        
//执行核心操作
        
//记录操作完成时间
        
//给对象解锁

    }
    
//一些类似操作
    public void save(PersitanceStorage ps){

    }
}

 

       在上面的代码中,我们注意到三个问题:首先,其它数据成员不是这个类的核心关注点;第二performSomeOperation()的实现做了许多核心操作之外的事,它要处理日志、验证、线程安全、协议验证和缓存管理等一些外围操作,而且这些外围操作同样也会应用于其他类;第三,save()和load()执行的持久化操作是否构成这个类的核心是不清楚的.
      横切关注点的问题虽然横切关注点会跨越多个模块,但当前的技术倾向于使用一维的方法学来处理这种需求,把对应需求的实现强行限制在一维的空间里.这个一维空间就是核心模块级实现.其他需求的实现被嵌入在这个占统治地位的空间.换句话说,需求空间是一个n维空间,而实现空间是一维空间,这种不匹配导致了糟糕的需求到实现的映射。
      表现用当前方法学实现横切关注点是不好的.它会带来一些问题,我们可以大致把这些问题分为两类。
代码混乱:软件系统中的模块可能要同时兼顾几个方面的需要.举例来说,开发者经常要同时考虑业务逻辑、性能、同步,日志和安全等问题,兼顾各方面的需要导致相应 关注点的实现元素同时出现,引起代码混乱.
      代码分散:由于横切关注点本来就涉及到多个模块.相关实现也就得遍布在这些模块里.如在一个使用了数据库的系统里,性能问题就会影响所有访问数据库的模块。这导致代码分散在各处.
结果混乱和分散的代码会从多个方面影响系统的设计和开发:
可读性差:同时实现几个关注点模糊了不同关注点的实现,使得关注点与其实现之间的对应关系不明显。
低产出:同时实现几个关注点把开发人员的注意移到外围关注点,导致生产效率降低.
低代码重用率: 由于一个模块实现多个关注点,因此其他需要类似功能的系统不能马上使用该模块.进一步降低了生产效率。
代码质量差:混乱的代码掩盖了代码中隐藏的问题。而且,由于同时要处理多个关注点.应该特别注意的关注点得不到应有的关注.
难以扩展:狭窄的视角和有限的资源总是产生仅注意当前关注点的设计.新的需求导致从新实现.由于实现不是模块化的,就是说实现牵涉到多个模块,为了新需求修改子系统可能会带来数据的不一致,而且还需相当规模同测试来保证这些修改不会带来bug。
当前解决方法由于多数系统中都包含横切关注点、自然的已经形成了一些技术来模块化横切关注点的实现,这些技术包括:混入类、设计模式和面向特定问题域的解决方式。
使用混入类,你可以推迟关注点的最终实现.基本类包含一个混入类的实例,允许系统的其他部分设置这个实例。举个例子来说,实现业务逻辑的类包含一个混入的logger,系统的其他部分可以设置这个logger已得到合适的日志类型,比如logger可能被设置为使用文件系统或是消息中间件。在这种方式下,虽然日志的具体实现被推迟,基本类还是必须在所有写日志的点调用日志操作和控制日志信息的代码。
行为型设计模式,如Visitor和Template Method模式,也允许你推迟具体实现。但是也就像混入类一样,操作的控制——调用visitor或template Method的逻辑——仍然留给了基本类。
面向特定问题域的解决方式,如框架和应用服务器,允许开发者用更模块化的方式处理某些横切关注点。比如E J B(Enterprise JavaBean)架构,可以处理安全、系统管理、性能和容器管理的持久化(container-managed persistence)等横切关注点。B e a n与数据库的映射,但是大多数情况下,开发者还是要了解存储结构。这种方式下,你用基于XML的映射关系描述器来实现于数据持久化相关的横切关注点。
面向特定问题域的解决方式提供了解决特定问题的专门机制,它的缺点是对于每一种这样的解决方式开发人员都必须重新学习,另外,由于这种方式是特定问题域相关的,属于特定问题域之外的横切关注点需要特殊的对待。
设计师的两难局面。好的系统设计师不仅会考虑当前需求,还会考虑到可能会有的需求以避免到处打补丁。这样就存在一个问题预知将来是很困难的,如果你漏过了将来可能会有的横切关注点的需求,你将会需要修改或甚至是重新实现系统的许多部分;从另一个角度来说,太过于关注不一定需要的需求会导致过分设计的、难以理解的、臃肿的系统。所以系统设计师处在这么一个两难局面中:怎么设计算不了过分设计?应该宁可设计不足还是宁可过分设计?
举个例子来说,设计师是否应该在系统中包含现在并不需要的日志机制?如果是的话,哪里是应该写日志的点?日志应该记录那些信息相似的例子还有关于性能的优化问题,我们很少能预知瓶颈的所在。常用的方法是建立系统,profile它,然后翻新系统以提高性能,这种方式可能会依照profiling而修改系统的很多部分。此外,随着时间的流逝,由于使用方式的变化,可能还会产生新的瓶颈。类库设计师的任务更困难,因为他很难设想出所有对类库的使用方式。
总而言之,设计师很难顾及到系统可能需要处理的所有关注点。即使是在已经知道了需求的前提下,某些建立系统时需要的细节 也可能不能全部得到,整体设计就面临着设计不足/过分设计的两难局面。
AOP基础
到目前为止的讨论说明模块化横切关注点是有好处的。研究人员已经尝试了多种方法来实现这个任务,这些方法有一个共同的主题:分离关注点。A O P是这些方法中的一种,它的目的是清晰的分离关注点来解决以上提到的问题。
AOP, 从其本质上讲,使你可以用一种松散耦合的方式来实现独立的关注点,然后 组合这些实现来建立最终系统、用它所建立的系统是使用松散偶合的,模块化实现的横切关注点来搭建的、与之对照 用OOP建立的系统则是用松散耦合的模块化实现的一般关注点来实现的。在AOP中,这些模块化单元叫“方面(aspect)”,而在OOP中,这些一般关注点的实现单元叫做类。
AOP 包括三个清晰的开发步骤:
方面分解:分解需求撮出横切关注点。在这一步里,你把核心模块级关注点和系统级的横切关注点分离开来、就前面所提到的信用卡例子来说,你可以分解出三个关注点:核心的信用卡处理、日志和验证。
关注点实现:各自独立的实现这些关注点,还用上面信用卡的例子,你要实现信用卡处理单元、日志单元和验证单元。
方面的重新组合:在这一步里,方面集成器通过创建一个模块单元—一方面来指定重组的规则,重组过程—一也叫织入(weaving)或结合(integrating)——则使用这些信息来构建最终系统、还拿信用卡的那个例子来说你可以指定(用某种AOP的实现所提供的语言)每个操作的开始和结束需要记录,并且每个操作在涉及到业务逻辑之前必须通过验证。


AOP与OOP最重要的不同在于它处理横切关注点的方式.在AOP中 每个关注点的实现都不知道其它关注点是否会“关注”它,如信用卡处理模块并不知道其它的关注点实现正在为它做日志和验证操作。它展示了一个从OOP转化来的强大的开发范型。
注意:一个AOP实现可以借助其它编程范型作为它的基础,从而原封不动的保留其基础范型的优点。例如,AOP可以选择OOP作为它的基础范型,从而把OOP善于处理一股关注点的好处直接带过来。用这样一种实现,独立的一般关注点可以使用OOP技术、这就像过程型语言是许多OOP语言的基础一样。
AOP语言剖析
就像其他编程范型的实现一样,AOP的实现由两部分组成:语言规范和实现。语言规范描述了语言的基础单元和语法;语言实现则按照语言规范来验证代码的正确性,并把代码转成目标机器可执行的形式。这一节,我来解释一下AOP组成部分。 
AOP语言规范
从抽象的角度看来 一种AOP语言要说明下面两个方面:
关注点的实现:把每个需求映射为代码,然后,编译器把它翻译成可执行代码。由于关注点的实现以指定过程的形式出现,你可以使用传统语言如C、C++、JAVA等。
织入规则规范:怎样把独立实现的关注点组合起来形成最终系统呢?为了这个目的 需要建立一种语言来指定组合不同的实现单元,以形成最终系统的规则。这种指定织入规则的语言可以是实现语言的扩展,也可以是一种完全不同的语言。 
AOP语言的实现
AOP的编译器执行两步操作:
l 组装关注点
2 组装结果转成可执行代码。
AOP实现可以用多种方式实现织入, 包括源码到源码的转换、它预处理每个方面的源码,产生织入过的源码,然后把织入过的源码交给基础语言的编译器, 产生最终可执行代码。比如 使用这种方式,一个基于Java的AOP实现可以先把不同的方面转化成Java源代码,然后让Java编译器把它转化成字节码.也可以直接在字节码级别执行织入; 毕竟 字节码本身也是一种源码。此外,底层的执行系统—一Java虚拟机—一也可以设计为支持AOP的。基于Java的AOP实现如果使用这种方式的话,虚拟机可以先装入织入规则,然后对后来装入的类都应用这种规则、也就是说,它可以执行just-in-time的方面织入。 
AOP的好处
AOP可帮助我们解决上面提到的代码混乱和代码分散所带来的问题,它还有一些别的好处:
模块化横切关注点:AOP用最小的耦合处理每个关注点,使得即使是横切关注点也是模块化的。这样的实现产生的系统,其代码的冗余小。模块化的实现还使得系统容易理解和维护。
系统容易扩展:由于方面模块根本不知道横切关注点,所以很容易通过建立新的方面加入新的功能.另外,当你往系统中加入新的模块时,已有的方面自动横切进来,使系统易于扩展。
设计决定的迟绑定:还记得设计师的两难局面吗?使用AOP 设计师可以推迟为将来的需求作决定,因为他可以把这种需求作为独立的方面很容易地实现。
更好的代码重用性:AOP把每个方面实现为独立的模块, 模块之间是松散耦合的.举例来说,你可以用另外一个独立的日志写入器方面来替换当前的,用于把日志写入数据库,以满足不同的日志写入要求。松散藕合的实现通常意味着更好的代码重用性,AOP在使系统实现松散出合这一点上比OOP做得更好。 
AspectJ:一个Java的AOP实现
AspectJ是一个可免费获得的、由施乐公司帕洛阿尔托研究中心(Xerox PARC)开发的、Java的AOP实现。它使用java作为单个关注点的实现语言,并扩展Java以指定织入规则.
另外,AspectJ允许以多种方式用方面和类建立新的方面,你可以引入新的数据成员和方法或是声明一个新的类来继承和实现另外的类或接口。
AspectJ的织入器——AspectJ的编译器——负责把不同的方面组合在一起,由于AspectJ编译器建立的最终系统是Java字节码,因此,它可以运行在任何符合Java标准的虚拟机上。而且,AspectJ还提供了一些工具,例如调试器和Java IDE集成等。
我需要AOP吗?
AOP仅仅是解决设计上的缺点吗?在AOP里,每个关注点的实现的并不知道是否有其它关注点关注它,这是AOP和OOP的主要区别。在AOP里,组合的流向是从横切关注点到主关注点,而OOP则相反。但是,OOP可以和AOP很好地共存。比如,你可以使用一个混入类来做组合,既可以用AOP实现,也可以用OOP实现,这取决你对AOP的接受程度,在这两种情况下,实现横切关注点的混入类实现都无需知道它自己是被用在类中还是被用在方面中。举个例子来说,你可以把一个日志写入器接口用作某些类的混入类或是用作一个日志方面,因而,从OOP到AOP 是渐进的。

了解AOP
在这篇文章里,你看到了横切关系带来的问题,这些问题当前解决方法以及这些方法的缺点。你也看到了AOP 是怎样克服这些缺点的,AOP的编程方式试图模快化横切关注点的实现,提供了一个更好更快的软件开发方式。
如果你的系统中涉及到多个横切关注点,你可以考虑进一步了解AOP,了解它的实现和它的好处。AOP很可能会是编程方式的一个里程碑。 

 

 

posted @ 2010-12-31 11:12 ztotem 阅读(46) 评论(0) 编辑
代码

--delete from #tba
--
delete from #tbb

create  table #tba ( sid int ,n varchar(20) )

create table #tbb (sid int ,c varchar(20) ,s float )

insert #tba
select 1,'z1' union all
select 2,'z2' union all
select 3,'z3' union all
select 4,'z4' union all
select 5,'z5' 

insert #tbb
select 1'shuxue',50 union all
select 1'english'60 union all
select 1'yuwen'90 union all

select 2'shuxue',70 union all
select 2'english'40 union all
select 2'yuwen'35 union all

select 3'shuxue',57 union all
select 3'english'64 union all
select 3'yuwen'93 union all

select 8'shuxue',55 union all
select 8'english'84 union all
select 8'yuwen'90 union all

select 4'english'65 union all
select 4'yuwen'33 
 

--select * from @tba
--
select * from #tbb

--固定字段方式行转列
/*

select sid,sum(case when c = 'shuxue' then s else 0 end) as 'shuxue',
sum(case when c = 'english' then s else 0 end) as 'english',
sum(case when c = 'yuwen' then s else 0 end) as 'yuwen'
from @tbb 
group by sid
*/

--动态方式行转列
declare @sql varchar(8000)
set @sql = 'select sid,'
select @sql = @sql + 'sum(case when c = '''+c+''' then s else null end) as '''+c+''','
from (select distinct c from #tbb) as B 
set @sql = left(@sql,len(@sql)-1+ ' from #tbb group by sid'

--PRINT @SQL 
exec(@sql)
/*
*/

--回顾下左外连接,右外连接,全外连接;交叉连接(笛卡尔乘积),内连接
--
select * from @tba a left join @tbb b on a.sid = b.sid 

--select * from @tba a right join @tbb b on a.sid = b.sid

--select * from @tba a full join @tbb b on a.sid = b.sid

--select * from @tba cross join @tbb

--select * from @tba a inner join @tbb b on a.sid = b.sid
--
select * from @tba a join @tbb b on a.sid = b.sid
--
select * from @tba a, @tbb b where a.sid = b.sid

--having关键字
/*

select a.sid,count(a.sid) cid from @tba a left join @tbb b on a.sid = b.sid
group by a.sid having count(a.sid) > 2

--select count(sid) as cid from @tbb group by sid  having count(sid)>2 

*/

 

posted @ 2010-12-14 17:32 ztotem 阅读(62) 评论(0) 编辑

    abstract、virtual、override 和 new 是在类的继承关系中常用的四个修饰方法的关键字,在此略作总结。

1. 常用的中文名:abstract 抽象方法,virtual 虚方法,override 覆盖基类方法,new 隐藏基类方法,override 和 new 有时都叫重写基类方法。

2. 适用场合:abstract 和 virtual 用在基类(父类)中;override 和 new 用在派生类(子类)中。

3. 具体概念:

    abstract 抽象方法,是空方法,没有方法体,派生类必须以 override 实现此方法。

    virtual 虚方法,若希望或预料到基类的这个方法在将来的派生类中会被重写(override 或 new),则此方法必须被声明为 virtual。

    override 重写继承自基类的 virtural 方法,可以理解为拆掉老房子,在原址上建新房子,老房子再也找不到了(基类方法永远调用不到了)。

    new 隐藏继承自基类的 virtual 方法,老房子还留着,在旁边盖个新房,想住新房住新房(作为派生类对象调用),想住老房住老房(作为基类对象调用)。

    当派生类中出现与基类同名的方法,而此方法前面未加 override 或 new 修饰符时,编译器会报警告,但不报错,真正执行时等同于加了 new。

4. abstract 和 virtual 的区别:abstract 方法还没实现,连累着基类也不能被实例化,除了作为一种规则或符号外没啥用;virtual 则比较好,派生类想重写就重写,不想重写就吃老子的。而且继承再好也是少用为妙,继承层次越少越好,派生类新扩展的功能越少越好,virtual 深合此意。

5. override 和 new 的区别:当派生类对象作为基类类型使用时,override 的执行派生类方法,new 的执行基类方法。如果作为派生类类型调用,则都是执行 override 或 new 之后的。


演示 override 和 new 区别的例子:


// Define the base class
class Car
{
   
public virtual void DescribeCar()
   {
       System.Console.WriteLine(
"Four wheels and an engine.");
   }
}

// Define the derived classes
class ConvertibleCar : Car
{
   
public new virtual void DescribeCar()
   {
       
base.DescribeCar();
       System.Console.WriteLine(
"A roof that opens up.");
   }
}
class Minivan : Car
{
   
public override void DescribeCar()
   {
       
base.DescribeCar();
       System.Console.WriteLine(
"Carries seven people.");
   }
}
public static void TestCars1()
{
   Car car1 
= new Car();
   car1.DescribeCar();
   System.Console.WriteLine(
"----------");

   ConvertibleCar car2 
= new ConvertibleCar();
   car2.DescribeCar();
   System.Console.WriteLine(
"----------");

   Minivan car3 
= new Minivan();
   car3.DescribeCar();

   System.Console.WriteLine("----------");

}

 

输出类似如下所示:

Four wheels and an engine.

----------

Four wheels and an engine.

A roof that opens up.

----------

Four wheels and an engine.

Carries seven people.

----------

但是,如果我们声明一个从 Car 基类派生的对象的数组。此数组能够存储 Car、ConvertibleCar 和 Minivan 对象,如下所示:


public static void TestCars2()
{
    Car[] cars 
= new Car[3];
    cars[
0= new Car();
    cars[
1= new ConvertibleCar();

    cars[2] = new Minivan();

}

 

然后用一个 foreach 循环来访问该数组中包含的每个 Car 对象,并调用 DescribeCar 方法,如下所示:


foreach (Car vehicle in cars)
{
  System.Console.WriteLine(
"Car object: " + vehicle.GetType());
  vehicle.DescribeCar();

  System.Console.WriteLine("----------");

}

 

此循环的输出如下所示:

Car object: YourApplication.Car

Four wheels and an engine.

----------

Car object: YourApplication.ConvertibleCar

Four wheels and an engine.

----------

Car object: YourApplication.Minivan

Four wheels and an engine.

Carries seven people.

----------

注意,ConvertibleCar 的说明可能与您的预期不同。由于使用了 new 关键字来定义此方法,所调用的不是派生类方法,而是基类方法。Minivan 对象正确地调用重写方法,并产生预期的结果。


 来源:http://www.cnblogs.com/ibmfm/archive/2008/12/31/1366153.html

posted @ 2010-10-26 15:07 ztotem 阅读(27) 评论(0) 编辑
posted @ 2009-12-17 13:53 ztotem 阅读(40) 评论(0) 编辑

我逐渐的明白,我最害怕失去的是独立的思考能力。收藏此文以鞭策自己不断进行思想的碎片整理。

==================================================

在作弊中慢慢成长

作者: 王怡 

也许作弊,是我们对于校园内腐败的一种称呼。一个天真孩童,穿过长达十余年的教育隧道,通往社会。像一个少林寺和尚在黑暗中打过十八铜人阵而还俗。哪里能够不留下一生当中的伤痕累累。在风雨之夜历经骨痛,心想,那是我长大成人的代价。

我的父亲是一位退休的中学语文教师。也是我高中时的任课老师。家、国不曾相通,师、父确是并举的。喝过酒到六七分,他的话题偏偏就要落在从事终生的教育上。他对中学教育的总体评价是不及格,批语是:“毁人无数”。以下是他的原话:好成绩(的人)往往太听话,受害最深,丧失灵性。那些调皮的、捣蛋的,从小学到中学,紧箍咒箍上十来年,差不多都给毁了,一个个唯唯诺诺、充满奴性。只有少数人意志坚强,有反叛精神,当面一套背后一套,加上被老师忽略,反而有空间生长。结果捱了过去,还能成器。

最后还要补上一句:你大表哥就是活生生被毁掉的例子。

父亲的话也许偏激,但其实这样的例子在我周围,实在是罄竹难书。我小学最好的一个朋友,五年级时写一篇作文居然就写了十一篇作业纸,升中学考试全县第一、考了299分。聪颖无比,前途无量,不过到紫阳元年初中二年级时,就在家长和学校的双重压力下精神失常,而中途缀学。他的悲剧在于,在此之前,因为他的功课太好,因为他一直是教育体制中的既得利益者,所以他还没有来得及怀疑,还没有来得及做第一次弊,就被毁去了。

因为作弊,是一种自我保护。是为了避免更大的伤害而自愿接受的代价。是少数人躲过枪林弹雨、借此顺利通过十余年暗无天日的教育隧道的途径。而且在大多数时候,如果你已经不想把自己完全出卖给教育者,那就甚至是唯一的途径。

在小学四五年级,我们几乎每学期都要参加县上的各种大会典礼。因为领导们每年都要开许多重要的会议,我们定制盛装、反复彩排,背诵赞歌,然后在那些个重要的节日里走上街头游行,或者向大会献词。我那个最好的朋友雷光辉,就是每一回都走在队列最前面的那个孩子,或者站在舞台中央向领导们高声朗诵的少先队大队长。由于单纯和虚荣心,雷光辉每一回情绪饱满地朗诵着那些每一句后面都有一个“啊”字的颂词时,我埋没在后面的行列里,已经开始学会了作弊。当我发现站在队列里的好处是可以只张嘴不开腔,我就不再羡慕雷光辉了。我从一个三好学生开始成为了一个校园中的作弊者。

其实更早的时候,当我还是一个完全无民事行为能力人(十周岁以下),在少先队的宣誓仪式上跟着大队辅导员龙老师一字一句地念:“时刻准备着,为共产主义事业而奋斗”。作弊就已经拉开了序幕。因为即使在能够理解这句话的年龄,从加入少年先锋队开始,一直到今年我年满二十八岁正式退出共产主义青年团,没有一天曾经把这句话当过真。我所认识的每一个同学朋友,也没有任何一个人把这句话当过真的。但是真正的作弊者不是我,而是龙老师。因为我是无辜的,我在无法理解这句话的时候被裤衩一般的红领巾诱惑了。刑法上有规定,凡是和十四岁以下的未成年人发生性关系,无论未成年人是否同意,都属于强奸。这个道理我觉得完全可以适用于上述场合。当大队辅导员龙老师带领不明真相的我们进行一生中的第一次庄严宣誓时,他就是一个不折不扣的作弊者。而且进而,他也是一个粗暴的强奸者。是他拿走了我精神上的童贞。

在那之后,你的漫长的一生,已经不再有真正的誓言。

相比之下,考试时的作弊反而是次要的。由于我的成绩也挺好,高中以前尚未在考试时作过弊。后来成绩下滑,就开始自甘堕落。然而对以后的人生更显重要的作弊,始终是在考场以外。初中二年级,也就是雷光辉退学之后,由于蜀中无大将,廖化作先锋。我就被某些老师盯上了。一个唤做姚远富的语文老师,从来没有教过我们。但他的一场规模宏大的公开课选在了我们班上。上课之前一周,几个成绩好的良民包括我被拣选出来。姚老师问了我一个问题,要我作答。答了之后他不满意。经过几番近乎全裸的提示,姚老师最后将标准的答案说了出来。姚老师深谋远虑,对我说:你可以就按照你自己开始的理解回答,经过老师提示和同学讨论之后,你再按照我刚才说的来答。

果然效果极佳。这一场作弊,同时满足了姚远富和王怡的虚荣心。我既已失身,从此被教育者拖下了水。在高中成绩下降之前,继续伙同一些老师作案数次。这一段经历后来想起,觉得屈辱无比。感觉就像是一场成年人对于儿童的轮流鸡奸。并且发现,成绩不要太好,其实也是一种自我保护。

不敢反抗教育者,不敢在老师面前说谎话,是一个学生最大的悲哀。奴性的养成,在一个以培养奴隶和良民为目的的教育体制下,在一个意识形态全面掌控的局面中,作弊,几乎是唯一的拨乱反正,是在可以做爱之前一种最重要的能力。尽管由每一个有着作弊前科的学生所构成的社会,是一个充斥着作弊者和腐败者的社会。但我宁愿把这样一个社会看作是对于威权和领袖的藐视和销解。一个作弊者的社会,比起一个奴隶的社会已经好上许多倍。

不能说真话的时候,至少我们可以选择不说假话。然而在教育者的命令下,往往连不说话的自由也没有。被迫说假话,使说话者在教育者面前丧失了最后的一点尊严。紫阳二年我读初中三年级,整整一年,没有写过一篇作文。当时的语文老师姓郭,我们叫她郭老太婆。她每周布置一篇作文,那些题目已经让我开始倒胃口了。我不想写,就不写。接连五次没有交作业,第六次的题目叫做《记劳动节的一件好事》。我交了一篇《我为什么不写作文》上去,批评了郭老太婆的命题。我这么做是有本钱的,因为父亲在本校教高中,是语文权威,本校的教师子女在学校里是一大派,有点像社会上的高干子女。由于有人际关系的牵扯,一般的老师都轻易不会得罪其他老师的子女。加上我自己语文成绩好,初一时的作文就在绵阳市得过中学生作文比赛中初中组的第一名。郭老太婆又是快退休的。所以她从那以后就对我不再理会,当我不存在。上课也不提我的问,更不去我父亲那里告状。但是到了初中毕业会试,我终于尝到苦果。由于一直不说话,说话的能力也就退化了,我自恃作文写得好,一年不写不练,已经失去了方向感。中考的作文题目记不得了,但和郭老太婆的命题差球不多。我最后决定在这样一个重要关头放弃自我,不敢冒险。按照父亲教导的灵丹妙药,所谓“总-分-总”的万能模式,编排了一个蹩脚故事。结果作文得分极低,一塌糊涂。到现在,编故事写记叙文都是我文字上最大的弱项。

到了1989年。这一年的作弊是铺天盖地的。上半年我在历史考试中第一次作弊。历史是我喜欢的科目,但历史课的问答题和政治课一样最卑鄙无耻。我不愿意将那些句子化时间背下,我宁愿选择作弊,如果是照本宣科的抄,感觉上要快乐得多。不经过大脑,也是一种自我保护的手段。有些话说着说着,就要毒发身亡,就要搞不拎清是自己的想法还是教育者的想法。那些将政治课本背的滚瓜烂熟的良民们,即使他们内心是如何的排斥和瞧不起那些东西,然而多年之后,却不得不发现,意识形态已经深入灵魂,播下了精子,构成了精神背景当中一生也无法抹去的桌面主题。许多年之后一次同学聚会上,一位朋友告诉我,现在才感觉到中学的政治课对自己的影响有多么大。其实这种影响看一看由精英们组成的所谓大专辩论赛就知道了,我们的大学生们除了口齿伶俐以外一无是处。能够拿出来支持论辩的理论和精神背景,永远逃不脱中学政治课提及的概念。对比台湾的一些大学生选手,精神与思想视野,简直无法相提并论。

最大的作弊还是来自教育者。上半年的腥风血雨一旦散去,所有的教育者开始合谋为一个时代作伪证。一个十七岁少年的判断力,几乎全部丧失。一遍遍的在政治课、语文课,在时事政治的考试中背诵领袖的讲话,构成了我们这一代人几乎全部的精神成长。除非,你是一个作弊者。

在一个伯父的家中,我有幸和父亲一起听到了当时某省委书记杨某的讲话录音。录音是关于传达中央对前总书记的处理和揭批。杨某人穷凶极恶,口不择言,对赵某人的攻击令人齿冷。杨某者,一乡干部耳。赵任某省委书记时,杨某时任某县委书记。一次得知赵书记要过境,不做停留。此人在必经之路拦路作弊,挽起裤脚,在路边的稻田里和老乡亲切交谈。一举得到赵的看重,从此步步高升。

这段典故在省内有多种版本流传。1989年四五月份,风声不对、火烧眉毛。杨某人作为全省最高官员,居然借故视察水灾,离开省城去边远县分避此风头。直到大势已定方才回来。作为赵一系的省级官员,杨某唯恐表态不及,摆出一副痛打落水狗的大阵仗,不惜污言秽语揭人老底。雨果在《九三年》中称,“绝对正确的革命之上,还有一个绝对正确的人道主义”。其实革命是否一定就绝对正确姑且不论,在此之上的其他价值,更远远并不只是一个人道主义而已。信义、坦诚、荣誉和人品,都是不可假借政治正确的名义去辜负的。等到年底大换血,杨某功成身退,卸任赴全国政协副主席的位置养老。我当年专门看了报纸上杨的简介,上面写着:文化程度,相当于高中。

在我十七岁的时候,全省一亿人的最高行政官员,以他卑劣的作弊行径,让我对教育者高声诵读的大部分价值开始心如死灰。

准备高考,对于在教育者面前作弊已经习以为常的我而言,是一个凤凰涅槃的过程。接受高考的洗礼,就是接受意识形态的洗礼。一个文科学生一遍遍背进大脑里去的东西,至少有三分之一是大粪。如果你不能在政治、历史和语文课上考到平均八十分,基本上是不可能读大学的。而如果你真的在这三课上考到了平均八十分,你的未来还有什么真正的希望?你还有多少的机会可以清空回收站,可以对自己进行碎片整理。绝大多数的人终其一生,也再不能将那些精神深处的大粪打整干净了。从十二年的中小学教育中挣脱出来,我们几乎没有一个人,没有一个人是清白的。

所以大学对于我和许多同龄人的重要性,首先意味着一场大扫除的可能。我在大一读完了范文澜的《中国通史》,和记不清谁写的一部《中国文化史》,基本上剔除了中学历史课的糟粕。接下来看剑桥中国史,整个人这才完全不一样了。大二读现代诗歌比较多,从戴望舒到台湾诗歌,再和八十年代的当代诗歌迎面相遇。把高中语文课本忘得干干净净。卢梭、尼采、萨特、韦伯和弗洛伊德,这些在中学闻所未闻的名字将我簇拥。后来在大学最后一年接触到自由主义,感到所有的代价终于开始赢得了回报。相比之下那些教科书又算得什么。所以大学里的作弊实在是家常便饭。四年间,绝大多数的课程,我听了一两回后,就不再去。我的大学是旷课旷出来的。

理科生不同。一个文科生又不作弊、又不旷课,即便考研,读到博士,也是毫无前途。除非他是因为遇上了一个真正的好老师,方才这般老实。不过这对于绝大多数学生的漫长生涯来说,是一种罕见的奢侈。我就没有这样的福气。

所以我那些一生中比童年更加美好的日子。每一天的方式都是类似的。上午九、十点钟起床,吃完饭,生活便从中午太阳最高的时候开始。或者是去图书馆泡着,或者是和一个写诗的朋友石东生带一本书、一副棋,骑车去锦江边的滨江茶园喝茶。到了六七点钟回来,晚上从不上自习,因为有节目。节目就是看镭射电影。感谢那些伟大的盗版者,让我在四年大学期间看了一千一百余部电影。其中七成是美国片,三成香港片,剩下的占一成。那些在小县城里看不到的电影,每一部都会让一个中学政治老师含恨而死。

夜里回到寝室,有人就打双扣,没人就点蜡烛看书(最痛恨大学的按时熄灯制度)。如果是夏天,需要反复到水房冲凉,就干脆偷跑出去喝啤酒。那样的生活,是一个中学生无法奢望的。无法奢望一个人可以如此的远离教育者的目光。有一次我起床比较早,兴致勃勃地去图书馆。在路上遇上辅导员石静。她问我:怎么没有上课吗?我信口雌黄地说:今天老师没来。从此以后我在校园里遇见她大约又有四五次,每一回我装着没看见,她也装着没看见我。在我心中,那是四川大学所能够给予我的最美好的几个瞬间。

我的许多的学分是作弊挣来的。大三大四两年的体育课测验表,全都是自己填上去的。除了大一傻乎乎的,以后也再没有出过早操。所以虽然读过大学,我始终认为自己属于自学成才。在这一切将要划上句号时,大四几乎一年时间的实习期,使作弊下的成长达到了高潮。

我在一家公有制的法院当书记员。强调公有制是因为所有法官都把他们的院长叫做“老板”。开始不习惯,但作弊作惯了的人适应性强。那一年是我们寝室最为奢侈的日子。整整一年每个人抽的烟都是红塔山。每一天都有人有饭局,所以双扣打得少了。有一次和法官去金堂县办案,回来时我带回了一条塔山,一个二百元的红包,还有一大筐金堂最著名的橘子。个个都有碗口大,空前绝后,我再也没有见过那么大的橘子了。

我的朋友马锦涛在毕业三年之后告诉我,实习期间他收过当事人最多一次八百元现金。我比他清廉多了,因为实习三个月之后我的老毛病一犯,就扔下手里的活路,再也没有去上过一天班。也就是那次去金堂,一个姓郑的法官在我面前丢人现眼,又吃又拿,晚上耍混要小姐陪。同去的我和一个女法官站在旁边,恨不能当场钻下地去。那是我事隔多年之后,再次又有了一种被鸡奸的感觉。回来不久,一个当事人说庭长收了他的钱,在办公室闹事,打翻了女庭长的水杯。这个乡下人被司法拘留十五日。两天后我和别人一起去拘留所问他要不要申请复议,他已经被吓坏了。他的表情让我想起了我童年的的好朋友雷光辉。回到法院,庭长要我写一份当天(闹事时我在场)的证明材料。从第二天起,我就恢复了睡懒觉的习惯,不再去上班。

后来女庭长让我的同学带话,说我不去上班,到时候不会给我写实习鉴定。这种话吓不倒作弊者,我心中早有打算,根本不去理会她。

实习结束前,我自己写好了鉴定。然后去那家法院,直接上五楼办公室,把该盖的章都给盖了。以前所有文件,包括判决书都是我拿上去盖章的,所以人家连问都没有问一声。这个最大的一次作弊,反而作的最稀松。后来看见新闻说,有一家地方法院居然搞出假离婚判决书来。我想有什么稀奇,我一个实习生,当时要是自己打一份,一样也是把人民法院的大红章给盖了。

办完了这件事,我为了一个在重庆读书的朋友能够分配到成都,通过母亲的关系去给一家学校的校长和主管局的人事处长行贿。这次的作弊被那位有着真才实学的朋友看作永远也不愿提及的耻辱。干完之后,我对自己说:还是到学校去教书吧。因为我实在不想再作弊了。

高考时我听进去父亲的话,打死也不填报师范院校。没想到结果最后还是充当了道貌岸然的教育者。五年来,我自知育人不够,但始终记得父亲的话,以不能毁人为宗旨。我现在做的事情,就是在大学校园里,希望帮助每一位杀出重围的中学生进行碎片整理。告诉他们那些曾经被毁掉或者从未在心中生根的价值。并在心中坚持,终其一生,和教育者留下的大粪为敌。

写到这里,我回头听见电视上的新闻,成都的中学生还在举行“生在红旗下”的迎七一作文比赛,评委是老诗人流沙河。我知道自己肩上的担子仍然像太行王屋一样沉重。

但我始终充满信心。从一个作弊者到一个教育者,我通过自己的努力证明了一件事。就是生在大粪中,你依然可以努力开出鲜花。

一朵并不好看,但是学会了思想的花。

即使在某些人眼中,你并不是花,而是一株毒草。

王怡/2001-06-12于包家巷
posted @ 2009-12-08 22:16 ztotem 阅读(31) 评论(0) 编辑
摘要: "真正的发现的航程,并非是在寻找新的土地,而且用新的视界去寻找"--普鲁斯特"智慧日进者方值得尊敬。"-林肯"我从不让我在学校所学的干扰我的教育"-马克吐温如果公立学校尚未摧残你的灵魂,那么学习是一项极佳的活动。它扩大了你的观点。它给予你用来改善生活的新知识,。即使你对世俗的利益不满足,但是学习也可以是一种乐趣的来源。但在忙碌的世界里, 我们总是很难有合适的时间去学习那些并非必需的知识。唯一学到的...阅读全文
posted @ 2009-11-17 14:01 ztotem 阅读(28) 评论(0) 编辑
摘要: 以下几个存储过程以HolidayList表为基础[代码]判断当天是否有行情:[代码]调用方式:[代码]获取当前日期的上一有行情的日期:[代码]调用方式:[代码]阅读全文
posted @ 2009-09-16 22:41 ztotem 阅读(175) 评论(1) 编辑
摘要: C++知识分类:①基础知识(C 语言、标准库、文件、注册表、数据结构) ②高级知识(多线程、串口通讯、网口通讯、动态库、MFC、COM、ATL、ActiveX) ③专业知识(图像处理、多媒体、OpenGL、DirectShow、数据库、网络安全) 第1阶段先花一个月时间学习基本C语言,然后再看林锐博士的高质量编程,最后才去看C++ prime,the c++...阅读全文
posted @ 2009-09-01 21:29 ztotem 阅读(60) 评论(0) 编辑
摘要: 我极少审视自身对于学习的源动力,方法以及习惯的确立和形成过程,习惯随遇而安式的学习。用《编程那些事儿》的作者所说,某部分思维处于未开化的阶段,或者如另一位作者所说是对于环境或熟知的事物,思维进入到舒适区,且不自察觉。说到舒适区,可参阅此篇blog:《成年人的思想还能进步么》。唯手熟: 学习的终极目的是实践,卖油老头的娴熟技艺来自于“此无它,唯手熟耳”的手段。 学习编程的目的...阅读全文
posted @ 2009-08-22 18:35 ztotem 阅读(129) 评论(0) 编辑
摘要: [转载请保留] 作者:善用佳软 出处:http://xbeta.info/090809.htm  本文与软件无关,但与“顶级软件”或“应用之道”是相关的。所谓分别,只是浅层表象;至高境界,万物一理。本文是阅读某篇文章,进而联系到以前的所读,所想。所以,涉及引文和领域较多,有blog、图书、拳击、魔方、太极)。读者未必能一一共鸣,但分享总是有益的。  ...阅读全文
posted @ 2009-08-17 21:31 ztotem 阅读(67) 评论(1) 编辑