关于面向对象的讨论【2】-.NET初学者架构设计指南(一)Hello world的时代

.NET初学者架构设计指南(一)Hello world的时代

中 学的时候,学校里开设了电脑课。当时的电脑还是一种比较希罕的东西,学校里的电脑一共就十几台,还专门找了一个大厅摆放这些机器。厅里面铺着厚厚的地毯, 整天都拉着重重的窗帘。每次上课前一天,我们需要沐浴更衣,剪好指甲。上课时大家都穿上鞋套,排好队伍,列队进入机房。然后各位同学坐在座位上,在老师的 指挥下,拿出一张五英寸的软磁盘,磁盘里安装着DOS操作系统,插入电脑的A驱动器。然后依次打开显示器、主机电源,在一阵吱吱声中,等待着电脑的启动, 进入一个充满了幻想的神奇世界。

我就是在那个时候写出了第一行程序。当时我们学的是一种叫做GWBASIC的语言,这是BASIC语言的一个分支。

BASIC是一种非常简单的交互式程序设计语言。编码人员需要为每一行代码编制一个行号。行号是一个自然数,为了日后调试的需要,一般都是 在最初编制行号的时候故意留下富余,不是按照1、2、3……的方式编制行号,而是按照10、20、30……的形式。程序输入完毕以后,运行“RUN”命 令,编译器按照行号的顺序,解释执行程序。

这样的编程方式太简单了,只要记住几个流程控制、输入输出的关键字,就可以写出一个简单的程序。那段时间我每天都在想着把平时遇到的东西 用程序写出来,多元多次的方程式、猜数字的游戏、三角函数曲线……先把编程的思路记在纸上,每个星期上课的时候再在电脑上写出来,调试运行。调试方式也非 常简单,就是把数值往屏幕上PRINT,然后运行查看结果。写完了之后运行“SAVE”命令,把代码保存到软盘里。

中学时期应该是一个人的思维最灵活的时期,以后的时期经验逐渐的丰富,但是学习新知识的能力实际上是在走下坡路。除非特地去培养,很多方 面的知识也就停留在中学的水平。比如对于一个搞计算机的专业人员来说,他的历史、语文、物理、化学知识很可能就永远的停留在中学时期的水平。那段时间我疯 狂的写着程序,最大的愿望就是家里能有一台电脑,安装着GWBASIC的编译器,我可以每天把自己关在屋子里,用GWBASIC写出超级玛丽,或者坦克大 战一样的游戏。

GWBASIC使用一种非常原始的方式进行流程控制——GOTO。他也有函数的概念,但是实际上也是GOTO到某段代码上去(使用 GOSUB指令),执行完了再GOTO回来(使用RETURN指令)。按照当时流行的观念,程序中使用GOTO并无不妥,这是实现条件循环的一种很正常的 方式。例如下面这段代码:

50 LET I = 0
60 I = I + 2
70 PRINT I
80 IF I < 100 THEN GOTO 60

下面是我当时写出的一段代码,这是一个猜数字的游戏,他就是在GOTO来GOTO去的兜圈子,像是进入了一个迷宫。还好这个迷宫的规模不大,很容易就能找出他在干什么。这段代码之所以能够保存到现在,是因为他没有象其他代码一样保存在软盘里,而是随手记录在了书的空白处。

10 PRINT "Guess a number"
20 INPUT A
30 IF A > 5 THEN GOTO 60
40 IF A < 5 THEN GOTO 80
50 IF A = 5 THEN GOTO 100
60 PRINT "Too big"
70 GOTO 20
80 PRINT "Too small"
90 GOTO 20
100 PRINT "Right"
110 END

这样的编程方式就是:面条式代码。这是一种最简单的编码方式,不需要长时间的学习或太多的经验就可以立即掌握。但是他能解决的问题也是有限的,也就 只能写一个猜数字的小游戏,或者画出一个Y=A*SIN(X)+B的函数曲线图。如果要真的用他来写一个超级玛丽,那将是很很很很很困难的。

后来进入了结构化编程的时代,GOTO成了破坏程序结构化的罪人,渐渐的被大家抛弃,现在只在的很少的地方仍然发挥着作用(比如在VB或 者C语言中进行异常处理)。但是这种GOTO式的编程方法影响了我很久。直到我大学时期,学习FORTRAN77的时候,仍然在采用这种编程方式。这样的 方式很简单,不用想的太多就能解决问题,也使我小富即安,懒得去研究别的编程方式。

结构化编程方式是面条式代码的一种改良。他首先把需要处理的问题划分成若干个模块,然后再把每个模块划分成更小的模块,这样一步步细化下 去,直到每个模块的功能可以用一个程序语句实现,这就完成了程序的设计。在划分模块的时候,结构化编程的原则是:一个模块只能有一个入口和一个出口,并在 要按照基本结构完成模块之间的连接。这就意味着GOTO只能与IF配合使用,以构成分支和循环的结构。分支和循环结构在任何一种编程语言中都有更简单明确 的关键字来实现,GOTO自然就失去了存在的意义。

结构化编程是一种面向过程的编程方式。所谓“面向过程编程”是译自“Procedure-oriented programming”,实际上应该理解成“以过程为导向的编程方式”。按照这样的编程方式,人们首先要确定用什么样的流程来实现业务需求,接着就一步 步的分解这个流程,分解,再分解……直到可以用一个语句实现,最后就用程序实现这样的流程。下面的流程就实现了这样一个小测验:测试计算11到20的平 方,每算对一个数可以得到10分,最后输出总分。

面向过程的编程方式必须在编程之前将解决问题的流程确定下来,这是一种很不灵活的方式。我们解决一个问题的时候,是很难在一开始就把流程定 的很合理的。比如说,我们开发一个Email服务器,用户最初要求有这样的功能:收到邮件的时候判断一下是不是垃圾邮件,如果是垃圾邮件,就直接移到垃圾 邮件夹里。后来我们在开发的过程中发现,垃圾邮件的识别率并不是很高,难免会把一些正常邮件当作垃圾邮件移走了,造成用户的邮件不能及时收到。于是这个流 程必须调整成这样:发现垃圾邮件不能移走,而是在标题上加上一个警告标记。并且这个流程的改变会影响其他的流程:使用POP客户端下载邮件的时候,对垃圾 邮件只能下载标题和纯文本的内容,确保客户端的安全。可以看出,业务流程的制定需要在随后的开发过程中不断得到反馈,不断进行调整,最后才能达到一个比较 好的效果。但是按照面向过程的编程方式,我们必须先确定一个流程,再开始设计,否则需求就不确定。如果在编程的过程中发现流程不合适,在效率或者准确性上 不满足需要,程序就要重新设计了。这样边写边改,又要顾忌对其他流程的影响,程序写起来是很困难的。

后来又发展出来另外一种编程方式:面向对象的编程。面向对象的编程是译自“Object-oriented programming”,简称OOP,其实上也应该理解成“以对象为导向的编程方式”。用这样的编程方式,先不要急于确定用什么样的流程来实现业务需 求,而是先看看需求里面包含有哪些“东西”,这些东西是怎样出现的,具有什么样的属性,可以做哪些事情,会发生什么样的事件,这些东西之间是什么样的关 系。用程序把这些东西造出来,然后就让这些东西运行起来,实现预想的功能。

比如刚才那个Email服务器的问题,在流程不确定的情况下,我们可以先看看这个Email服务器里面有哪些东西,最明显的,应该有 Email类。Email类有三个行为:接收(Receive)、显示(Show)和下载(Download)。垃圾邮件是邮件的一个特例,可以看作 Email的一个子类,如下:

JunkMail覆盖了Email的接收、显示和下载方法。如果垃圾邮件应该有一些特别的处理方式,就可以只修改JunkMail类——在 接收时移至垃圾邮件夹、或者在显示的时候加上一个警示标志、下载时过滤掉其中的非文本内容——没有其他类的代码需要改动。这样不会对普通邮件的处理流程产 生任何影响。

面向过程和面向对象这两种编程思想的区别在于:他们对于需求的理解是不一样的。面向过程的编程人员,他们把需求理解成一条一条的业务流 程,他们喜欢问用户“你的业务流程是什么样的?”,然后他们分析这些流程,把这些流程交织组合在一起,最后实现了需求;面向对象的编程人员,他们把需求理 解成一个一个的对象,他们喜欢问用户“这个东西叫做什么,他从哪里来,他能做什么事情?”,然后他们制造这些对象,让这些对象互相调用,符合了业务需要。 关于这两种编程方式的对比,在后面的章节中会有具体的说明。这里简单的说两点:

1、对象比流程更加稳定。业务流程的制定需要受到很多条件的限制,甚至程序的效率、运行方式都会反过来影响业务流程。有时候用户也会为了更好的实现商业目的,主动的改变业务流程,并且一个流程的变化经常会带来一系列的变化。这就使得按照业务流程设计的程序经常面临变化。

2、对象比流程更加封闭。业务流程从表面上看只有一个入口、一个出口,但是实际上,流程的每一步都可能改变某个数据的内容、改变某个设备的状态,对外界产生影响。而对象则是完全通过接口与外界联系,接口内部的事情与外界无关。

按照面向对象的编程方式,我们要用对象来体现现实世界中出现的事物。如果需求比较复杂,这样会造成程序里出现大量的对象、复杂的关系,修改 程序的时候越来越麻烦。其实一些对象之间总是有着比较固定的关系,有的对象之间是包含的关系,有的是依赖的关系,有的对象是别的对象的创建者……有经验的 程序员会从这些关系中发现一些规律,寻找出处理这些关系的一些方法,这就形成了设计模式。比如一个通信公司为他的用户设置各种套餐,用户选择不同的套餐, 通话就采用不同的计费策略,这种情况可以采用Strategy模式;一家销售自行车的公司同时销售自行车的零件,有的零件是多个零件的组合,又可以和别的 零件组合成一个更大的零件,这就可以采用Composite模式。有时候程序员可以从模式中获得设计的灵感,对软件的整体构架产生影响。在以后的章节中我 会对设计模式进行介绍。

软件开发思想经过了几十年的发展。最早的面条式的代码,一个中学生很快就能学会,可以立即用它来解决一个多元多次方程;后来发展到结构化 编程,把代码分割成了多个模块,增强了代码的复用性,方便了调试和修改,但是结构也复杂了很多。最早的编程方式是面向过程的,非常直观,一个初学者很快就 可以理解;后来有了面向对象的方式,问题的解决看上去不再这么直截了当,需要首先开发业务对象,然后才能实现业务流程。随着面向对象编程方式的发展,又出 现了设计模式、MVC、ORM、以及不计其数的工具、框架。软件为什么会越来越复杂呢?其实这不是软件本身的原因,而是因为软件需要解决的需求越来越复杂 了。

最早的计算机只需要帮助人们做纯粹的计算任务,他用插头和开关作为输入设备,用信号灯做输出设备,没有存储器,也没有程序。当时人们需要 计算机,只是想让他帮助人们在人口普查、天气预报这样的事情中担任计算任务。早期的计算机曾经参与了曼哈顿计划,最初军方雇用了大约100名计算员,参与 计算原子核裂变的各项数据,但是无法达到满意的进度。后来由于计算机的研制成功,大大加速了原子弹的研制速度,这也加速了第二次世界大战的尽快结束。

稍后一点的计算机采用卡片穿孔的方式作为控制方式。程序员把需要运行的运算用二进制的方式记录在卡片上,穿孔的地方代表1,不穿孔的地方 代表0。把卡片塞进计算机的输入设备,计算机就按预定的方式运行,这就是最早的机器语言。随着计算机的运算速度越来越快,人们发现很多时候都是计算机在等 待着输入设备,很多时间被浪费掉了。于是人们设计出了一次可以处理多个卡片的计算机。多张卡片可以同时放入计算机,计算机按照一定的规则进行调度,按照某 种优先顺序执行他们,这就是中断和任务的调度的概念,最早的操作系统就这样出现了。银行、会计事务所这样的公司每星期把写好的卡片放到计算机中运行,很快 就可以完成大量数据的处理工作。这时的计算机仍然是一种非常复杂的设备,维护、使用都十分困难,当时的计算机生产公司必须提供全套的安装、维护、运行解决 方案。

此时的计算机编程就是在卡片上穿孔,所使用的语言完全是机器代码。机器代码难以记忆,不容易理解。于是人们发明了汇编语言,汇编语言实际 上是机器语言的助记符号,可以用编译器翻译成机器代码卡片。从词法和语法上说,他更接近与自然语言,但是从流程上说,仍然是机器语言的那一套。

这个时候,计算机软件已经成为了一种耗资巨大的工程。当时的计算机硬件是一种十分高档的昂贵设备,以至于一些大公司都没有勇气独立购买, 而是采取租用的方式,租借机器的投资可以达到上百万。而软件开发所花的钱比起租机器的钱是只多不少。最为典型的工程是IBM360的操作系统。当时IBM 公司研发新的电脑——IBM360,他们的计划是为这种机器单独开发一个操作系统。软件开发耗资巨大,工期一再拖延,直到整机上市一年以后,操作系统才得 以发布。后来一位参与操作系统开发的工程师写了一本书,描述了他在项目中得到的一个重要经验:向一个进度缓慢的软件项目中盲目的追加人力,只能让进度更加 缓慢。软件开发需要很大的人际交流成本,这使得项目的规模不能简单的用人月数来衡量。

汇编语言这解决了机器代码难写难记的问题,但是不同公司生产的机器、不同型号的机器汇编指令集是不同的,在一种机器上写出来的程序无法移 植到另一种机器上执行。于是有人希望解决这个问题,他设计了一种新的程序语言——FORTRAN。FORTRAN的语法更加接近自然语言,并且他设计了适 用于多种机型的编译器,可以把FORTRAN的源码编译成可以在多种机器上执行的机器代码。计算机的创始人之一,冯·诺伊曼当时认为搞这种高级语言没有多 大的意义,计算机发展的重点不应该在这个地方。冯·诺伊曼肯定是一个汇编高手,写起机器代码来也是相当的娴熟,自然认为搞什么高级语言没有多大的必要,汇 编挺好的嘛。这种感觉就应该类似于当今的一些C语言高手面对JAVA和C#时的感想。

FORTRAN的意义在于,他使计算机不再是计算机专业人员才能操纵的工具。数学家、工程师、会计师、学生都有机会亲自使用计算机来解决 自己的工作中遇到的问题。高级语言的诞生使得软件业得到突飞猛进的发展。当时的FORTRAN仍然不是一种结构化的编程语言,FORTRAN中的变量都是 全局变量,他使用与汇编相似的方式进行流程控制。

随后的几年中,LISP、ALGOL、COBOL等一批高级语言陆续不断的涌现出来。这些语言都有一个共同点:他们都出现了局部变量的概 念,都是结构化的编程语言。局部变量有着更加清晰的作用域和生命周期,程序划分为若干个子过程,某个子过程中定义的变量在其他子过程中是不能访问的。有了 这样的机制,程序员不用再担心自己定义的变量被意外的修改,这样就有利于更多的程序员合作编写大规模的程序。

接下来的几年出现了越来越多的高级语言,在文字处理、科学计算、数据制表等各种领域发挥着重要的作用。BASIC语言也就是在这一时期出 现(BASIC语言并不是结构化语言),他的全称是:初学者通用符号指令代码。BASIC语法简单,易学易用,普通人稍加训练就可以用BASIC进行编程 了。

从这一段历史看出,计算机软件技术不断发展,他的目的是使人们使用计算机解决问题的过程越来越简单。人们需要用计算机来解决越来越复杂的 需求,从最初的科学计算,逐渐发展到表格处理,会计计算,管理一个大型企业的商业活动,这就迫使软件开发技术和思想不断进步。要创建新的技术平台,让设计 人员在这个平台上不用考虑过多的基本技术问题;要创建新的分析方法,让设计人员可以忽略细节上的复杂度,更容易从整体上把握软件的构架。

现在的软件技术发展仍然是在延续这样的方向。软件的构架越来越庞大,从单层的、简单的面向过程的代码,发展到多层的、面向对象的代码,表 面上看是变得复杂了,实际上是使得软件的逻辑结构更加清晰,从而不断的满足日益复杂的业务需求。程序员可以从技术细节中腾出力量,去解决更加复杂的业务问 题。

学习和运用各种先进的技术也应该注意这一点:技术的发展是为了更容易的解决业务问题,降低开发成本——这也是我们运用他们的目的。本文在 后面的章节介绍一些编程的思想和技术,也会遵循着这样一种思路,要看看这些东西是如何使程序员更加迅速准确的解决业务需求。为了能够说明这些思想和技术是 如何使得问题的解决逐渐变得简单,本文在举例说明的时候,会尽量的使用接近于实际情况的例子。简单的玩具形式的例子,比如用Cat、Dog和Animal 来说明多态的规则,看上去很形象,也是很有趣味,但是事情本身过于简单。使用这样的方式很容易把技术的原理说清楚,但是却让人不易明白他们的使用场景,甚 至误以为他们把原本简单的事情搞得复杂了。本文中的事例有的牵涉到一些特定业务领域的知识,看起来难免晦涩枯燥,希望大家能够容忍一下。

TO BE CONTINUE

出处:http://www.cnblogs.com/lane_cn/archive/2007/01/10/617099.html

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值