读《面向对象的思考过程》(Object oriented thought process)后的总结

1.面向对象(OO)的由来
面向对象是相对于面向过程的设计而言的。面向对象产生的原因在于原有的面向过程的程序设计将数据和行为分离,而且数据过分暴露,代码重用性差。有鉴于此,为了将不相关的数据隐藏起来,既数据隐藏,需要对数据和行为进行封装,从而产生了OO。
数据隐藏是将数据隐藏在类内部而不暴露。
封装是数据隐藏的必然结果,把数据和行为集成了一个类内,尽量减少数据暴露。
2.接口和实现(Interface和Implementation)
OO中,对象都不是孤立存在的,对象之间必有关系,接口是一种联系方式。OO中接口的含义同C#中关键字Interface不是一个含义。OO中,接口是指对象之间的交流机制,这种机制与封装相违背,OO中的接口表现为Public的方法,一切Public方法均可视为接口。通俗而言,只有Public的方法才可以为外部对象引用,从而构成对象之间的交流通道。
接口的设计原则:
l 类中的接口应尽量的少(Minimal Interface),甚至一开始并不定义public类型方法,直到有用户需求;
l 从用户角度设计接口,符合现实,满足用户需求;
Implementation(实现,不知对否)理解的不是很清楚,除接口外的所有方法可视为Implementation,表现为类内的私有方法,不能为外界对象所使用;另外,Interface的函数体(即实现部分)是否可以视为Implementation?因为Interface的实现部分,外部对象不可知,只是知道其名称(包括方法名、输入参数、返回值)。
3.Constructor的作用
必须为public类型,用来构造对象,通常在其中对对象的attributes进行初始化,即使没有new,也最好在constructor里定义其值为null。在使用attributes时,有一个良好的习惯,即用if判断其是否为null。
4.异常处理的首要原则
系统不能因为异常崩溃,当有错误发生时,系统要么适应错误并继续运行下去,要么在不损失任何数据的情况下安全退出系统,这是异常处理的最基本要求。
5.类的设计原则
l 可重用性
l 可扩展性
l 与硬件有关的代码,要从主类中剥离
l 变量作用域尽可能小,能用局部变量就不要用类一级变量
l 对象的序列化,中间对象消失前,应给与序列化并保存
l 易维护性,本质上是减少类之间的耦合,使一个类的改变不过分波及其他类,这主要对接口的设计提出要求。尽量避免类之间互相调用,不仅破坏了程序的层次,也加大的类之间的耦合程度。
6.OOD的基本步骤
面向对象的系统设计也有很多方法论,很多组织并不使用标准化的方法论。但基本上要跟从普遍的习惯,使用别人不用的方法论,意义不大。大体上OOD有以下几个步骤:
(1) 适当的分析。脑中思考,集体讨论。
(2) 制定一个工作说明(the statement of work)来描述系统。
工作说明也供需求方参考,以确定需求方是否可以接受工作说明中的方案,工作说明要以段落文章(paragraph)的方式予以体现。参考《**公司商业数据服务系统》一文。
(3) 在工作说明的基础上,确定系统需求说明。
系统需求是系统最重要的组成部分。工作说明中也有系统需求的说明,但过于概括,而且有很多与需求不相干的内容。系统需求说明必须精细,要与用户展开讨论,但用户过分的需求或者不利于系统维护的需求,项目经理在特殊情况下应该坚决拒绝。最终,系统需求说明要以条目的形式(bulleted list format)体现,这与工作说明的格式明显不同。系统需求必须在开始阶段做好,越早改动,其费用越小,越晚改动,其费用越大。
(4) 为用户接口设计原型(prototype)。
可在某些IDE中完成,如Visual Basic。
(5) 识别出系统中的类。
区分、识别类的一个很常用的方法是,“突出需求说明中的所有名词”,系统中的类大部分来源于这些名词,列出所有的名次后,要经过筛选,确定需要那些类。当然,并不是所有的类,都在这些名词中间。在类的设计过程中,还需要不断的增加、删除、改动类。一种普遍流行的识别和归纳类的方法是CRC卡片法(Class-Responsibilities-Collaborations Cards),每张CRC卡片都会表示类的名称、责任和合作关系。CRC卡片是一种非电子化的方法(当然肯定有公司针对此方法开发了系统),即CRC卡片的实施是在纸面上完成的,具有很强的灵活性和随意性。一般来说,卡片上必须包含三种内容:类名、责任、合作关系(类名主要在名词中寻找,职责主要在动词中寻找)。使用CRC卡片有很多好处,由于一开始进行OOD的并不仅仅是OODers和OOPers,也有用户,使用CRC卡片,可以让他们也看懂系统的设计过程,有利于双方交流;此外,通过确定CRC卡片上的“责任”和“合作关系”,可以检查类与类之间的关系,从而确定类是否缺失。继CRC卡片后,用UML建立对象模型。注意:CRC内的一开始给出的都是public类型,因为主要考虑的是类的接口,其他具体的private字段和方法,在修正CRC卡片时,可以逐渐添加。
(6) 确定各类的职责。
(7) 决定类之间的交流方式。
(8) 建立一个高级模型来描述即将动工的系统。
这里的模型指的是类模型,通常用UML进行构建。一个大型的系统,如果不使用UML,是几乎不可能完成的。
7.继承和包含(Inheritance and Composition)
继承前面已经说过,不重复。
包含指的是对象作为数据成员的情况。
继承和包含都是OO中代码重用的重要手段。一定不要滥用继承,甚至有的计算机学家认为Design with composition rather than inheritance。在很多OO设计平台上,并不支持真正的继承,MS COM是构建在接口继承上的,C#里的继承只能有一个父类,大多数时候要从Interface继承。我自己感觉,C#中的接口比抽象类更好用。使用类的话,要分别定义对象,但使用接口,只定义一个接口即可,它可以接受多种类型的对象,很灵活(比如说,如果接口作函数形式参数的时候,可以接受多种类型的对象,使用类的话就没有这种优点!)
8.使用框架(framework)
这里的框架与.net framework不是一种东西。使用框架的好处:第一,软件界面相似;第二,开发者可以充分重用框架已有而且经过测试的代码。因此,使用框架,同使用继承和包含一样,都是实现代码重用的重要方式。继承是类级别的重用,而framework则是类级别重用的组合,重用的往往是系统级别的。
通常的框架是以API的形式体现的,API是一种框架,用以解决代码重用性问题。API作为应用程序接口,存在很长时间了。MFC封装了大部分API接口,所以很多VC开发者直接使用MFC开发系统。但是在某些时候,为了提高程序灵活性和重用性,不会使用MFC,而是直接使用Win32API。
.net framework是一套全新的编程接口,在某种方面也可以看作是对API的封装,但是它运行在。Net平台上,机制和原来的完全不同。所以两者的区别就远大于MFC和API的区别。在.net中可以通过pInvoke来调用大部分API。对于C# 程序员而言,没有必要刻意掌握API,但也应该了解(这就是为什么。Net用来做应用,而不是想C++那样可以做底层,因为一切都在.net SDK的基础上了,但是反过来又可以问,底层到底有多底?没人晓得)。
阅读更多

没有更多推荐了,返回首页