可扩展可复用程序的开发之道

Posted freemancwj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可扩展可复用程序的开发之道相关的知识,希望对你有一定的参考价值。

      一直想写一篇综合性的关于软件开发的文章,但是写了很多次都半途而废,儿子放寒假了,想让他学点软件开发基本知识,所以写定决心写了这篇文章,然而并没有写完。 这是一篇给初学者如何开发具有扩展性程序的初级文章,我将用一些代码的例子以及结合自己实际工作中的开发经验来讲解何开发扩展性强的程序。因为水平有限,不会讲得很深入,本文只适合软件开发初学者。

我将分6部分暂定来讲述如何开发扩展性强的软件

第一部分:计算机程序设计发展概述。

第二部分:面向对象开发入门。

第三部分:用数据库设计来应对变化。

第四部分:善用配置文件,但约定优于配置。

第五部分:如何应对UI变化(模块化,组件化以及运用前端框架)。

第六部分:js模块化(面向对象)编程。

一、计算机程序设计发展概述

        “变”是宇宙不变的真理,而“懒”是人类的本性。没有人不喜欢轻轻松松的活着,从某种角度讲,偷懒是人类发明创造的催化剂,人类在工程技术方面的发明创造大都是为了降低劳动强度和难度、减少重复工作、减少工作量、简化工作过程,提高工作效率。

       具体计算机程序设计开发方面。为了应对软件开发过程中的各种问题和变化,自计算机程序开发技术诞生以来,计算机科学技术人员一直在追求怎么多、快、好、省的开发出高质量、高可靠、扩展性好、复用性好,灵活性强的软件系统。为了达到这个目的,几十年来,软件开发理论、编程语言、编程工具、开发技术一直在演化、进步,开发平台、开发框架、设计模式也是一直层出不穷,下面我们就来回顾一下计算机程序设计开发的历史。

 1、机器语言阶段

        最早的计算机程序都是采用机器语言来编写的,我们知道计算机采用的是二进制,信息在计算机中都是用01表示的计算机执行的指令是由01组成的序列,所以机器语言直接使用二进制码来表示机器能够识别和执行的指令和数据。说白了就是直接编写 0 1 的序列来代表程序语言。

机器语言由机器直接执行,速度快,但一个很明显的缺点就是:写起来实在是太困难了,一旦你发现自己写错了,改起来更蛋疼!这样直接导致程序编写效率十分低下,编写程序花费的时间往往是实际运行时间的几十倍或几百倍。

由于机器语言实在是太难编写了,效率实在太低,太容易出错,聪明而又懒惰的人类绝不让这种状况继续存在下去,于是就发展出了汇编语言。

2、汇编语言阶段

       汇编语言亦称符号语言,用助记符代替机器 指令的操作码,用地址符号(Symbol)或标号(Label)代替指令或操作数的地址,。汇编语言由于是采用了助记符号来编写程序,比用机器语言的二进制代码编程要方便些,在一定程度上简化了编程过程。例如 使用 LOAD 来代替 0000,使用 STORE 来代替 0001。即使汇编语言相比机器语言提升了可读性,但其本质上还是一种面向机器的语言,编写同样困难,也很容易出错。

3、面向过程语言阶段

       聪明而又懒惰的人类再一次发挥自己强大的智商,创造出了新的语言,面向过程的语言,面向过程的语言被认为是一种“高级语言”,相比面向机器的语言来说高级语言用近似人类的语言来写程序,然后编译成可执行程序。高级语言编程友好性大大提高。面向过程的语言已经不再关注机器本身的操作指令、存储等方面,而是关注如何一步一步的解决具体的问题,:解决问题的过程简单来说,面向过程编程就是碰到问题就直觉的用计算机能够理解的逻辑来描述和表达待解决的问题及具体的求解过程。相比面向机器的语言来说,面向过程是一次思想上的飞跃,程序员从复杂的机器操作和运行的细节中解放出来,转而关注具体需要解决的问题;面向过程的语言也不再需要和具体的机器绑定,从而具备了移植性和通用性;面向过程的语言本身也更加容易编写和维护。这些因素叠加起来,大大减轻了程序员的负担, 提升了程序员的工作效率,从而促进了软件行业的快速发展。

       典型的面向过程的语言有:BASICC 语言等。web程序员最熟悉的一种前端脚本语言:javascript基本上算是面向过程的语言,虽然它也可以用面向对象的形式开发程序,但开发起来很麻烦,其实是一种模拟,它的语法很多面向对象的特性它都不具备,当然经过多年的发展进化,javascript越来越象面向对象语言,特别是ES6ES6新增了很多的语法,比如支持class关键字等)和众多的优秀的前端框架出现后,javascript已经脱胎换骨。

  面向过程语言其实还可以细分成结构化程序语言和非结构化程序语言一些面向过程语言支持goto语句它可以随意的跳到程序中的任一行代码,导致程序结构不清晰,逻辑混乱,复杂度高,极易出错,被形象的称为面条式代码这种面条式代码导致了第一次软件危机。第一次软件危机最典型的例子 IBM System/360 的操作系统开发。项目共计有2000 多个程序员投入开发,共计花费了 5000 人一年的工作量,写出将近 100 万行的源码,总共投入5 亿美元。尽管投入如此巨大, 但项目进度却一再延迟,软件质量也得不到保障。后来该项目主管布鲁克斯基于这个项目经验而总结的《人月神话》 一书,成了史上最畅销的软件工程书籍。为了解决第一次软件危机计算机科学家提出了结构化程序设计的思想,结构化程序设计的主要特点是抛弃 goto 语句,采用子程序(函数就是一种子程序)、代码区块、for循环以及while循环等结构,来替换传统的goto。希望借此来改善计算机程序的明晰性、质量以及开发时间,并且避免写出面条式代码。结构化程序设计采取“自顶向下、逐步细化、模块化”的指导思想。结构化程序设计本质上还是一种面向过程的设计思想,但通过“自顶向下、逐步细化、模块化”的方法,将软件的复杂度控制在一定范围内,从而从整体上降低了软件开发的复杂度。结构化程序方法成为了1970 年代软件开发的潮流

 4面向对象程序设计

   结构化编程的风靡在一定程度上缓解了软件危机,然而好景不长,随着硬件的快速发展,业务需求越来越复杂,以及编程应用领域越来越广泛,第二次软件危机很快就到来了。第二次软件危机的根本原因还是在于软件生产力远远跟不上硬件和业务的发展,相比第一次软件危机主要 体现在“复杂性”,第二次软件危机主要体现在“可扩展性”、“可维护性”上面。传统的面向过程(包括 结构化程序设计)方法已经越来越不能适应快速多变的业务需求了,软件领域迫切希望找到新的银弹来解 决软件危机,在这种背景下,面向对象的思想开始流行起来。

面向对象的思想更加贴近人类思维的特点, 更加脱离机器思维,是一次软件设计思想上的飞跃。

   面向对象的程序设计通过将现实世界中的事物概念映射到程序设计中的“对象”概念上,现实世界中事物的属性和行为映射到“对象”的属性和方法。程序通过各种对象之间的调用以及协作,从而实现计算机软件的功能。跟很多工程方法一样,面向设计的初衷就是一种处理软件复杂度的设计方法。

   面向对象程序设计可以看作一种在程序中包含各种独立而又互相调用的对象的思想,这与传统的思想刚好相反:传统的程序设计主张将程序看作一系列函数的集合,或者直接就是一系列对电脑下达的指令。面向对象程序设计中的每一个对象都应该能够接受数据、处理数据并将数据传达给其它对象,因此它们都可以被看作一个对象。面向对象有三大特性和五大原则,具体是哪三大特性和五大原则,在后面的面向对象入门部分我会结合例子讲解。

   面向对象开发技术出来以后,衡量一个程序员水平高低的主要标准就是能否用面向对象思想去设计和实现一个软件系统。事实上很多程序员平时工作主要就是 Ctrl+C Ctrl+V, 甚至有很多程序员用 Ctrl+C Ctrl+V这一招干一辈子,这种程序员写代码只为满足功能需求,不求代码的可复用性和可扩展性, 这是非常不好的编码习惯,一个系统里Ctrl+C Ctrl+V用多了,系统里就会有很多重复代码,代码中重复的代码多到一定程度,维护、修改的时候,就是一场灾难。越大的系统,这种方式带来的问题越严重,编程有一原则,就是用尽可能的办法去避免重复很多程序员干了10来年,编码水平没有任何提高。很多码农不要说创新能力,连变动能力都缺乏,变动一个需求就不会写,一定要有别人写好的范例,照葫芦画瓢才会开发,一般也就改改界面,最多也就改改简单的逻辑。

5、互联网时代,基于浏览器以B/S方式架构的web程序给软件开发带了更多的挑战。

   计算机软件诞生以来,很少有一个软件系统开发完成以后不会改变,随着时间的推移,技术的发展,需求的变化等各种各样的原因,软件总是不可能一劳永逸而到了互联网时代,这种变化更加频繁每个互联网程序员都会在自己的开发生涯中,经历了很多的需求变更,重构代码的事情

       互联网时代,基于B/S方式架构的web程序的健壮性,可靠性、可扩展性、兼容性要比传统桌面要求高的多。首先web程序面对的是数以万记的互联网用户,所以对于系统的高并发性、容错性要求很高,其次web程序必须要能满足跨平台,既要能在Pc是使用,还得能在移动端使用,当然浏览器具有天然的跨平台特性,但是是浏览器本身的兼容性却也是一个很大的问题。web浏览器少说都有十多种,这些浏览器的兼容性并不好,而且每个浏览器自身又有无数版本,大部分版本还不兼容,这种情况在几年以前非常糟糕,web程序都得兼容,至少得兼容几大主流浏览器。以前的web程序要想满足PC端和移动端浏览器不同的宽度,必须得设计两套页面和样式,直到后来出现了html5,css3技术以及响应式的、跨平台的网页开发框架(比如Bootstrap等)才解决了这个问题,移动端既要能在安卓系统浏览,还得能在ios系统是浏览。为了应对互联网领域快速的需求变化十多年前兴起敏捷开发,它采用小步快跑,快速迭代,快速上线,听取用户反馈然后快速改进,以随时应对变化的方法来开发软件系统,摈弃传统开发中的等一切设计完美、写好面面俱到的文档然后才开始开发的方式。因为需要随时应对变化,所以敏捷开发经常对开发出来的系统的可扩展性和应对变化的能力要求很高。

       web程序开发技术在过去一二十年经历非常快速而剧烈的变化,各种技术此起彼伏,方兴未艾。web程序可以采用各种技术组合来实现,尤其是前后端技术组合可以非常灵活,实现同一个web程序可以采用的技术和框架组合估计10个手指数不过来。首先,web开发平台就数不胜数,开发语言就更是五花八门,架构方式、开发框架更是多于牛毛,各种前后端框架层出不穷,简直就是乱花渐入迷人眼面向对象以后,最新兴起的架构技术也有很多,比如领域驱动设计、微服务架构等等,因为本人水平太低,对这些高级技术没有入门,平时工作也很少用到,没有资格讲解,就不献丑了。

二、面向对象编程入门

   前面我们已经概述了面向对象编程并且提到面向对象编程有三大特性和五大原则。下面我们具体的来谈一谈:

三大特性:封装、继承、多态。

五大原则:单一职责原则开闭原则里氏替换原则接口分离原则依赖倒置原则面向接口编程),多用组合,少用继承原则。

先来谈谈三大特性:

   上面说的太抽象,我们用现实生活中的例子类比来说明:我一直觉得印刷术的发展过程最能体现面向对象程序设计思想诞生的过程,印刷术发明之前,文章书籍全靠手抄,每多出一本书就要多抄写一次,相当于机器语言时代雕版印刷术的发明大大减少了这种枯燥繁重的重复劳动,雕版相当于简单的封装,一个雕版是一个对象,但是这个对象的粒度太粗,雕版印刷术的一个雕版只能印刷一篇文字,换一篇文字又得重新刻一个版,一本书每一页都需要刻一个版,有多少页就需要刻多少个版,每个版的都是独立、没有关联的,每个版的文字只能属于这个雕版,无法复用,而且一批书印完,这些版就作废了新印一本书又得重新刻版,最让人无法忍受的是只要刻错一个字,整个雕版都废掉了显然,雕版印刷的问题就在于没有把单独的汉字抽象出来,而是把所有的字都刻在同一版面上耦合度太高不能灵活调用,也不能复用,而活字印刷术把一个个的文字单独做成模型,降低了耦合度,极大的提高灵活性,字模可以拼合成任意的文章,提高了应对变化的能力。雕版印刷相当于面向过程编程,而活字印刷相当于面向对象编程,活字模型相当于面向对象中一个个可复用的类、方法等等,它蕴含的思想跟面向对象分析设计编程思想是相通的。

再来谈谈五大原则:

   如果要在这些原则里面选一条最重要的,毫无疑问我会选单一职责原则,这个原则的本质就是我们的设计和实现的对象和实体在各自的概念层次上面都应该是高内聚的。我认为单一职责原则并不是面向对象设计才有的原则,它的适用性非常广泛。我理解的单一职责原则是这样的,对于一个层次上的抽象对象,它只表达或者负责一个这个层次上的概念。比如一个方法只负责单一的行为,一个类只表示单一的概念,一个模块只负责这个模块所表示的单一概念的属性和操作,一个子系统只负责属于这个子系统概念边界内的流程;在面向过程的设计中这个原则同样适用,比如分层模型中一个层只负责这个层的功能并且与上下层的边界要划分清楚。所以说单一职责原则在设计和实现的过程中都具有很广泛的适用性。

   开闭原则指的是软件对象实体应该对扩展开放对修改关闭。在需求变动的时候,最好的不需要对原有的设计和代码做改动,而是增加一些类就可以满足需要。 要做到开闭原则,1.抽象,恰当的抽象才能将逻辑或者对象抽象成为可复用和易扩展的组件。2.封装变化,预先将可预测的变动点进行封装抽象,从而可以不修改已有逻辑。

里氏替换原则,一个子类可以替换他们的父类。即子类应该拥有父类的所有操作,实现IS-A的关系。

依赖反转原则,也就是面向接口编程。具体的说一个类依赖的属性尽量不要直接依赖具体的实现,而是依赖接口或者是abstract类。这样更容易解耦,从而实现OCP

   优先使用聚合或组合关系复用代码。 类与类之间简单的关系有Is-AHas-AUse-A,对应着继承,关联和依赖。而他们的耦合关系是继承>关联>依赖。而且使用继承的时候尽量要保证子类与父类之间是Is-A关系。所以尽可能使用聚合关系,除非它们真的适用继承关系。

这么说可能还有些抽象,下面我们看一个用面向过程方式写的程序,然后分析一下它到底有什么坏处

下面的代码是一个简单的计算两个数加、减、乘、除的控制台程序:

未完待续……????

以上是关于可扩展可复用程序的开发之道的主要内容,如果未能解决你的问题,请参考以下文章

00-五个原则

软件构造 第五章第一节 可复用性的度量形态和外部观察

python简单工厂模式解析

规划可扩展的 Web 应用程序开发

三软件设计原则

规划可扩展 Web 应用程序的开发