180 lines
35 KiB
TeX
Executable File
180 lines
35 KiB
TeX
Executable File
% !TEX root = main.tex
|
||
|
||
\section{引言}
|
||
|
||
软件\index{软件}是以计算为核心手段实现应用目标和价值的解决方案。软件科学是以软件为基本研究对象的人工科学(或曰“人工物科学”,Science of Arti-ficial);软件工程则是基于软件科学原理进行软件开发的工程。软件学科,或曰软件科学与工程,是指在研究、开发、维护以及使用前述含义下的软件所涉及的理论、原则、方法、技术所构成的学科。在方法论的意义上,软件学科构成整个计算机学科的主体部分,并与系统、控制以及经济、社会等相关学科交叉融合。从1966年首届图灵奖至2018年的53次颁奖中,属于软件领域的有37次(69.8\%),其中以程序设计语言、编译和操作系统为主获奖的有22次获奖,还有4次数据库获奖。作为本书第一部分的开篇,本章将简要回顾软件和软件技术的发展历程,通过梳理软件发展脉络,总结软件学科的基本内涵、关键问题、研究方法和发展规律,为第二部分学科发展战略提供基础。
|
||
|
||
\section{软件发展简史}
|
||
本节我们试图从 “编程”表达解决方案和 “抽象”实现复杂性控制两个基本视角简要回顾软件发展历史,为下节讨论软件学科发展基本规律提供背景。
|
||
|
||
\subsection{人力/机械计算时代}
|
||
程式化的计算是人类思维的基本形式之一。如果我们广义地理解“计算”,软件的历史可以追溯到很久以前。人类历史上最早的计算设备是中国算盘,其算法口诀可视为一种程式化计算的规则。到东汉年代,提花机(参见图\ref{fig:1-1})的设计中蕴含了用编程方式编织特定图案的思想。类似的设备晚至1805年才在欧洲出现,即所谓Jacquard‘s Loom(参见图\ref{fig:1-2})。1842年人类的第一位程序员Ada Lavelace为Babagge的分析机写了第一个程序,功能是计算Bernoulli数(参见图\ref{fig:1-3},\ref{fig:1-4})。可见早在机械计算时代,可编程的思想已经萌芽。
|
||
|
||
\begin{figure}[htbp]
|
||
\centering
|
||
\begin{minipage}[t]{0.48\textwidth}
|
||
\centering
|
||
\includegraphics[width=5cm]{fig1-1/1-1.png}
|
||
\caption{提花机}
|
||
\label{fig:1-1}
|
||
\end{minipage}
|
||
\begin{minipage}[t]{0.48\textwidth}
|
||
\centering
|
||
\includegraphics[width=5cm]{fig1-1/1-2.png}
|
||
\caption{Jacquard‘s Loom}
|
||
\label{fig:1-2}
|
||
\end{minipage}
|
||
\end{figure}
|
||
|
||
\begin{figure}[htbp]
|
||
\centering
|
||
\begin{minipage}[t]{0.48\textwidth}
|
||
\includegraphics[width=5cm]{fig1-1/1-3.jpg}
|
||
\caption{Babagge分析机}
|
||
\label{fig:1-3}
|
||
\end{minipage}
|
||
\begin{minipage}[t]{0.48\textwidth}
|
||
\centering
|
||
\includegraphics[width=5cm]{fig1-1/1-4.jpg}
|
||
\caption{Babagge分析机的第一个程序}
|
||
\label{fig:1-4}
|
||
\end{minipage}
|
||
\end{figure}
|
||
|
||
|
||
Computer一词历史上出现在1613年,用来指完成演算或计算的人员。这种说法一直到19世纪末后工业革命产生了主要目标是用来演算的机器为止\footnote{https://www.computerhope.com/issues/ch000984.htm}。著名的哈佛大学天文台在1877年至1919年期间雇佣了一批妇女作为处理天文数据的技术工人。在电子计算机出现之前的人力和机械计算时代,Mathematic Tables项目是最大最复杂的计算项目,组织这类项目的关键就是编程的基本思想。Gertrude Blanch女士作为“数学的导演”和“计算的经理”,设计了人力计算团队执行的“算法”。这些算法和错误检测的设计思想作为超越函数的计算标准延续了数十年。逐渐地,也出现了表达编程描述形式和记号,例如1921年Lillian和Frank Gilbreth的过程图(Process Charts,参见图1-5),与后来的程序流图十分类似;又如1940年IBM的W.J. Eckert提出的打孔卡(参见图1-6)。我们可以看到,计算和编程是紧密相关的,而编程的结果事实上是给出了一种计算应用(数学计算)的解决方案,它可以由人力计算或机械计算完成。然而,在人力/机械计算时代,还未形成通用计算和编程的思想。
|
||
|
||
|
||
\subsection{电子计算时代}
|
||
上世纪四十年代出现了电子计算机。计算机先驱们相继研制了Colossus(1943)、ENIAC(1946)、EDSAC(1949)和Mark I(1949)等计算机。EDSAC作为第一台存储程序结构的电子计算机打开了通用计算的时代。此时的程序是通过一种微开关的形式加载到机器硬件上的。到五十年代后,才出现了用户和计算机之间的简单交互。Grace Hopper在1951年和1952年为UNIVAC I编写了A-0系统,这是第一个电子计算机的编译器。从今天的角度看,A-0更像现代编译器概念的Loader或Linker,但可以认为是第一个系统软件。UNIVAC I的程序由一组子程序和参数序列组成。两年后,A-2系统成为了第一个开源软件。早期的驻留管理程序将程序从纸带或者穿孔卡上读入到计算机中进行加载,这种技术直接形成了历史上第一个商用操作系统,即1956年推出的IBM 704的操作系统。五十年代后,人们开始意识到1936年提出的图灵机模型的理论意义,图灵机由此成为计算机科学发展的理论基础。通用图灵机和通用计算使人们进一步认识到可编程是计算的基本属性,人们通过编写程序使得计算机完成指定的任务。
|
||
|
||
\subsection{软件和软件工程的出现}
|
||
“软件”一词最早出现在1953年兰德公司R.R. Carhart的报告中,用来说明讨论可靠性时与硬件相对应的“人因”。而人们现在通常理解中的“软件”这一术语来自John W. Tukey在1958年所发表的论文。文中指出 “软件由精心编写的解释程序、编译器和自动编程等组成,它们至少像电容器、晶体管、电线和磁带等现代计算机硬件一样重要”。1968年,或许是巧合,出现了两个软件发展史上的重大事件。这两个事件的背景都与IBM著名的IBM S/360系统相关。
|
||
|
||
第一个事件是软件与硬件的解绑。早期的软件依附在硬件之上解决应用问题,此时的计算机系统中硬件和软件是相互捆绑的。所谓“捆绑”,是指计算机公司(如IBM)在收费上采取只考虑硬件价格而软件和系统服务免费的策略。这在当时对于用户是很有吸引的,也增强了公司的竞争力。到1964 年时情况发生了变化,IBM发布了新的IBM S/360系统,希望能够升级硬件系统而不需要替换或改变用户的应用程序。而稍后RCA也宣布了其新的Spectra 70系统与IBM S/360兼容。这使得IBM难以阻止RCA在市场上“免费”使用IBM的软件。1968年,IBM宣布了其软件和硬件系统的解绑,改变了软件的商业和竞争模式。自此软件从计算机系统中与硬件的剥离,获得了可以独立发展的空间。可以看到,除了商业上的反垄断和市场竞争因素外,软件本质上所具备的“解决方案”的独立性和计算平台抽象使得解绑具备了历史必然性和技术可行性。自此,人们逐步认识到软件是计算机系统的灵魂,它向下管理计算机系统的各类资源,向上满足用户对计算机系统的应用需求。
|
||
|
||
第二个事件是软件工程\index{软件工程}的提出。计算机能力的快速提高和软件复杂性增加导致了所谓的“软件危机”现象,例如,IBM S/360的操作系统OS/360的进度、开销和可靠性均不尽人意。北大西洋公约组织(NATO)在1968年举行了首次软件工程会议。在这次会议上,专家们首次提出需要与其他领域的工程方法一样系统化地进行软件开发。正如Margaret Hamilton在开发阿波罗在轨飞行和导航系统项目中所明确指出的,“我努力使软件具有应有的地位,使得构造软件的活动受到应有的尊重,因而我开始用‘软件工程’将其与硬件和其他类型的工程区分开来,成为整个系统工程的一部分”。软件工程的出现激活了软件发展的巨大活力。这一史实也提示了软件发展的外在驱动力,即不断增长的应用需求和计算能力。
|
||
|
||
|
||
\subsection{软件发展的主线}
|
||
追溯软件发展可以有多条线索,既可以考察计算机系统平台、应用和计算形态的发展,也可以采用程序设计语言、系统软件、软件开发方法等角度。从应用需求看,软件从军事计算需求起步,逐步从商业计算、个人计算、网络计算、云端计算、到如今泛在计算;从计算平台看,从主机时代、微机时代、互联网时代到人机物融合时代,计算设备的多样性、能力、范围不断扩展。相应的,为更好地面向需求,满足各类质量、进度和成本约束,软件的语言从机器语言、汇编语言、高级语言、发展到领域语言,软件开发方法从结构化方法、对象化方法、构件化方法、服务化和网构化方法到智能化方法,系统软件平台从批处理、交互式、网络化、云边端融合系统软件。
|
||
|
||
软件作为问题解决方案,其结果是对认知空间中的概念的表达。Sapir-Whorf的语言相对论假设对语汇的重要性给出了一个表述。其较弱的版本称为语言相对论,是指语言影响思维与决策;而较强的版本称为语言决定论,则是指语言决定思维与认知边界。认识软件的切入点是认识各种软件抽象。它们构成了软件的语汇,包括但不限于程序设计语言设施、软件构件、软件服务等。宏观地说,软件方法学的核心是建立(一般的)软件抽象,而系统软件的核心在于实现这些抽象,软件工程则使用这些抽象构造应用软件。不同层次的抽象、抽象的计算实现和使用组成了软件发展的脉络。我们试图以软件各种抽象为主线来梳理和汇聚软件发展的基本历程。
|
||
|
||
从最初计算机系统上的机器指令开始,人们不断地在建立新的抽象,例如:汇编语言中的宏指令抽象定义了具有宏名的一段汇编语句序列;结构化高级语言提供了数据结构抽象和过程抽象;面向对象语言提供了类和继承抽象;构件化方法中的构件抽象;服务化方法的服务抽象;以及网构化方法的主体抽象;智能化方法语言中的学习赋能抽象等等。语汇抽象之间的关系与软件定义栈呈现一个垂直方向的对应关系。例如,在典型的大数据处理系统(如Google搜索引擎)中,我们可以看到接口与服务、方法与设施、虚拟化与实现等不同层次组成的抽象栈,它们分别对应着Web服务、MapReduce、Dryad、Pregel、BigTable、集群调度、分布式文件、操作系统等抽象层。
|
||
|
||
以程序设计语言和相应程序接口为基础,形成了软件的基本抽象。与数学抽象不同,软件抽象是可编程的单元并有计算之实现。围绕这些抽象软件学科的发展呈扇形展开,分化出以建立抽象为主要内容的软件方法学和程序设计语言;以实现抽象为主要内容的系统软件;以使用抽象为主的软件开发和工程。参见图\ref{fig:1-5}。
|
||
|
||
% word中未指明具体标题和图片序号??
|
||
\begin{figure}[htbp]
|
||
\centering
|
||
\includegraphics[width=0.80\textwidth]{fig1-1/1-5.jpg}
|
||
\caption{}
|
||
\label{fig:1-5}
|
||
\end{figure}
|
||
|
||
\begin{itemize}
|
||
\item 从软件抽象的角度看程序设计语言与软件工程的发展互动
|
||
\end{itemize}
|
||
|
||
军事和科学计算是计算应用的最初需求。面向科学计算建立的抽象成为软件发展的早期里程碑。为了满足数值计算的需求,John Backus于1953年发明了Fortran语言,是历史上第一个正式推广的高级程序设计语言,于1957年在IBM 704计算机上实现。Fortran语言提供的抽象对用数学公式表达的问题求解提供了直接支持。经过多年的版本更替,Fortran语言至今仍在使用。Fortran的主要贡献者获得了图灵奖。1960年,面向常规商业信息处理,COBOL语言发布,成为COBOL-60。COBOL提供了面向周期性循环处理和数据变换的抽象,适合于报表、情报、计划编制等商业数据处理,如今仍有应用。同一时间段,面向通用计算的算法语言ALGOL 60诞生,成为ACM当时算法描述的标准,它提供了数据结构、块结构、递归等设施。ALGOL语言的意义重大,一是它确立了结构化高级程序设计语言设计的基础,之后的Pascal、C、Java等强制式程序设计语言的基础;二是它催生了试图严格或形式化定义语言和程序的一大批软件基础理论成果。ALGOL 60的主要贡献者Peter Naur获得了2006年图灵奖。60年代末至80年代,历经Simula 67、Smalltalk、C++等语言,面向对象程序设计范型形成,提供了类、对象、方法、消息传递、继承等设施,建立了封装、抽象和多态等机制。面向对象语言的创立者也获得了图灵奖。与强制式程序设计语言不同,50年代末人们还探索了声明式程序设计语言,其代表是基于Lambda演算的函数式语言LISP。它提供了用于问题求解的函数抽象,首次在语言中支持递归函数定义。LISP的设计思想深刻地影响了ML、Haskell等函数式程序设计语言的发展。随着人们对程序设计安全可靠、便捷有效等需求的提高,以及计算平台向并发、分布、异构发展,程序设计语言呈现了两方面走向:一是,程序设计范型的融合,例如面向对象语言和函数式语言的融合并支持并发、安全计算,出现了Scala、Rust等程序设计语言,展现了强劲的势头;另一方面是,面向特定领域的语言受到了重视,它们针对领域应用提供高效便捷的抽象,例如面向大数据处理的Map Reduce面向区块链智能合约的Solidity。
|
||
|
||
60年代末软件工程思想的出现,使得人们认识到如何面向应用建立软件开发方法和软件工程模式的重要性。软件开发方法中的诸多抽象大多来自于程序设计语言的思路。例如,70年代的结构化系统分析和设计方法、80年代的面向对象分析和设计、90年代基于构件的软件工程、新世纪的面向服务/网构化的软件工程等等。软件开发和程序设计在抽象上尽可能地保持了一致或相容,使得软件工程模型不同阶段、不同层次的抽象有着较好的对应。
|
||
|
||
程序设计语言向上要面向问题求解方法的表达,向下要在计算机系统上实现。围绕语言的语法、语义和语用等方面的程序理论和问题求解的计算理论成为了软件理论的重要部分。从ALGOL60开始,关于程序理论的研究就开始了,其基本内容是在计算理论的基础上建立程序的形式语义,并对程序及其性质进行推理,本质是基于数学的方法来建立抽象及抽象之间的联系。在60年代到70年代,人们建立了程序设计语言的操作语义学、公理语义学、指称语义学和代数语义学。程序语言与形式语义的研究紧密联系,例如,1974年Barbara Liskov提出了抽象数据类型的程序设计思想,建立了现代面向对象语言的核心特征,包括强类型检查和通用类型支持,支持了对象化方法语言中的类抽象。以形式语义学为基础,人们长时期探索程序的形式开发和形式验证等形式化方法和技术以提高软件生产率和软件质量,取得显著的进展,例如模型检验获得了2005年图灵奖。与程序相关的问题的求解判定和算法复杂性也成为程序设计语言设计和形式化方法的重要内容,例如Gradual类型的引入。
|
||
|
||
\begin{itemize}
|
||
\item 从软件抽象的角度看系统软件与软件工程的发展互动
|
||
\end{itemize}
|
||
|
||
随着硬件能力快速提高,以编译器和操作系统为代表的系统软件成为建立抽象、使用抽象来实现更高级抽象的焦点。事实上,程序设计语言中许多重要概念来自于编译器和操作系统的设计。John Cocke在解决上下文无关语言的有效扫描中发明了动态程序设计范型,而Floyd为了构建层次化自顶向下的扫描器发明了递归协程序作为抽象结构。Floyd希望能发现语言支持的新范型(抽象)。这说明了抽象是用来支持相对应的设计方法,也就是问题求解的方法。
|
||
|
||
到六十年代,集成电路的兴起增强了计算机的能力,操作系统出现了不少新技术并变得强大复杂。典型的技术有多道程序设计、分时、实时、多处理器技术等等。70年代,操作系统的设计进一步发展,形成了UNIX操作系统,成为当今主机操作系统的基础。80年代,商业计算和微处理器时代到来,出现了一批微机和工作站操作系统,代表的是MS-DOS,Linux、Solaris 和Windows等。90年代,随着计算机网络和网络就是计算机的推动下,在主机和微机操作系统的基础上,中间件或网络化操作系统逐渐成为系统软件的新的增长点。进入新世纪后,以iOS和Android代表的移动操作,和主机操作系统向数据中心扩展的云操作系统形成了云端计算的软件基础设施的基本格局。
|
||
|
||
操作系统中的三个基本元素是抽象、机制和策略。而其抽象的基本设计原则是机制与策略的分离、共性的沉淀。典型的例子有进程和进程管理、线程和并发、调度、内存管理、进程间通信、I/O管理、虚拟化、分布文件系统、分布共享内存、安全与隐私抽象-Ownership等等。在实现这些抽象的过程中,人们发现并设计了计算求解的复杂性应对的原理和法则,例如局部性原理、名字映射、分而治之、信息隐藏等等。与实现抽象密切相关,系统软件与计算平台的演进紧密相关,例如在网络化时代,操作系统的API是网络操作的API,而在云边端的时代,操作系统通过协议软件、RPC等来集成。Barbara Liskov讨论了系统、语言和抽象的关系,指出抽象对系统组织的作用,例如用进程和软件层次来组织复杂系统。为了应对操作系统设计中可靠性、安全性、可配置、可扩展和多处理器程序设计等挑战,微软的Singularity OS的首要任务开发新的抽象,包括平台的抽象指令集、操作系统和应用统一可扩展的体系结构和一阶的应用抽象。特别的是应用抽象递归的应用到操作系统自身,包括内核和其他OS构件。Singularity OS的后继Midori OS支持了微软西海岸和亚洲的自然语言搜索服务。Midori表明了合理的抽象和软件栈能在内存、类型和并发安全之上构建系统和应用,性能和安全并不是对立的。
|
||
|
||
回顾软件学科发展,在认知空间中,人们一方面不断的建立抽象,一方面不断的在计算平台上实现抽象,两者相辅相成,螺旋上升;与此同时使用抽象的方法和对高层抽象的需要促进了软件开发方法和技术的发展。例如,结构化程序设计开创了程序设计得到的程序具有良好的结构,在这个指导思想下,问题求解可以看作是一系列的分解过程,即从一个较高层的过程,初步的加入细节得到较低层的抽象,从而完成整个程序。逐步精化和层次化的程序结构是结构化程序设计的基本原理。在结构化程序设计的基础上,当程序员在某个抽象层次上使用下一层次提供的抽象时并不需要考虑底层的实现细节。然而高级程序设计语言不可能以内嵌的方式提供问题求解需要的所有抽象,需要一种方式可以从内嵌类型构造不同层次抽象的能力。这些动机促使了抽象数据类型的出现。抽象数据类型用抽象对象上一组操作的方式定义了该类抽象对象,即用类型上的操作来定义新类型。它一方面封装了底层操作抽象的细节,又构造了一组新的类型抽象。如图,结构化抽象与THE OS、C与UNIX、面向对象与CORBA和EJB、服务化与Docker虚拟机交相辉映,形成了以计算为手段的解平台提升,并与结构化、对象化、构件化、服务化等软件开发方法携手同行,成为人工科学边界物的基础。
|
||
|
||
软件发展的核心是管理复杂性。从平台空间到应用空间的认知与问题求解鸿沟是作为解决方案的软件来提供或弥补的,相应的软件形态也在逐步的演变丰富。在计算机诞生后五十年中,软件的表象发生数次变化。从早期的“程序=数据结构+算法”的初级抽象,到“软件=程序+文档”,结构化程序设计关注在于管理结构复杂性。进入网络化时代后,交互复杂性和规模复杂性日益突出,体系结构加设计模型抽象、服务加组合抽象为管理这些类复杂性应运而生。进入大数据时代后,知识复杂性和领域复杂性需要纳入软件,软件在程序加文档的基础上需要抽象知识、数据和能力。软件的发展从微观上看,从40年代到60年代解决基础问题,到80年代管理结构复杂性为主,到本世纪初管理交互复杂性为主,到近来以管理异构、互联的规模复杂性和社会技术复杂性。建立、实现、使用抽象的循环迭代不断往复,推进着软件技术的发展。
|
||
|
||
抽象是从制品的角度来认识、构造和演进软件。而软件作为人类的智力产品,与这条主线相配合,组织和管理制品在生命周期中的过程复杂性是极为重要的,也构成了一条与抽象相配合的辅线。它的演进与软件的应用、平台和认知空间的演进互联互动,从早期的作坊式生产组织方式、企业化生产组织方式发展到网络化智能化时代的社会化生产方式。企业化生产组织方式主要有软件过程(1970)、CMM(1988)、SCRUM(1995)、RUP(2000)和外包(2001);社会化生产方式有开源(1997)、Git(2005)、Stack Overflow(2007)和DevOps(2008)。
|
||
|
||
|
||
|
||
\section{软件学科的内涵、发展规律和基本架构}
|
||
\subsection{内涵与学科特征}
|
||
软件作为计算平台上实现应用价值的解决方案,是最纯粹的人工制品,其内涵特征包括了三个方面:
|
||
\begin{itemize}
|
||
\item [-] 功能性:以何种结构和行为
|
||
\item [-] 目的性:达成什么应用目的
|
||
\item [-] 适应性:何种环境依赖之下
|
||
|
||
\end{itemize}
|
||
|
||
软件学科是以软件为研究对象,研究设计和使用软件及其规律的学科。其核心内容是以计算为工具的问题求解方法论,目标是达成效能、效率和价值的统一,知识体系包括了理论、方法、工具、环境和生态。N. Wirth在“软件工程简史”一文中指出 “如果说我们能从过去学到什么,那就是计算机科学本质上是方法论学科。它开发并教育在广泛不同应用的共性受惠的知识和技术”。我们认为,在这个意义上,软件学科实质上就是Wirth所说的计算机科学的主体。之所以我们使用了软件科学,是因为有了时代的扩展(参见第二篇引言)。
|
||
|
||
软件的功能性、目的性和适应性,使得软件学科呈现出了艺术、科学和工程共存的学科特征。这源自于软件本身融合了人类活动、数学物理规律约束的计算模型和装置、以及面向应用价值的工程设计。例如,软件的算法设计是艺术,而算法分析是科学;程序设计是艺术,而程序正确性是科学;进一步软件开发是工程,而软件分解与抽象及其正确性是艺术与科学。软件之目的性是其工程属性的来源,而功能性的设计及设计的柔性孕育了多样的艺术性,软件最终运行的计算平台的物理和自然属性内生了软件发展遵循的科学规律。而艺术、科学和工程在软件发展的不同阶段和侧面会相互渗透乃至相互转换。归根到底,其目的性表征的价值、软硬平台与外部环境所形成的功能及界面适应性是其核心,也形成了软件成为万能集成器和粘合剂的基础设施地位。而这一特性,也形成了软件作为核心的不同层次栈组成的计算载体,包括语言、平台、结构和框架。
|
||
|
||
\subsection{发展的基本规律}
|
||
随着网络时代的到来,软件网构化和服务化,解耦和绑定的周期性出现,驱动力主次的周期性变化,使得软件方法和技术体系的变化成为常态,正所谓“变是不变的真理”。我们从两个方面来认识软件学科发展的规律:第一,本学科发展的驱动力是什么?第二,本学科的研究方法论是什么。
|
||
|
||
\subsubsection{发展的驱动力}
|
||
软件是兼具刚性约束和柔性适应的产物。平台和应用目的可计算、复杂性和正确性形成了软件需要遵循的刚性约束,而内在的各种方法学引导、功能和适应性设计则造就了软件的柔性多样,也给予了软件学科无穷的发展活力。作为人工制品的界面物属性,软件学科发展的外部驱动力来自于两个方面:外在驱动力来自于不断增长的应用需求和不断增强的计算平台;内在驱动力来自于其核心问题的解决,即软件的效率、质量和成本,即提高软件生产率、保障软件质量、降低软件成本,以及不断发展的人本属性,包括人的认知规律和人力资源管理的深化与提高。
|
||
|
||
\textbf{外在驱动力}
|
||
|
||
回顾软件发展的历史,可以看到软件学科发展的外在驱动力主要来自于两个方面。第一个方面是来自于计算平台的发展,简称平台驱动力;第二个方面是应用需求的增长,简称应用驱动力。平台的变迁形成了软件所依赖的平台空间;而应用的增长形成软件所解决的问题空间。在平台空间和问题空间之间,形成了软件作为界面物所需具有的功能、目的和适应形成的认知空间。软件的发展是这三个空间变化、渗透和互动的产物。
|
||
|
||
应用和平台的诉求,应用拉动,平台提高,推动软件的发展。从应用驱动力的角度,软件的应用范围不断扩展,渗透力不断增强。不断增长的应用诉求拉动了软件技术从早期的科学计算应用,扩展到了等各类不同应用,软件学科的无可比拟的渗透力变得空前的强大,软件的形态、开发方法和运行形态等诸多方面发生了巨大的变化。从平台驱动力的角度,计算平台从von Neumann计算机到网络就是计算机、从端网云是计算机到全球泛在计算,形成了从封闭、静态环境(单机计算平台)到开放、动态环境(网络计算平台)的态势,造就了软件发展的不竭动力,使得软件所能提供的解决方案的解空间更趋科学、高效。在应用驱动力和平台驱动力的联合作用下,软件正走向“定义一切”。
|
||
|
||
\textbf{内在驱动力}
|
||
|
||
作为计算平台上问题解决方案的方法论,软件学科需要阐明一些基本问题,这些基本问题的解决支撑了软件学科发展,即:可计算性理论,解决问题能不能在计算平台上求解的问题;算法设计与分析,解决问题能不能在计算平台上高效能行求解的问题;软件方法和技术,解决问题能不能有效控制复杂性;软件基础理论,解决软件能不能可信的问题。前两个问题解决问题的能行求解;第三个问题解决复杂性的工程控制方法;第四个问题评价获得的解是否符合应用价值取向,达到目的。我们认为,作为问题求解的方法学,提高求解效能(单位成本的软件生产率和软件质量)是软件发展的内在驱动力,而基于抽象的复杂性控制成为学科发展的核心要素。
|
||
|
||
从技术角度看,灵活、可变、适应性是软件不变的需求。软件在语言上追求更具表达能力;在方法上符合人类思维、易构造、易维护;在系统上更高效可靠。围绕抽象和复杂性控制,软件学科形成了从模式化、形式化、自动化到智能化的基本手段,由软件结构、开发结构和组织结构组成的工程模型走向开放化。
|
||
|
||
\subsubsection{学科方法}
|
||
|
||
从研究的角度,软件学科需要建立构造并在计算机上运行问题解决方案的科学和工程基础。从应用的角度,我们需要建立开发软件制品的方法和过程来高效和节约地构建软件系统。在软件学科中,基本方法可以归为三类,即理论方法、实验方法和设计方法。
|
||
|
||
\textbf{理论方法}
|
||
|
||
理论方法首先给出对象的定义描述,并假设它们之间可能的联系,通过证明来判断这些联系是否成立,并解释所得到的结果。源于以图灵机为代表的形式化计算模型的奠基性贡献,使得计算平台伊始便具有刚性的数学理论约束,使得数学天然地进入了计算机理论研究。通过建立形式理论、推理获得结果并解释结果,形成了软件作为数学对象来研究和开发的方法学。这种方法提供了开发模型和理解模型边界的分析框架,在软件正确性方面发挥了重要作用。理论方法根植于数学,将计算视作数学对象开展研究。
|
||
|
||
\textbf{实验方法}
|
||
|
||
实验方法或者建模属于实验科学方法。它首先形成基于假设构造一个模型,开发统计/量化方法,应用到案例上,度量和分析,来确认所提出的模型。这种模式是一种变革性的改进,例如提出一种新的方法和工具来完成软件开发。仅仅提出一种方法还不够,需要有度量和分析的方法来说明方法和工具较已有方法的先进性。实验方法根植于自然科学方法,源于科学假设,系统建立模型,验证并确认这些假设。与其他科学方法类似,实验手段中计算手段的引入使现代实验方法有了新的途径。对于软件科学的研究来也是这样,可以利用计算的手段开展软件的实验研究,包括用软件模拟软件的模型方法和用数据科学方法来研究软件及其环境的现象和方法。
|
||
|
||
\textbf{设计方法}
|
||
|
||
自然科学中理论方法和实验方法之外,人工科学的特有方法是设计方法,它着眼于为了解决一个问题来工程化构造一个软件。它的基本过程是表述需求、表述规约、设计和实现系统并测试系统。设计中不断对已有的软件解决方案观察,提出更好的解决方案,建立/开发、度量和分析,重复直到难以改进。这种模式是一种演进改进的方法,是一种模型改进的方法,关键在于仔细的分析和度量。设计方法根植于工程,源于面向问题,通过系统的设计过程来构造解决方案。
|
||
|
||
软件科学构成了人工科学的基础。其核心是模型抽象。以模型为数学对象,形成了软件学科的理论方面;从软件到软件模型,形成了软件学科的科学方面,从软件能否构造一个符合该软件系统的模型,并对软件开展预言;从问题、软件模型到软件,形成了软件科学的工程方面,面向问题获得求解模型并构造一个符合该模型的软件系统。上述三个方面在软件科学的研究中并不是正交的,往往会联合在一起共同解决学科问题。它们各自具体不可替代的作用,理论方法描述和揭示软件模型及对象之间的联系,实验方法可以运用这些联系来预言软件行为并与现实世界比较,设计方法则是通过这些联系的科学发现来设计完成解决方案。这三者的紧密联系也使得软件科学区别于数学、自然科学和传统工程科学。
|
||
|
||
\begin{itemize}
|
||
\item \textbf{举例}:基于大代码的软件自动生成方法就综合软件科学中的理论、实验和设计方法。程序综合是计算机科学的明珠。其理论研究是长期以来的科学问题。演绎推理的理论方法是其重要途径,形式规约开始构造一个正确的程序,自动定理证明和归纳综合是其基本思路,并逐步发展到了归纳推理。近来随着海量代码的累积,实验统计的方法逐步兴起,以实验方法从代码数据中学习,建立程序综合和推理的启发式预言有效地提高了综合效率。以归纳推理和统计推理相结合的程序综合设计方法成为了当前软件自动化研究的重要趋势,在代码自动生成、代码修复、人机协同编程等方面取得了重要进展。
|
||
|
||
\end{itemize}
|
||
|
||
\subsection{软件学科的基本架构}
|
||
出于不同目的考虑,学科可有不同的划分。从目前我国人才培养一级学科划分看,软件学科横跨了计算机科学与技术,软件工程、网络空间安全等三个一级学科。特别是,与计算机软件与理论二级学科和软件工程一级学科关系密切。与本国际本科计算教育学科相比,软件学科横跨了ACM/IEEE计算教程等五个学科,即计算机科学、计算机工程、软件工程、信息技术、信息系统。它们的覆盖关系如图1-X所示。
|
||
|
||
我们着眼于软件学科发展历程的回顾,重新梳理,就现状划分了三个子领域,即程序设计语言与理论、系统软件、软件工程。其中,程序设计语言与理论的核心内容是建立抽象;系统软件的核心内容是实现抽象;软件工程的核心内容是使用抽象。它们与我国目前一级学科、ACM/IEEE计算学科的关系如图1-X所示。
|
||
|
||
软件强大的渗透性,使得软件和产业紧密相联,并产生了软件产业。软件的问题解决方案和人工制品特性、软件发展的外部驱动力决定了其形成产业的必然,而强大的产业需求不断地拉动软件的发展,软件学科与软件产业相互促进,共生共荣。
|
||
|
||
\section{本章小结}
|
||
|
||
本章通过梳理软件发展的脉络,指出了软件是以计算为核心手段实现应用目标和价值的解决方案。可编程是软件的基本特征,建立抽象、实现抽象和使用抽象是软件发展的主线。不断增长的应用需求和不断增强的计算平台构成了软件发展的外部驱动力,而控制复杂性、提高单位成本的软件生产率和软件质量是其发展的内在驱动力。软件作为最为复杂的人工制品,软件学科是以软件为研究对象,通过科学方法、实验方法和设计方法等途径,研究设计和使用软件及其规律的学科。
|
||
|
||
第一篇的后续几章分别从程序设计语言与理论、系统软件、软件工程、软件产业等方面进一步阐述学科领域的内涵和外延、关注解决科学问题,以及对应的发展历程,现状和存在的主要矛盾。目的是从各方面来阐述软件发展的学科特性,把握学科现状和发展规律,为展望学科的未来发展奠定理性思考的基础。
|
||
|
||
\section{参考文献}
|
||
|
||
\begin{itemize}
|
||
\item [] [1]. Liskov \& Zilles. Programming with Abstract Data Types, ACM SIGPLAN Notices, 1974
|
||
\item [] [2]. Floyd. The paradigms of programming, CACM 1979
|
||
\item [] [3]. Watts S. Humphrey. Software Unbundling: A Personal Perspective. IEEE Annals of the History of Computing. 2002
|
||
\item [] [4]. H.A. Simon. The Science of the Artificial. 1968
|
||
\end{itemize}
|