多年前用com时,做的小结,拿来分享,有错误的地方,多提宝贵意见,另外,我现在基本不用|COM了,但可以借鉴它的思想

来源:互联网 发布:mac下的翻墙软件 编辑:程序博客网 时间:2024/05/22 04:35

程序是思想的表达,只有有思想的人才能写出有意义的程序。

技术是问题的解决方案,只有合适的才是最好的,所以千万不要盲目追求使用某种新技术。

一、              在每一个线程内只要使用COM组件,就一定要调用COM初始化

在COM中,COM环境的维护是以线程为单位的,在一个线程里初始化了COM环境,只要这个线程退出,那么COM环境就被注销了。这时,倘若我们在其他的线程里在使用组件就会调用失败,表现在两个方面:

1、已经创建了的对象无法释放,即调用Release会出错。

2、要创建的对象无法创建,即调用CreateInstance会失败。

因此、建议总是调用CoInitialize

二、              不要在线程之间传递原始接口指针

一个COM对象往往具有共用性,在一个进程的不同线程内,不同的进程中可能需要对同一个COM对象的同一个接口的访问。这就引入了并发问题。COM并发的一个基本原则,就是如果多个不同线程共享同一接口,那么在线程之间传递接口时,首先要进行封送。封送接口指针可使COM创建一个新的代理,以允许从另一个单元向外调用。不通过封送而将一个原始接口指针(内存中的一个32位地址)直接传递给另一线程,会绕过COM的并发机制,将会由于各种临界资源的访问产生各种错误。Windows NT 4.0 和更高版本可以使用一对名为 CoMarshalInterThreadInterfaceInStream 和 CoGetInterfaceAndReleaseStream 的 API 函数,在线程之间轻松地封送接口指针。

三、              接口调用的默认规则

一个接口往往是实现一组功能的函数集合。设计的原则是函数的独立性,即是强调各个函数之间尽量做到相互独立。最后的结果就是它们之间的调用次序不会影响函数功能的实现。但是,在具体的实现中,往往由于各方面的缘故难以满足这个要求。这就有了函数之间的依赖关系。举例来说,一个查询的函数的执行需要首先存在数据库连接,而这个连接是通过另外的一个接口函数传入对象里面的,那么,这两个函数就有了调用的先后顺序,我们称之为接口调用的默认规则

这个规则的普遍存在,除了要求我们在设计接口时要避免,更重要的是维护规则的逻辑不变性。无论对象内部如何调整,都不会影响到外部的用户。

       因此接口的发布时,除了描述接口函数功能,还要描述接口调用的默认规则。

四、              函数实现和调用的良好习惯

在某些函数的实现时,往往我们需要通过函数的参数返回一个对象或者接口指针。首先说实现,存在两种可能,一是函数满足用户的要求,返回了对象或者接口的指针;二是函数不能满足用户的要求,不能返回对象或者接口的指针。良好的习惯就是函数要对自己的能力明确表态,如果能实现,则返回,否则应该赋值NULL。这样用户可以根据参数返回值得知指针的有效性。其次说调用,也存在两种可能,一是函数明确表态,用户在调用了函数之后,可以判别指针返回值;二是函数只能返回正常值,对于不能满足的,参数返回值不做任何赋值操作,这就可能是乱码啊。良好的调用习惯就是指针在调用函数之前先进行初始化赋值NULL。试想,如果供需双方都有不良习惯,那么,函数在正常调用时,没有任何错误;倘若不能正常调用时,只能出错了。

五、              界面状态机

在这里定义界面的状态机,主要是为了解决界面控制和用户操作带来的问题,企图保证界面状态的正确:包括输入数据、输出数据、可操作性。

六、              全局变量的弊端和妙用

作为全局变量一向由于其作用范围广,便于在对象间传递信息的优点被许多程序员使用,但是好的东西往往也有反面性,根据本人的建议,一般情况下,还是少用全局变量为妙。全局变量是在模块装载时就装载并分配内存的,其有效期为模块存在的整个生命期内,与模块内对象的生命期无关。由于全局变量的作用范围广,作用周期长,容易使得程序带来记忆效应,容易 出现问题。由于模块内的任何对象和函数都具有对全局变量的修改能力,容易使得全局变量的值修改出错;全局变量的应用会增加模块之间的耦合性,打乱模块之间的逻辑结构。所有这些都说明全局变量存在着各种弊端,但是,我们并没有禁止使用,正是由于全局变量在模块退出时才最后析构,可以利用全局变量的这一特点来判断对象的状态,这正是全局变量的妙用。

七、              程序的运行过程和DLL的调用机制

程序的运行首先是由操作系统将程序代码装入内存栈中,栈中就有了类的定义,函数实现等,然后进入运行阶段,首先,创建全局变量,如果全局变量是对象,那么就要根据类定义(成员的大小)分配内存,保存对象,同时使对象的函数列表指针指向类的函数列表。从而使对象具有了成员和函数的双重功能。

八、              测试工作三步走

1、界面、功能、性能三大内容

2、界面讲控制-状态机,闭集回归

3、功能:考虑业务逻辑正确性,算法逻辑正确性,功能实现全面性

4、性能:考虑业务逻辑性能优化,算法逻辑性能优化

5、语言逻辑:正确性和速度优化

九、              关于线程

多线程对于模块划分的问题和多线程中线程有效性判断。多线程对于模块的划分要掌握一个 “功能原子性”原则,这类似于数据库设计中的原子性原则。

十、              关于内存和野指针

关于内存的详细讨论,我专门写了一个专题《关于内存问题和使用内存建议》,这里指了一般错误原因。

1        内存分配未成功,却使用了它。

2        内存分配虽然成功,但是尚未初始化就引用它。

3        内存分配成功并且已经初始化,但操作越过了内存的边界。

4        忘记了释放内存,造成内存泄露。

5        释放了内存却继续使用它。

 

十一、   Windows程序运行机制

在Window操作系统平台上编写window程序,不能不了解window程序的运行机制:这就是Windows消息机制。Windows消息犹如发动机的油泵,获取用户操作等的各种消息,并发送出去,由窗口接收消息,并作相应的处理。因此,在编写程序时,如果有什么问题无法解决时,我们不妨回到消息机制中来,通过消息机制来实现,必定这是window操作系统的根本,也是经验。

十二、   软件工程化之路

用分阶段的周期计划严格管理

1.项目概要计划

2.里程碑计划

3.项目控制计划

4.产品控制计划

5.验证计划

6.运行维护计划

坚持阶段评审:错误发现的越晚,修正这些错误所付出的代价越大。坚持阶段评审,以便尽早发现错误。

严格的产品控制:需求等变动所造成的软件改动,要保证各界段文档与代码一致。

结果应能清楚地审查:为保证阶段化管理,明确地规定开发小组的责任和产品标准

十三、   关于使用ADO进行数据库操作的说明

数据库打开判断和关闭,数据集判断

循环与moveNext的对应

数据库操作(插入、删除、修改)事务机制

数据库查询的精简机制和类型匹配机制。

数据集打开和执行SQL语句的方式打开。

查询的关心属性与关键属性的选取,语意与语句不一致,语意如何以逻辑的形式表达,这条适合关联查询和其他查询,这种情况建议使用层次查询,但是层次查询将会出现循环,所以会影响速度。所以说改善查询条件是至关重要的。

十四、   运行时类型识别

需要进行内存块的检测。

十五、   面向对象的本质

设计面向对象的类,做C++的设计者,而不要做VC工具的奴隶。

十六、   接口的多态和对象的多态

多接口,是对象多态的体现,一个对象可以有不同的功能。

一个接口被多个对象实现,这叫做接口的多态,调用统一接口,却看到了不同的结果,这个问题,在C++中应用非常普遍。自动化和ATL中的多接口实现多态

十七、   自动化和ATL的选取,最好不要混用

十八、   注册的本质:静态注册和动态注册

 静态注册,也就是我们所说的将对象、接口、类型库的位置写入注册表,通过注册表建立起他们及其位置的对应关系。

十九、   自描述语言和格式化语言的选择

自描述语言XML在信息传递、特别是网络信息传递中具有不可逾越的优势,但是,自描述语言由于带有自描述的赘余信息,致使数据量大,在读取和写入时,比较耗时。因此,在选择自描述语言生成文件还是格式化文件时,关键要看信息占用度。如果信息占用度较高,则可以采用此种文件格式,否则,信息占用度较低,且又要关系计算的速度,则最好采用格式化数据。第二种选择方案是:如果文件信息是用来与外部交换数据的则采用XML,如果是内部的计算过程文件,则只需要格式化数据。

二十、   Goto和return 的谨慎

鉴于goto得到了C++程序员公然的抨击,但是return 的使用,却没有引起程序员足够的重视,尤其在一些复杂的含有动态分配的问题中,返回前没有保证内存问题,这就造成了内存使用的问题。

二十一、      数组定义的大小问题

好多采用变量定义的数组,致使编译器无法通过编译,这是由于编译阶段,编译器无法识别数组的大小问题造成的,有些大小是在编译阶段就已经知道了,有些则必须在运行阶段才能够解决。

二十二、      为什么静态数组的大小不能采用变量?

这涉及到程序的编译期和运行期两个阶段的问题。

二十三、      计算机的栈思想应用

辅助解决程序返回时的错误。

二十四、      想不到的exit原来这么武断、这么懒

所以你最好不要用它。

二十五、      编成良好的习惯能够暴露逻辑问题和解决问题

二十六、      三个目标:

1、自觉执行起编码规范,严格编码

2、引入设计模式,设计出良好的组件、系统

3、重视复用,逐步建立完善的可复用组件库

二十七、      系统交互性(输入、输出、灵活控制)

界面友好的本质在于从用户角度考虑,用户易于获得所期望的结果,增加人性化的设计.这必然要求与用户进行大量的交互。确定用户以什么方式输入比较合适,然后以什么方式输出结果才合理,实用。例如,商业化的软件像Word,Excel ,

XML,Txt,Access,dmp格式的文件已经成为全球人们信息交互的主要载体.那么,我们的软件在入口和出口上都应该充分的考虑这些数据格式.比如,将Word 的表格数据,通过设置的行列对应关系进行入库,而不要一个一个的入库,这样就来得简单.输出的数据也同样保存为这些格式。

开发软件具有自己的数据形式,具有完善的功能需要庞大的开发工作量,同时增加了开发难度,合理的采用商业化的软件作为中间介质,不但具有通用性,同时也可以利用商业化的软件完成相当数量的功能,稳定、简单而实用。比如将

表格数据存储为Excel,就可以很轻松的实现打印等。

二十八、      逻辑关系的定制、存储,简化界面的开发

在开发复杂界面,且界面与数据相关的情况下,请不要在软件中将数据的关系锁死,这样一旦修改数据的关系,软件就要跟着修改,增加了开发和测试的工作量。这种数据之间的逻辑关系,我们可以进行综合归类,或通过数据库,或者通过格式化文件来描述这种逻辑关系,在软件实现中,只考虑逻辑关系,不考虑具体的数据,这样就不会由于数据扩展升级带来麻烦。例如需求数据采集,需求类型,网络类型关系要在库中存储,然后在外面可以设置修改他们的关系。

 

二十九、      在数据库查询中,关键字段和非关键字段的使用:关键字段可以关联,非关键字段不能关联,注意正确表达语义,不要漏掉记录,也不要多选记录

三十、   一个分号引发的血案

三十一、      一个括号{}生机无限

三十二、      查找文件函数,注意千万别漏了

三十三、      桥模式的魅力

三十四、      模式的本质在于理解问题本身后灵活运用

三十五、      有关数据库操作中的翻译,请不要采用if语句,而应该在数据字典中定义,通过语句查询而得,有利于提高查询效率和简化编程。

三十六、      软件架构

软件架构多组涉众,具有多个视图。

第一个问题,软件架构的表达与交流问题。

第二个问题,软件架构的设计问题,可以从用户、客户、开发人员、管理人员四个视角采取分而治之的方式进行设计。软件架构设计中牵扯很多概念和技术,例如逻辑层、物理层、子系统、模块、接口、进程、线程、消息和协议等,可以一次只围绕少数概念和技术展开,分别着重研究软件架构的不同方面。

架构设计方法的5视图:逻辑架构、开发架构、运行架构、数据架构和物理架构,其中逻辑架构视图和物理架构视图是最基本的架构视图。

物理架构规定了组成软件系统得物理元素,这些元素之间的关系,以及他们部署到硬件上的策略。物理架构可以反映出软件系统动态运行时的组织情况。

软件逻辑架构设计的三大核心任务:

l        识别功能块

l        规划功能块的接口

l        明确功能块之间的使用关系和使用机制。

成功的软件架构设计应具有的品质:

l        良好的模块化。每个模块职责明晰,模块之间松耦合,模块内部高聚合并合理地实现了信息的隐藏;

l        适应功能需求的变化,适应技术的变化。典型地,应该保持应用相关模块和领域通用模块的分离,技术平台相关模块和独立于具体技术的模块相分离,从而达到隔离变化的效果;

l        对系统的动态运行有良好的规划。明确哪些模块是主动模块,那些模块是被动模块,他们之间的调用关系和加锁策略。

l        对数据的良好规划。包括数据的持久化存储方案,数据传递、数据复制、和数据同步等策略。

l        明确灵活的部署规划。涉及到可移植性、可伸缩性、持续可用性和互操作性。