.NET 高级架构师0002 架构师之路(1)---面向过程和面向对象

1、引言
     机算机科学是一门应用科学,它的知识体系是典型的倒三角结构,所用的基础知识并不多,只是随着应用领域和方向的不同,产生了很多的分支,所以说编程并不是一件很困难的事情,一个高中生经过特定的训练就可以做得到。但是,会编程和编好程绝对是两码事,同样的程序员,有的人几年之后成为了架构师,有的人却还在不停地coding,只不过ctrl-c、ctrl-v用得更加纯熟了。在中国,编程人员最终的归途无外乎两条:一是转向技术管理,它的终点是CTO;二是继续深入,它的终点是首席架构师,成为CEO的人毕竟是少数。如果你现在还是个普通的程序员,希望继续在技术这条路上前进的话,我想你还是应该先补充一点软件工程的思想,学习一点有关设计模式的知识,只有具备这些能力,你才能从整体和宏观层面来考虑问题、分析问题和解决问题。本人Coding了很多年,中间走了不少弯路,虽然最终没什么大成就,但总算有一些心得,很愿意把自己的一些经验拿出来跟大家分享,这或许对你的发展有所帮助。

由程序员转为架构师,最绕不开的概念就算是面向对象(OO)了。记得在大学的时候,我们专业开了一门课叫《面向对象的编程》。那个时候,我们刚刚学了一门C语言,开发环境用的还是DOS下的Turbo C,半点项目开发的经验都没有,纯粹的空对空。所以,一学期下来,我始终处于一种懵懂状态,既没领会面向过程和面向对象到底有什么区别,也没搞懂面向对象能带来什么好处。

2、面向过程(OP)和面向对象(OO)

2.1 蛋炒饭和盖浇饭
      有人这么形容OP和OO的不同:用面向过程的方法写出来的程序是一份蛋炒饭,而用面向对象写出来的程序是一份盖浇饭。所谓盖浇饭,北京叫盖饭,东北叫烩饭,广东叫碟头饭,就是在一碗白米饭上面浇上一份盖菜,你喜欢什么菜,你就浇上什么菜。我觉得这个比喻还是比较贴切的。
蛋炒饭制作的细节,我不太清楚,因为我没当过厨师,也不会做饭,但最后的一道工序肯定是把米饭和鸡蛋混在一起炒匀。盖浇饭呢,则是把米饭和盖菜分别做好,你如果要一份红烧肉盖饭呢,就给你浇一份红烧肉;如果要一份青椒土豆盖浇饭,就给浇一份青椒土豆丝。

蛋炒饭的好处就是入味均匀,吃起来香。如果恰巧你不爱吃鸡蛋,只爱吃青菜的话,那么唯一的办法就是全部倒掉,重新做一份青菜炒饭了。盖浇饭就没这么多麻烦,你只需要把上面的盖菜拨掉,更换一份盖菜就可以了。盖浇饭的缺点是入味不均,可能没有蛋炒饭那么香。
到底是蛋炒饭好还是盖浇饭好呢?其实这类问题都很难回答,非要比个上下高低的话,就必须设定一个场景,否则只能说是各有所长。如果大家都不是美食家,没那么多讲究,那么从饭馆角度来讲的话,做盖浇饭显然比蛋炒饭更有优势,他可以组合出来任意多的组合,而且不会浪费。

2.2 软件工程
      盖浇饭的好处就是“菜”“饭”分离,从而提高了制作盖浇饭的灵活性。饭不满意就换饭,菜不满意换菜。用软件工程的专业术语就是“可维护性”比较好,“饭”和“菜”的耦合度比较低。蛋炒饭将“蛋”“饭”搅和在一起,想换“蛋”“饭”中任何一种都很困难,耦合度很高,以至于“可维护性”比较差。软件工程追求的目标之一就是可维护性,可维护性主要表现在3个方面:可理解性、可测试性和可修改性。面向对象的主要好处就是显著的改善了软件的可维护性。

面向过程(OP)和面向对象(OO)是不是就是指编码的两种方式呢?不是!你拿到了一个用户需求,比如有人要找你编个软件,你是不是需要经过需求分析,然后进行总体/详细设计,最后编码,才能最终写出软件,交付给用户。这个过程是符合人类基本行为方式的:先想做什么,再想如何去做,最后才是做事情。有的同学说:“我没按照你说的步骤做啊,我是直接编码的”。其实,你一定会经历了这三个阶段,只不过你潜意识里没有分得那么清楚。对于拿到需求就编码的人,可能编着编着,又得倒回去重新琢磨,还是免不了这些过程,

以OO为例,对应于软件开发的过程,OO衍生出3个概念:OOA、OOD和OOP。采用面向对象进行分析的方式称为OOA,采用面向对象进行设计的方式称为OOD,采用面向对象进行编码的方式称为OOP。面向过程(OP)和面向对象(OO)本质的区别在于分析方式的不同,最终导致了编码方式的不同。

2.3 面向过程(OP)和面向对象(OO)

关于面向过程的编程(OPP)和面向对象的编程(OOP),给出这它们的定义的人很多,您可以从任何资料中找到很专业的解释,但以我的经验来看,讲的相对枯燥一点,不是很直观。除非您已经有了相当的积累,否则说起来还是比较费劲。

我是个老程序员出身,虽然现在的日常工作更多倾向了管理,但至今依然保持编码的习惯,这句话什么意思呢?我跟大家沟通应该没有问题。无论你是在重复我走过的路,或者已经走在了我的前面,大家都会有那么一段相同的经历,都会在思想层面上有一种理解和默契,所以我还是会尽量按照大多数人的常规思维写下去。

面向过程的编程(OPP)产生在前,面向对象的编程(OOP)产生在后,所以面向对象的编程(OOP)一定会继承前者的一些优点,并摒弃前者存在的一些缺点,这是符合人类进步的自然规律。两者在各自的发展和演变过程中,也一定会相互借鉴,互相融合,来吸收对方优点,从而出现在某些方面的趋同性,这些是必然的结果。即使两者有更多的相似点,也不会改变它们本质上的不同,因为它们的出发点就完全是两种截然不同的思维方式。关于两者的关系,我的观点是这样的:面向对象编程(OOP)在局部上一定是面向过程(OP)的,面向过程的编程(OPP)在整体上应该借鉴面向对象(OO)的思想。这一段说的的确很空洞,而且也一定会有引来争议,不过,我劝您还是在阅读了后面的内容之后,再来评判我观点的正确与否。

象C++、C#、Java等都是面向对象的语言,c,php(暂且这么说,因为php4以后就支持OO)都是面向过程的语言,那么是不是我用C++写的程序一定就是面向对象,用c写的程序一定就是面向过程呢?这种观点显然是没有真正吃透两者的区别。语言永远是一种工具,前辈们每创造出来的一种语言,都是你用来实现想法的利器。我觉得好多人用C#,Java写出来的代码,要是仔细看看,那实际就是用面向对象(OO)的语言写的面向过程(OP)的程序。

所以,即使给关羽一根木棍,给你一杆青龙偃月刀,他照样可以打得你满头是包。你就是扛着个偃月刀,也成不了关羽,因为你缺乏关羽最本质的东西---绝世武功。同样的道理,如果你没有领会OO思想,怎么可能写得出真正的OO程序呢?面向对象(OO)和面向过程(OP)绝对是两种截然不同的思维方式。

那是不是面向过程就不好,也没有存在的必要了?我从来没有这样说过。事实上,面向过程的编程(OPP)已经存在了几十年了,现在依然有很多人在使用。它的优点就是逻辑不复杂的情况下很容易理解,而且运行效率远高于面向对象(OO)编写的程序。所以,系统级的应用或准实时系统中,依然采用面向过程的编程(OPP)。当然,很多编程高手以及大师级的人物,他们由于对于系统整体的掌控能力很强,也喜欢使用面向过程的编程(OPP),比如像Apache,QMail,PostFix,ICE等等这些比较经典的系统都是OPP的产物。

象php这些脚本语言,主要用于web开发,对于一些业务逻辑相对简单的系统,也常使用面向过程的编程(OPP),这也是php无法跨入到企业级应用开发的原因之一,不过php5目前已经能够很好的支持OO了。

2.4 详解面向过程的编程(OPP)

在面向对象出现之前,我们采用的开发方法都是面向过程的编程(OPP)。面向过程的编程中最常用的一个分析方法是“功能分解”。我们会把用户需求先分解成模块,然后把模块分解成大的功能,再把大的功能分解成小的功能,整个需求就是按照这样的方式,最终分解成一个一个的函数。这种解决问题的方式称为“自顶向下”,原则是“先整体后局部”,“先大后小”,也有人喜欢使用“自下向上”的分析方式,先解决局部难点,逐步扩大开来,最后组合出来整个程序。其实,这两种方式殊路同归,最终都能解决问题,但一般情况下采用“自顶向下”的方式还是较为常见,因为这种方式最容易看清问题的本质。

我举个例子来说明面向过程的编程方式:

用户需求:老板让我写个通用计算器。

最终用户就是老板,我作为程序员,任务就是写一个计算器程序。OK,很简单,以下就是用C语言完成的计算器:

假定程序的文件名为:main.c。

int main(int argc, char *argv[]){

//变量初始化
    int nNum1,nNum2;
    char cOpr;
    int nResult;
    nNum1 = nNum2 = 0;
    cOpr = 0;
    nResult = 0;

//输入数据
    printf("Please input the first number:\r\n");
    scanf("%d",&nNum1);
    printf("Please input the operator:\r\n");
    scanf("%s",&cOpr);
    printf("Please input the second number:\r\n");
    scanf("%d",&nNum2);

//计算结果 
    if( cOpr == ‘+‘ ){
    nResult = nNum1 + nNum2;
    }else if( cOpr == ‘-‘ ){
    nResult = nNum1 - nNum2;
    }else{
    printf("Unknown operator!");
    return -1;
    }

//输出结果
    printf("The result is %d!",nResult);
    return 0;
}

抛开细节不讲,我想大多数人差不多都会这么实现吧,很清晰,很简单,充分体现了“简单就是美”的原则,面向过程的编程就是这样有条理的按照顺序来逐步实现用户需求。

凡是做过程序的人都知道,用户需求从来都不会是稳定的,最多只能够做到“相对稳定”。用户可能会随时提出加个功能,减个功能的要求,也可能会要求改动一下流程,程序员最烦的就是频繁地变动需求,尤其是程序已经写了大半了,但这种情况是永远无法避免的,也不能完全归罪到客户或者需求分析师。

以我们上面的代码为例,用户可能会提出类似的要求:
      首先,你程序中实现了“加法”和“减法”,我还想让它也能计算“乘法”、“除法”。
      其次,你现在的人机界面太简单了,我还想要个Windows计算器的界面或者Mac计算器的界面。

用户需求开始多了,我得琢磨琢磨该如何去写这段代码了。我今天加了“乘”“除”的运算,明天保不齐又得让我加个“平方”、“立方”的运算,这要是把所有的运算都穷尽了,怎么也得写个千八百行代码吧。还有,用户要求界面能够更换,还得写一大堆界面生成的代码,又得来个千八百行。以后,这么多代码堆在一起,怎么去维护,找个变量得半天,看懂了代码得半天,万一不小心改错了,还得调半天。另外,界面设计我也不擅长,得找个更专业的人来做,做完了之后再加进来吧。这个过程也就是“软件危机”产生的过程。伴随着软件广泛地应用于各个领域,软件开发的规模变得越来越大,复杂度越来越高,而其用户的需求越来越不稳定。

根据用户提出的两个需求,面向过程的编程该如何去应对呢?我想大家都很清楚怎么去改。Very easy,把“计算”和“界面”分开做成两个独立的函数,封装到不同的文件中。
      假定程序的文件名为:main.c。

#include "interface.h"
#include "calculate.h"
int main(int argc, char *argv[]){

//变量初始化
    int nNum1,nNum2;
    char cOpr;
    int nResult;
    nNum1 = nNum2 = 0;
    cOpr = 0;
    nResult = 0;

//输入数据
    if( getParameters(&nNum1,&nNum2,&cOpr) == -1 )
    return -1;

//计算结果 
    if( calcMachine(nNum1,nNum2,cOpr,&nResult) == -1 )
    return -1;

//输出结果
    printf("The result is %d!",nResult);

return 0;
}

interface.h:
int getParameters(int *nNum1,int * nNum2,char *cOpr);

interface.c:
int getParameters(int *nNum1,int * nNum2,char *cOpr){
    printf("Please input the first number:\r\n");
    scanf("%d",nNum1);
    printf("Please input the operator:\r\n");
    scanf("%s",cOpr);
    printf("Please input the second number:\r\n");
    scanf("%d",nNum2);

return 0;
}

calculate.h:
int calcMachine(int nNum1,int nNum2,char cOpr, int *nResult);

calculate.c:
int calcMachine(int nNum1,int nNum2,char cOpr,int *nResult){
    if( cOpr == ‘+‘ ){
        *nResult = nNum1 + nNum2;
    }else if( cOpr == ‘-‘ ){
        *nResult = nNum1 - nNum2;
    }else{
        printf("Unknown operator!");
        return -1;
    };
    return 0;
}

面向过程的编程(OPP)就是将用户需求进行“功能分解”。把用户需求先分解成模块(.h,.c),再把模块(.h,.c)分解成大的功能(function),然后把大的功能(function)分解成小的功能(function),如此类推。

功能分解是一项很有技术含量的工作,它不仅需要分解者具有丰富的实战经验,而且需要科学的理论作为指导。如何分解,分解原则是什么,模块粒度多大合适?这些都是架构师的要考虑的问题,也是我们后面要着重讲的内容。

面向过程的编程(OPP)优点是程序顺序执行,流程清晰明了。它的缺点是主控程序承担了太多的任务,各个模块都需要主控程序进行控制和调度,主控和模块之间的承担的任务不均衡。
      有的人把面向过程定义为:算法 + 数据结构,我觉得也很准确。面向过程的编程中算法是核心,数据处于从属地位,数据随算法而流动。所以采用面向过程的方式进行编程,一般在动手之前,都要编写一份流程图或是数据流图。

时间: 2024-08-02 06:58:53

.NET 高级架构师0002 架构师之路(1)---面向过程和面向对象的相关文章

.NET 高级架构师0003 架构师之路(2)---架构师的职责

2 架构师的职责 近来看到CSDN上有个CTO俱乐部,里面聊得是不亦乐乎.我怀着无比崇敬的态度,拜读了一下牛人们的发言.里面有个哥们发起一个话题:"CTO, 你多久没有写程序了?".有人回答:"不写代码的CTO,属于......这公司问题大了!".看到这里,我就赶紧撤了,怕忍不住反驳几句,反而遭到牛人们的群殴.试想,一个上点规模的IT公司,还得靠CTO来写程序的话,那是不是才叫问题大了呢.当然,我没有做过CTO,所以我有我的不同看法,而且还愿意表达出来,无知者无畏.

.NET 高级架构师 WEB架构师 ------走正确的路

本人也是coding很多年,虽然很失败,但也总算有点失败的心得,不过我在中国,大多数程序员都是像我一样,在一直走着弯路,如果想成为一个架构师,就必须走正确的路,否则离目标越来越远,正在辛苦工作的程序员们,你们有没有下面几种感觉? 一.              我的工作就是按时完成领导交给我的任务,至于代码写的怎样,知道有改进空间,但没时间去改进,关键是领导也不给时间啊. 二.              我发现我的水平总是跟不上技术的进步,有太多想学的东西要学,Jquery用的人最近比较多啊,听

如何从普通程序员晋升为架构师 面向过程编程OP和面向编程OO

引言 计算机科学是一门应用科学,它的知识体系是典型的倒三角结构,所用的基础知识并不多,只是随着应用领域和方向的不同,产生了很多的分支,所以说编程并不是一件很困难的事情,一个高中生经过特定的训练就可以做得到.但是,会编程和编好程绝对是两码事,同样的程序员,有的人几年之后成为了架构师,有的人却还在不停地coding,只不过ctrl-c.ctrl-v用得更加纯熟了.在中国,编程人员最终的归途无外乎两条:一是转向技术管理,它的终点是CTO:二是继续深入,它的终点是首席架构师,成为CEO的人毕竟是少数.如

系统架构师-基础到企业应用架构-企业应用架构

一.上篇回顾 我们先来回顾下上篇讲解的内容,我们前面的几节分别讲述了,业务逻辑层.数据访问层.服务层.表现层,我们了解了这些分层的职责和分层之间的大概的关联 关系,本篇可能主要是简单的介绍下企业应用的几类模式,结合这几个分层直接的交互来完成系统功能的构建.我们还是先对我们学习的四个分层的职责和功能做个大 概的回顾,我们先来看看下图来回顾下我们讲述的内容. 我想通过上图,大家能回忆起我们讲述的相关内容,然后整理好自己的思路,我们本文将会针对这几个分层进行相应的模式的讲解,并且会结合实例来说明企业应

亿级流量电商详情页系统实战-缓存架构+高可用服务架构+微服务架构第二版视频教程

14套java精品高级架构课,缓存架构,深入Jvm虚拟机,全文检索Elasticsearch,Dubbo分布式Restful 服务,并发原理编程,SpringBoot,SpringCloud,RocketMQ中间件,Mysql分布式集群,服务架构,运 维架构视频教程 14套精品课程介绍: 1.14套精 品是最新整理的课程,都是当下最火的技术,最火的课程,也是全网课程的精品: 2.14套资 源包含:全套完整高清视频.完整源码.配套文档: 3.知识也 是需要投资的,有投入才会有产出(保证投入产出比是

分布式架构之--逻辑架构与物理架构

原文:http://blog.csdn.net/dinglang_2009/article/details/38636151?utm_source=tuicool 在现实开发过程和工作中,我们经常听到“架构设计”和“架构师”这样的名词,它并不神秘,但是却很少有人对“架构”有全面的了解和认识,更谈不上掌握了.事实上,也只有极少数人能成为或者被冠以“架构师”这样的title.为此,笔者总结了实践中对架构的一些理解,希望能够补充很多人对此认识上的不足,纠正一些误解. 架构的分类 对于“架构”来讲,理论

逻辑架构和物理架构

在实际开发工作中,我们经常听到“架构设计”和“架构师”这样的名词,它并不新鲜和神秘,但是却很少有人对“架构”有全面的了解和认识,更谈不上掌握了.事实上,也只有极少数人能成为或者被冠以“架构师”这样的title.为此,笔者总结了实践中对架构的一些理解,希望能够补充很多人对此认识上的不足,纠正一些误解. 架构的分类 对于“架构”来讲,理论上划分了5种架构视图,分别是:逻辑架构.开发架构.运行架构.物理架构.数据架构.根据名字,大家都可能大概能猜到其侧重点和含义. 这里先用通俗的文字简单介绍下,便于大

软件架构设计学习总结(22):软件架构——分层架构、事件驱动架构、微内核架构、微服务架构、基于空间的架构

分层架构 (Layered Architecture) 分层架构是最常见的架构,也被称为n层架构.多年以来,许多企业和公司都在他们的项目中使用这种架构,它已经几乎成为事实标准,因此被大多数架构师.开发者和软件设计者所熟知.比如MVC. 分层架构的一个特性就是 关注分离(separation of concerns) .在层中的组件只负责本层的逻辑.组件的划分很容易让它们实现自己的角色和职责,也比较容易地开发,测试管理和维护. 我们需要这样的冗余,即使业务层没有处理业务规则,也要通过业务层来调用数

架构设计-谈谈架构

1.什么是架构和架构本质 在软件行业,对于什么是架构,都有很多的争论,每个人都有自己的理解.   此君说的架构和彼君理解的架构未必是一回事. 我们主要针对互联网服server系统(类似网站)来定义架构:架构是系统的骨架,支撑和链接各个部分,包括组件.连接件.约束规范,以及指导这些内容设计与演化的原理. 组件:类似应用服务,独立模块.数据库.nginx等等.     连接件:分布式调用.进程间调用.调用使用http协议还是tcp协议.组件之间的交互关系.     约束规范:    定规则做限制:例