410 likes | 651 Views
组件技术 —— 最后一讲. 潘爱民 北京大学计算机科学技术研究所 http://www.icst.pku.edu.cn/CompCourse. 内容. 框架和类库 CORBA overview 复习. framework. 领域工程 单个系统 —— 〉一类系统 针对应用的抽象 组件库 提供定制功能,允许开发人员对于框架主体部分进行修改 不同层次上的 framework 基于二进制代码的 framework, 例如 MMC 基于源代码的 framework, 例如 MFC. 基于二进制的 framework. 接口: 为应用中的组件提供二进制接口
E N D
组件技术——最后一讲 潘爱民 北京大学计算机科学技术研究所 http://www.icst.pku.edu.cn/CompCourse
内容 • 框架和类库 • CORBA overview • 复习
framework • 领域工程 • 单个系统 ——〉一类系统 • 针对应用的抽象 • 组件库 • 提供定制功能,允许开发人员对于框架主体部分进行修改 • 不同层次上的framework • 基于二进制代码的framework,例如MMC • 基于源代码的framework,例如MFC
基于二进制的framework • 接口: • 为应用中的组件提供二进制接口 • 以对象形式封装 • 以功能为单位 • 粒度 • 大而全的接口 • 小型接口,允许动态发现新的接口 • 通信模型 • 用户组件与框架进行通信 • 用户组件之间如何通信? • 通过框架传递信息 • 通过框架建立直通模型
基于源代码的framework • 接口: • 一般为抽象类,用户提供虚函数的实现,并注册到主框架中 • 用户定制的余地比较大 • 通信模型 • 用户组件与框架进行通信 • 用户组件之间容易建立起直通途径
从派生类传播类型到基类的一种模式 • 意图: • 基类有时需要根据子类的类型执行一些功能,而基类又不可能直接得到子类的静态类型 • 这对于generic programming非常重要,因为编译器要靠静态类型来实例化模板(函数或者类) • 解决方案 • 用虚函数不能解决问题 ——runtime多态性 • 在子类中插入一个函数,由该函数调用模板函数或者模板类,或者该函数调用基类中的模板成员函数 • 仅对基于源代码的framework适用
Framework举例 • 为报社提供一套framework IFrameSite SnapInDLL SnapInDLL SnapInDLL ISnapInfo SnapIn对象 SnapIn对象 SnapIn对象 SnapIn仓库 FrameSite FrameSite FrameSite Snap-In管理器 UI管理器 Database管理器 Security管理器
可重用类库的设计(一) • 在所有的系统设计中,可重用类库的设计是难度比较大的,要做到: • 使用:灵活性和易用性 • 功能:广泛性和效率 • 经验非常重要 • 实现同样的功能会有许多不同的道路,如何选择?效果怎么样? • 类库的基础 • 是否使用其他的类库?是否使用特殊的平台和编译环境? • 参考成功的类库 • 起点要高
可重用类库的设计(二) • 接口的设计 • 这是类库的关键,会影响到类库的使用 • 接口的类型:C/C++ • 大而全的接口并不理想 • 接口的语义一定要清晰 • facade模式 • 内存管理 • 保证内存分配和释放的一致性 • 使用要方便 • [out]参数的资源由谁来申请?谁知道size? • 是否使用自定义的内存分配器,例如针对小对象的分配器
可重用类库的设计(三) • 使用各种模式 • 模式是经验,成功的典范 • policy模式允许使用者定制类 • 结构型模式有助于建立起更加合理的结构模型,而不至于层次错综复杂 • 行为型模式有助于各个类之间有更好的协作模型 • 创建型模式可以提供各种合理的创建机制 • 模板类库的特殊性 • 利用模板类型实现compile-time的预处理 • 熟悉编译器的特性 • 控制模板生成代码
可重用类库的设计(四) • 行为前置和延后 • 在基类中提供缺省的实现 • 纯虚函数 —— 强制子类提供实现 • 利用functor或者函数指针 • 要求(必须)子类调用父类的实现 • 用宏来封装代码 • 代码风格 • 类库的优化 • 优化需要用到内部知识,是否暴露这些知识 • 允许使用者用policy进行配置,用不同的实现配置类 • 类似于policy的思想,在细节点上用开关进行控制
可重用类库的设计(五) • 类库的调试 • 类库内部调试,使用assert支持 • 类库的测试 • 比应用系统的测试更加严格 • 类库的发行 • 是否提供源代码? • 文档 • 编译设置
可重用类库的设计(六) • 举例:MFC/ATL • MFC • 同时也具有源代码框架的结构 • 传统意义上的C++类库,对Win32进行了封装 • 以便于使用为主要目标,优化较少 • 用到了许多patterns,吻合Windows应用模型 • 涉及到许多类库设计技术 • 与Wizard结合产生基本代码 • ATL • 用到了generic programming中许多新的技术 • 模板技术 • 优化比较突出
CORBA Overview • ORB(Object Request Broker ) • Interface Definition Language (IDL) • CORBA Communications Model: IIOP • CORBA Object Model: IOR • CORBA Clients and Servers • client stubs and server skeletons • CORBAservices and CORBAfacilities
CORBA Specification overview • OMG IDL • Interface: • ORB Interface、DII/DSI、Interface Repository • POA • Interoperability • GIOP、IIOP、IOR • Mapping • COM、Automation • C mapping、C++ mapping、SmallTalk • Service Specification(单独的文档) • naming service、event service、transaction service、security service、trade service、……
OMG IDL • 类C风格的语言 • 定义接口: interface • 基本数据类型 • void、boolean、char、wchar、octet、 (unsigned) short、(unsigned) long、(unsigned ) long long、float、double、long double、string、any • 常数、常量表达式 • 构造数据类型 • typedef、enum、struct、union、数组、sequence
OMG IDL(续) • Interface,例如: interface Account { void deposit( in unsigned long amount ); void withdraw( in unsigned long amount ); long balance(); }; • 接口方法中参数的方向属性 • 异常:用户自定义异常和系统异常 • oneway操作 • module、include • 允许多重继承,与实现(implementation)无关
C++ mapping • 基本数据类型与C++的对应关系 • 特殊标识符的处理 • module ——〉namespace • IDL类型——〉CORBA::中的数据类型 • 字符串处理不用new、delete,而用专门的函数 • 枚举类型 • 复合类型 • 除了类型本身外,另生成一个_var类型(类似auto_ptr) • 接口类型 • _ptr类型、_var类型
客户端C++ mapping • 客户通过stub调用对象的方法 • 客户如何得到对象引用 • 客户如何调用对象方法
客户端C++ mapping • 客户通过ORB接口获得初始的对象引用 • 首先初始化ORB并获得ORB接口 • 然后利用字符串形式的引用获得内部的对象引用 int main( int argc, char *argv[] ) { // ORB initialization CORBA::ORB_var orb = CORBA::ORB_init( argc, argv, "local-orb" ); CORBA::Object_var obj = orb->string_to_object( argv[1] ); Account_var client = Account::_narrow( obj ); client->deposit( 700 ); client->withdraw( 250 ); cout << "Balance is " << client->balance() << endl; return 0; }
服务器端C++ mapping • 对象与OA进行通信
Servant 客户请求 Servant ORB POA Manager POA Servant 服务器端C++ mapping(续二) • Servant和CORBA对象
服务器端C++ mapping(续三) int main (int argc, char *argv[]) { CORBA::ORB_var orb = CORBA::ORB_init (argc, argv, ”local-orb”); CORBA::Object_var poaobj = orb->resolve_initial_references ("RootPOA"); PortableServer::POA_var poa = PortableServer::POA::_narrow (poaobj); PortableServer::POAManager_var mgr = poa->the_POAManager(); Account_impl * account = new Account_impl; PortableServer::ObjectId_var oid = poa->activate_object (account); …… // Write reference to file mgr->activate (); orb->run(); poa->destroy (TRUE, TRUE); delete micocash; return 0; }
POA: Portable Object Adapter • POA负责创建对象引用、激活对象以及分发请求 • POA负责从CORBA对象到servant之间的对应 • CORBA对象与servant对象的生命周期相互分开 • POA对于CORBA服务器在性能、资源利用、可伸缩性等方面具有重要的意义 • POA策略,控制: • 对象生命周期:永久对象、暂态对象 • 对象标识符:在POA范围内唯一 • POA Active Object Map:从ObjectID到servant的映射 • 请求处理策略:servant manager • 线程模型 • ……
POA: Portable Object Adapter(续) • POA的编程 • 所有的工作都从RootPOA开始 • 所有的POA构成一个树状层次结构 • 利用RootPOA的create_POA创建新的POA • 在创建POA时指定策略,CORBA::PolicyList • POA提供的功能 • 创建对象 • 注册servant,激活对象 • 提供ObjectID、ObjectReference之间的转换 • servant manager编程 • POA manager:控制来自客户的请求 • 多个POA可以共享同一个POA manager • ORB事件处理
服务器端C++ mapping(续四) • 利用idl生成的框架类编写servant类 • 编写main函数 • 从ORB初始化开始 • 考虑POA的策略,简单的程序可以使用默认的RootPOA • 创建servant并注册 • 处理对象引用 • 进入主循环 • 阻塞方式:orb->run() • 非阻塞方式:orb->work_pending()orb->perform_work()
用C++开发CORBA应用 • 基本的C++知识,包括链表结构、智能指针的知识 • 针对当前使用的ORB产品,熟悉对于基本数据类型的支持,以及这些类型与当前平台上各数据类型的关系 • 理解CORBA的client/server应用模型 • 包含头文件 • 链接库文件 • 掌握IDL编译器 • 掌握ORB接口 • 如何传递对象引用
ORB接口 • 初始:CORBA::ORB_Init,通过命令行传递参数 • 对象引用到字符串的转换操作 • 对象引用:CORBA::Object • 获得初始接口 • resolve_initial_reference
DII:Dynamic Invocation Interface • 客户程序可以不通过IDL编译器生成的stub而调用对象的方法,步骤: • 客户首先得到对象引用:CORBA::Object_ptr • 创建一个请求对象CORBA::Request_ptr • 把调用参数放到链表中:CORBA::NVList_ptr,指明类型和数值,也指明返回值 • 调用CORBA::Request_ptr->Invoke方法 • 服务器并不知道客户程序是通过stub还是DII调用其方法的 • 客户程序在编译时刻可以没有idl类型知识 • 比较:COM Automation中IDispatch接口的用法
用C++开发CORBA应用:客户 • 用IDL生成stub代码以及类型定义头文件 • 在客户的main函数中,初始化orb,获得orb对象 • 获得对象引用,并调用_narrow向下转换 • 调用对象的方法 • 如果使用DII,则需要用到请求对象,并处理参数 • 如果不用_var类型的话,释放orb和对象引用
DSI:Dynamic Skeleton Interface • 服务器程序可以动态实现对象,而不利用IDL编译器生成的skeleton代码 • 服务器实现一个对象,如下所示 class GenericServant : virtual public PortableServer::DynamicImplementation { virtual void invoke (CORBA::ServerRequest_ptr req); virtual CORBA::RepositoryId _primary_interface ( const PortableServer::ObjectId &, PortableServer::POA_ptr); }; • main函数的处理不变 • 重点在于invoke函数,利用CORBA::ServerRequest对象获得所有的类型信息 • 对于客户透明 • 比较:COM Automation中IDispatch接口的实现
用C++开发CORBA应用:服务器 • 用IDL生成skeleton代码以及类型定义头文件 • 在客户的main函数中,初始化orb,获得orb对象 • 根据服务器应用的需要,处理POA • 创建servant对象 • 如果使用DSI,那么invoke方法是servant对象的关键 • 如何把对象引用传递出去?字符串?名字服务? • 调用orb->run()或者orb->perform_work()
RepositoryID Data for Protocol 1 Data for Protocol 2 … Endpoint Info Object Key Object ID CORBA IIOP和IOR • General Inter-ORB Protocol:CORBA定义了GIOP作为其互用性框架结构,包括数据传输、数据表示、消息格式 • Internet Inter-ORB Protocol:IIOP是GIOP的具体实现,建立在TCP/IP基础上 • IOR:Interoperable object reference
IOR例子 Repo Id: IDL:GenericServer:1.0 IIOP Profile Version: 1.0 Address: inet:162.105.178.100:12122 Location: corbaloc::162.105.73.196:12122//25607/991958392/%5f0 Key: 2f 32 35 36 30 37 2f 39 39 31 39 35 38 33 39 32 /25607/991958392 2f 5f 30 /_0 Multiple Components Profile Components: Native Codesets: normal: ISO 8859-1:1987; Latin Alphabet No. 1 wide: ISO/IEC 10646-1:1993; UTF-16, UCS Transformation Format 16-bit form Key: 00 .
CORBA services:naming service • 建立起“名称-对象引用”的映射关系 • 在内部以层次结构的形式组织名字映射,类似于文件系统的结构。 • 所有的类型和接口定义位于CosNaming域中 • NamingContext接口负责所有有关命名服务相关的功能,例如: • 创建新的context、删除context • bind操作、unbind操作 • resolve操作 • 怎样获得初始namingcontext? • 通过orb->resolve_initial_reference • ORB厂商应该提供命名服务工具
naming service示例 CORBA::Object_var nsobj = orb->resolve_initial_references ("NameService"); CosNaming::NamingContext_var nc = CosNaming::NamingContext::_narrow (nsobj); CosNaming::Name name; name.length (1); name[0].id = CORBA::string_dup ("myAccount"); name[0].kind = CORBA::string_dup (""); // 服务器方 Account_ptr acc = new Account_impl (); nc->bind (name, acc); // 客户方 CORBA::Object_var obj; obj = nc->resolve (name); Account_var client = Account::_narrow( obj );
CORBA services:其他服务 • Event service • 提供松耦合事件模型的机制 • Trade Service • 提供了更加灵活的对象查找服务 • Time Service • 提供了与时间有关的服务,统一了时间的表达方式 • Concurrency service • Security Service • Transaction Service • ……
ORB产品 • 考察ORB:支持平台、支持语言、性能 • 商业ORB • Orbix,IONA公司,完全支持CORBA 2.3规范 • Visibroker,Inprise公司,4.0版完全支持2.3规范Netscape communicator浏览器嵌入Visibroker • 自由ORB • ORBit,遵循CORBA 2.2规范,支持C语言,性能较高 • mico,GNU,OpenSource • TAO,美国华盛顿大学分布式对象计算研究小组 • omniORB,AT&T剑桥实验室
CORBA与COM的比较 • 标准的层次不同 • CORBA与Java结合的优势 • CORBA跨平台优势 • COM在Windows平台上的优势 • COM的效率有优势 • 跨语言的策略不同 • COM组件丰富、CORBA开发简单 • CORBA不适合开发UI组件 • CORBA与COM互补策略