看到这个题目,我想起了很多很多...........
首先,我说明我为什么要写这篇文章了。
一个原因是逸惋惜峥嵘岁月岁月稠,当初读大学的时候,学习计算机技术的课程,我过多的走向了两种极端的状况。一种情况,我愿意把他归结于本末倒置,例如我学习《C++面向对象程序设计》的时候,更多的是研究C++的语法,却忽略了面向对象的思想,到头来,C++语法学会了,但是最重要的面向对象却没有理解,也不知道他能够真正的做些什么。另一个情况,我把它理解为目标很宏大,理解很困难,例如,我学习软件过程的时候,开始,课程上就劈头盖脑的来一堆概念,然而,很难理解,最后也失去了学习该
课程的兴趣,后来,随着自己阅历增长,经验的增加, 发现这些知识是非常重要的,只是但是由于知识的限制,没有融会贯通罢了。
另外一个原因,我们和他人讨论写的代码时候,总是会从某某的口中听到,你这源代码写的——耦合性太大了,可是,这总是一种不欢而散争论,你凭什么我的耦合性太大,是啊,凭什么说我的耦合性,更多是种感觉,到底怎么样才能判断高内聚低耦合,怎么样写出来高内聚低耦合代码了。
还有一
个原因。和上面的原因有点类似,在编程中接触到的很多同事。或者同样是编程的人。我发现他们的能力参差不齐。但是,你会有这样的感受,有些人写了两三年的代码会比一个写十几年代码,更加的简洁,更加的优雅。
总结一下上面的原因就是,在我们的编程实践中,我们需要找到一种思维框架来帮助我们设计和解释我们的程序。这个东西就是要讨论的程序员思维。
我们下面篇幅就解决这三个问题。
程序员思维是什么?
程序员思维从哪里来?
程序员思维到哪里去?
好吧,这是三个终极的问题。没有标准答案,也没有什么不标准的答案。我只是试图给出自己的一个思考的总结。
再解释程序员思维是什么问题这个问题是什么时候,我们先用类比法看一下什么是程序员思维。
类比法,是个好方法啊,就像字典中的同义词解析一样。我们就类比生活中的一些例子罢了,来解释什么是程序员思维。有些人,说编程就像解题,一个题干出出来了,我们需要利用所掌握的知识,一步步,井井有条的解决出来。而编程了,则是根据客户的一个需求,利用自己技能把其变成计算机软件,来帮助解决现实生活中的问题。有些人,说编程就像操作机器,你像一个司机,你操作方向盘让车向左走,他不会向右左。我们编程也是同样的道理,你输入一条加法指令,计算机也不会帮你做减法。有些人,说编程就像作家,作家,是将冰冷冷文字赋予了生命,来卖钱。程序员,是将毫无生气的一些指令,变成那好玩游戏,哪方便的app。这些,都是很形象的类比。我们这里套用马克思*韦伯在《新教理论与资本主义》中首次提出了一个概念能够很好的解释上面列举的事情的共性——工具理性。所谓“工具理性”,就是通过实践的途径确认工具(手段)的有用性,从而追求事物的最大功效,为人的某种功利的实现服务。工具理性是通过精确计算功利的方法最有效达至目的的理性,是一种以工具崇拜和技术主义为生存目标的价值观,所以“工具理性”又叫“功效理性”或者说“效率理性”的定义。可以将程序员思维,定义为是在理性思维的框架下,利用相应工具,来解决相应实际的问题。
再回答程序员思维从哪里来,这个问题时候,我们回顾了计算机语言历史:
1940之前
第一个编程语言比现代的计算机还早诞生。首先,这种语言是种编码(en:code)。
于1801年发明的提花织布机(或称甲卡提花织布机,英文:en:Jacquard
loom),运用打孔卡上的坑洞来代表缝纫织布机的手臂动作,以便自动化产生装饰的图案。 Ada
Lovelace在1842年至1843年间花费了九个月,将意大利数学家Luigi
Menabrea关于查尔斯·巴贝奇新发表机器分析机的回忆录翻译完成。她于那篇文章后面附加了一个用分析机计算伯努利数方法的细节,被部分历史学家认为是世界上第一个电脑程序。这个故事我们上面也说过。
Herman
Hollerith在观察列车长对乘客票根在特定位置打洞的方式后,意识到他可以把资讯编码记载到打孔卡上,随后根据这项发现使用打孔卡来编码并纪录1890年的人口统计资料。
第一个严格意义上的计算机程式码是针对他们的应用面设计的。在20世纪的前十年主要是用十进制来算数,后来人们发现不只是用文字,也可以用数字来表现逻辑。举例来说,阿隆佐·邱奇曾以公式化(formulaic)的方式表达λ演算。图灵机是一种纸带标记(tape-marking)机器(就像电话公司用的那种)操作方法抽象化后的集合。图灵机这种透过有限数字(finite
number)呈现机器的方式,奠定了程式如同冯·诺伊曼结构计算机中的资料一样地储存的基础。但不同于λ演算,图灵机的程式码并没有办法成为高阶编程语言的基石,这是是因为它主要的用途是分析算法的复杂度。
就像许多历史上的”第一次”一样,第一个现代编程语言也很难界定。最一开始是因为硬件限制而限定了语言,打孔卡允许80行(column)的长度,但某几行必须用来记录卡片的顺序。FORTRAN则纳入了一些与英文字词相同的关键字,像是”IF”、”GOTO”(原字词为go
to),以及”CONTINUE”。之后采用磁鼓(magnetic
drum)作为内存使用,也代表计算机程式也必须插入(interleave)到磁鼓的转动(rotation)中。和现今比较起来,这也让编程语言必须更加依赖硬件(hardware-dependent)。
对部分的人认为必须在”编程语言”的状态确立之前,根据能力(power)以及可读性(human-readability)的程度来决定历史上第一个编程语言是什么语言。提花织布机和查尔斯·巴贝奇所制作的差分机(en:Difference
Engine)都具备在大量限制下,简单描述机器应执行行为的语言。也有种并非设计给人类运用的受限特定领域语言(en:domain-specific
language),是将打孔卡运用到自动演奏钢琴(en:player piano)上。
1940年代
最早被确认的现代化、电力启动(electrically
powered)的计算机约在1940年代被创造出来。程式设计师在有限的速度及内存容量限制之下,撰写人工调整(hand
tuned)过的组合语言程式。而且很快就发现到使用组合语言的这种撰写方式需要花费大量的脑力(intellectual
effort)而且很容易出错(error-prone)。 Konrad
Zuse于1948年发表了他所设计的Plankalkül编程语言的论文[1]。但是在他有生之年却未能将该语言实作,而他原本的贡献也被其他的发展所孤立。
在这段期间被开发出来的重要语言包括有:
1943 – Plankalkül (Konrad Zuse)
1943 – ENIAC coding system
1949 –
C-10
1950与1960年代
有三个现代编程语言于1950年代被设计出来,这三者所衍生的语言直到今日仍旧广泛地被采用:
Fortran (1955),名称取自”FORmula
TRANslator”(公式翻译器),由约翰·巴科斯等人所发明;
LISP,名称取自”LISt
Processor”(列举处理器),由约翰·麦卡锡等人所发明;
COBOL,名称取自”COmmon Business Oriented
Language”(通用商业导向语言),由被葛丽丝·霍普深刻影响的Short Range
Committee所发明。
另一个1950年代晚期的里程碑是由美国与欧洲计算机学者针对”算法的新语言”所组成的委员会出版的ALGOL
60报告(名称取自”ALGOrithmic Language”(算法语言))。这份报告强化了当时许多关于计算的想法,并提出了两个语言上的创新功能:
巢状区块结构:可以将有意义的程式码片段群组成一个区块(block),而非转成分散且特定命名的程序。也就是我们所熟悉的模块化设计。
词汇范围(lexical
scoping):区块可以有区块外部无法透过名称存取,属于区块本身的变量、程序以及函式。就是我们所熟悉的作用域。
另一个创新则是关于语言的描述方式:一种名为巴科斯-诺尔范式
(BNF)的数学化精确符号被用于描述语言的语法。之后的编程语言几乎全部都采用类似BNF的方式来描述程式 语法中上下文无关的部份。BNF主要使用在了Algol
60的设计上面。而Algol
60对之后语言的设计上带来了特殊的影响,在其他部分的语言设计中这种设计思想很快的就被广泛采用。并且后续为了开发Algol的扩充子集合,设计了一个名为Burroughs(en:Burroughs
large systems)的大型系统。而延续Algol的关键构想所产生的成果就是ALGOL 68:
语法跟语意变的更加正交(orthogonal)
采用匿名的历程(routines)
采用高阶(higher-order)功能的递回式输入(typing)系统等等。
整个语言及语意的部分都透过为了描述语言而特别设计的Van
Wijngaarden grammar来进行正式的定义,而不仅止于上下文无关的部份。Algol
68一些较少被使用到的语言功能(如同步与并列区块)、语法捷径的复杂系统,以及型态自动强制转换(coercions),使得实作者兴趣缺缺,也让Algol
68获得了很难用(diffcult)的名声。尼克劳斯·维尔特就干脆离开该设计委员会,另外在开发出更简单的Pascal语言。
在这段期间被开发出来的重要语言包括有:
1951 – Regional Assembly Language
1952 – Autocode
1954 –
FORTRAN
1954 – IPL (LISP的先驱)
1955 – FLOW-MATIC (COBOL的先驱)
1957 –
COMTRAN (COBOL的先驱)
1958 – LISP
1958 – ALGOL 58
1959 – FACT
(COBOL的先驱)
1959 – COBOL
1962 – APL
1962 – Simula
1962 –
SNOBOL
1963 – CPL (C的先驱)
1964 – BASIC
1964 – PL/I
1967 –
BCPL
(C的先驱)
1967-1978:确立了基础范式
1960年代晚期至1970年代晚期的期间中,编程语言的发展也有了重大的成果。大多数现在所使用的主要语言范式都是在这段期间中发明的:
Simula,于1960年代晚期由奈加特与Dahl以Algol
60超集合的方式发展,同时也是第一个设计支援面向对象进行开发的编程语言。
C,于1969至1973年间由贝尔实验室的研究人员丹尼斯·里奇与肯·汤普逊所开发,是一种早期的系统程式设计(en:system
programming)语言。
Smalltalk,于1970年代中期所开发,是一个完全从零开始(ground-up)设计的面向对象编程语言。
Prolog,于1972年由Colmerauer、Roussel,以及Kowalski所设计,是第一个逻辑程式语言。
ML,于1973年由罗宾·米尔纳所发明,是一个基于Lisp所建构的多型(polymorphic)型态系统,同时也是静态型别函数编程语言的先驱。
这些语言都各自演展出自己的家族分支,现今多数现代编程语言的祖先都可以追朔他们其中至少一个以上。
在1960年代以及1970年代中结构化程式设计的优点也带来许多的争议,特别是在程式开发的过程中完全不使用GOTO。这项争议跟语言本身的设计非常有关系:某些语言并没有包含GOTO,这也强迫程式设计师必须结构化地编写程式。尽管这个争议在当时吵翻了天,但几乎所有的程式设计师都同意就算语言本身有提供GOTO的功能,在除了少数罕见的情况下去使用GOTO是种不良的程序风格。结果是之后世代的编程语言设计者发觉到结构化编程语言的争议实在既乏味又令人眼花撩乱。
在这段期间被开发出来的重要语言包括有:
1968 – Logo
1970 – Pascal
1970 – Forth
1972 – C语言
1972
– Smalltalk
1972 – Prolog
1973 – ML
1975 – Scheme
1978 – SQL
(起先只是一种查询语言,扩充之后也具备了程式结构)
1980年代:增强、模组、效能
1980年代的编程语言与之前相较显得更为强大。C++合并了面向对象以及系统程式设计。美国政府标准化一种名为Ada的系统编程语言并提供给国防承包商使用。日本以及其他地方运用了大量的资金对采用逻辑编程语言结构的第五代语言进行研究。函数编程语言社群则把焦点转移到标准化ML及Lisp身上。这些活动都不是在开发新的范式,而是在将上个世代发明的构想进一步发扬光大。
然而,在语言设计上有个重大的新趋势,就是研究运用模组或大型组织化的程式单元来进行大型系统的开发。Modula、Ada,以及ML都在1980年代发展出值得注意的模组化系统。模组化系统常拘泥于采用泛型程式设计结构:
泛型存在(generics being)
本质(essence)
参数化模组(parameterized
modules)
尽管没有出现新的主要编程语言范式,许多研究人员仍就扩充之前语言的构想并将它们运用到新的内容上。举例来说,Argus以及Emerald系统的语言配合面向对象语言运用到分散式系统上。
1980年代的编程语言实际情况也有所进展。计算机系统结构中RISC假定硬件应当为编译器设计,而并非为人类设计。借由中央处理器速度增快的帮助,编译技术也越来越进展神速,RISC的进展对高阶语言编译技术发展来不小的贡献。
在这段期间被开发出来的重要语言包括有:
1980 – Ada
1983 – C++ (就像有类别的C)
1984 – Common Lisp
1985 –
Eiffel
1986 – Erlang
1987 – Perl
1988 – Tcl
1989 – FL
(Backus)
1990年代:互联网时代
1990年代未见到有什么重大的创新,大多都是以前构想的重组或变化。这段期间主要在推动的哲学思想是提升程式设计师的生产力。许多”快速应用程式开发”
(RAD)
语言也应运而生,这些语言大多都有相应的集成开发环境、垃圾回收等机制,且大多是先前语言的衍生语言。这类型的语言也大多是面向对象的编程语言,包含有Object
Pascal、Visual
Basic,以及C#。Java则是更加保守的语言,也具备垃圾回收机制。与其他类似语言相比,也受到更多的观注。新的脚本语言则比RAD语言更新更好。这种语言并非直接从其他语言衍生,而且新的语法更加开放地(liberal)与功能契合。虽然脚本语言比RAD语言来的更有生产力,但大多会有因为小程式较为简单,但是大型程式则难以使用脚本语言撰写并维护的顾虑[来源请求]。尽管如此,脚本语言还是网络层面的应用上大放异彩。
在这段期间被开发出来的重要语言包括有:
1990 – Haskell
1991 – Python
1991 – Visual Basic
1993 –
Ruby
1993 – Lua
1994 – CLOS (part of ANSI Common Lisp)
1995 –
Java
1995 – Delphi (Object Pascal)
1995 – JavaScript
1995 –
PHP
1997 – REBOL
1999 –
D
现今的趋势
编程语言持续在学术及企业两个层面中发展进化,目前的一些趋势包含有:
在语言中增加安全性与可靠性验证机制:额外的堆栈检查、资讯流(information
flow)控制,以及静态执行绪安全。提供模组化的替代机制:混入(en:mixin)、委派(en:delegates),以及观点导向。元件导向(component-oriented)软件开发元编程、反射或是存取抽象语法树(en:Abstract
syntax
tree)更重视分散式及移动式的应用。
与数据库的整合,包含XML及关联式数据库。支援使用Unicode编写程式,所以源代码不会受到ASCII字符集的限制,而可以使用像是非拉丁语系的脚本或延伸标点符号。
图形化使用者接口所使用的XML(XUL、XAML)。在这段期间被开发出来的重要语言包括有:
2001 – C#
2001 – Visual Basic .NET
2002 – F#
2003 –
Scala
2003 – Factor
2006 – Windows PowerShell
2007 –
Clojure
2009 – Go
从这些编程语言简史和人们日常需求,我们可以回答这个问题了。所有的程序员思维都是来自于需求两个字。随着对现实信息管理的压力太大的,我们慢慢才有计算机发明。为了,更好的管理计算机,于是便有了编程语言,起初的语言,是面向机器的了,后来随着世人更加理解的角度,就进一步面向过程,为了使人更加理解世界万物,就有了面向对象的语言,综上所述,程序员的思维,从何而来,从世间万物的需求而来,从更好的解决问题的需求而来。
有了程序员的思维从何而来的这一个冒解决了,我们就能够很快的回答,程序员思维你要到哪里去了?
一切程序员思维的宗旨就是,为了更好的解决问题,更好解决需求,于是在这一光辉思想的引导下了,我们就发明各种各样设计模式,为了使其代码高内聚低耦合,这些都是使其我们程序员花这小的代价来满足最大需求。
以上所述,便是我对程序员思维的理解,恳请大家斧正。