来自Unix/Linux的编程启发录
本篇文章已授权微信公众号 guolin_blog (郭霖)独家公布重点内容
2017年第一篇文章,祝各位好友新年快乐.
年前因为不小心坐到了自己左手大拇指导致轻微的骨裂,没有按时更新,实在是羞愧.今年给自己订了个小目标,在安顿好新工作后,每周一篇来总结这些年所学.
话不多说,步入正题
写本文的最初灵感源于16年11月份我将工作环境切换到Mac OS上,当中一些使用”差异”让我開始对Unix/Linux中设计产生了浓厚的兴趣.虽然从13年開始使用redhat,再到后来一直使用的ubuntu,但却从来关注过这些,特此记录.
在整个探究过程中,那些经典的著作再次让我获益匪浅:C和指针,C专家编程,深入理解计算机系统(原书第3版),Linux/Unix设计思想,Linux Shell脚本攻略.前两本书购于13年,断断续续的读了许久,这一次重读令人豁然开朗,当中很多不解之处在深入理解计算机系统一书得到答案,而后两本则是年前有幸读到.当中Linux/Unix设计思想不谈技术细节,却揭示了Linux/Unix隐含的指导思想,最后一本则是从Shell出发,以实践的角度教你怎样利用Shell(Bash)在Linux/Unix平台上构建有效的解决方式,实乃入门进阶必备啊.
从女娲造人说起
俗说天地开辟,未有人民,女娲抟黄土作人.剧务,力不暇供,乃引绳于泥中,举以为人.故富贵者,黄土人;贫贱人,引绳人也…
神一样的程序猿
“女娲造人”可谓人人皆知,女娲是神,而程序猿是能力上最接近女娲的存在.假设说女娲创造的是真实的世界,那么程序猿是创造数字的世界,我们所写下的每行代码,所构建每一个程序,都在让这个数字世界变得丰富多彩.
没有哪个职业能够像程序猿:赋予代码以生命,创造数字世界中的花花草草!虽然我们拥有近乎神的能力,本身却也受着NIH综合征的困扰.
程序猿之殇
NIH综合征是什么?
Not invented here (NIH) is a stance adopted by social, corporate, or institutional cultures that avoid using or buying already existing products, research, standards, or knowledge because of their external origins and costs.
我们常常为NIH所困:在求解解决方式时,常常自觉得能够做得更好或者在看到别人的解决方式会提出各种质疑.这大都是我们缺乏对当时问题解决者所面临限制的认识所造成:可能迫于时间或者预算的限制,也可能受限于当时物理资源的限制.
穿着衣服的猴子
NIH综合征的特点就是人们会为了证明自己能够提供更加卓越的解决方式而放弃其它开发人员已经完毕的工作.这样的狂妄自大的行径说明此人并无兴趣去维护他人竭尽全力提供的最佳成果,也不想以此为基础去挑战新的高度.NIH综合征本质上是动物天性—”嘿,我更好”的体现,就像全部的公猴都会向母猴证明”我更好”一样.
放弃已有工作成果而另起炉灶的做法无形之间浪费了大量时间.有一些技术人员在入职新公司后,往往有想推倒一切重来的欲望.我以前有位朋友连续跳槽非常多家公司,每次入职之前都信心满满,不就后就黯然离开.朋友能力非常不错,但每次入职后总是急于通过推倒重来来证明自己的能力.
更糟的是,新的解决方式往往仅仅是做了一些改进,和之前并无本质差别,再加上现代的应用往往动辄十几万行,远超出每一个人所能注意的极限,这也会让程序猿产生疏漏,从而使得这个问题变得更糟糕.
当然,少数情况下,新的解决方式更好,这仅仅是因为技术人员早已了解做过的工作,从而针对问题能够提出更高的解决方式.站在如今的角度看历史,还看不出对错的话,除非你对历史一无所知.
为什么Linux会成功
Linux为什么会成功有非常多的的因素,除却当时环境因素外,其成功之处在于开源的世界让每一个人都能得到Linux源代码,从而使得经验能够被借鉴.其实,在原有软件基础上进行扩展是Unix的核心概念之中的一个.当然,在Linux出现之前,借鉴他人编写的软件已成为相当普遍的做法,这也是GUN宣言中的GPL下所阐释的思想.
来自Unix/Linux的编程启发录
如今我们来看看Unix/Linux中那些隐藏的编程哲学,须要说明的是Unix/Linux中的编程哲学非常通俗易懂,他们大多是你已知的,很多其它的时候是我们不曾注意到.
不管你如今负责的系统多么复杂,这总有能够帮助你的地方.(要说复杂,还有什么比Unix/Linux更为复杂的应用?)
原则一:小既是美
我猜当你看到”小既是美”一词时会首先想到一句谚语”麻雀虽小,五脏俱全”.那就用麻雀做引子来说说为什么小即是美.
大凡生物,不管形体怎样,愈小愈稳定.麻雀相对人而言,出现脑残鸟的几率要小的多,而单细胞生物相对多细胞生物产生显著变异体的概率也要小的多…在软件project中,相同如此.Unix中的程序大凡遵循这条准则,小带来的显著优点例如以下:
- 易于编写
- 易于理解
- 易于维护
- 消耗更少的系统资源
- easy与其它工具组合
虽然我知道你已经对其有过了解,我还是例行的啰嗦一下.
每一个程序猿心中都有编写一个万能软件的想法,渴望像上帝一样创世,能够名垂青史,但这实在是太难了.越是复杂的问题越令人畏缩不前,想想在上学期间,你是更乐于立马開始做一道题还是一套题呢?不出意外,我们大都喜欢从一道题開始.编写小程序相同如此:我们能够尽快的动手去做,而且针对某个点找出更合理的解决方式.另外,因为大脑的结构,我们无法同一时候关注超过四个以上的点,而复杂的程序须要被关注的点却远大于四个,这就意味着我们可能会犯很多其它的错误.
小程序带来的还有一个优点就是easy理解,一个100行的程序比一个1000行的程序要easy理解的多(复杂度相同的情况下).
当程序足够小的时候它就是函数,还有什么比函数更灵活地自由组合呢?
当然大多数小程序不能够小到仅仅有一个函数,但尽可能的减小程序大小仍然非常重要,unix/linux中的命令便是最佳的演示样例:cp用来拷贝,rm用来删除,组合起来就能够实现移动,简直棒呆了.
我想,没人会觉得麻雀每天摄入的能量会比人多吧?换到程序当中就是越小的程序消耗的系统资源会更少,大多数情况下如此.
原则二:让每一个程序仅仅做好一件事情
程序猿或许仅仅想编写一个简单的应用程序,可是随着他的创新精神占领上风,促使他在会在这里加入一个功能,在那里加入一个选项,非常快你就发现本来你仅仅想要一个文本编辑器,可是他却给你一个IDE,终于他给你的往往不是惊喜而是大杂烩.这个问题不但在程序猿身上体现出来,相同也会出如今产品经理上:想要一个计算器对么,我这里有个超级计算机能够给你用?如今你仅仅能面对这这么一个庞然大物了
该思想和”小即是美”相辅相成,”专注一件事”的应用终于会产生一个较小的程序,而小程序往往仅仅有单一的功能,单一功能的程序往往也会非常小.另外,每一个程序仅仅做一件事情也意味着我们能够集中精力去解决当前任务,全新全意做好本职工作.
原则三:建立原型
原型的建立是学习的过程:在该过程中能够知道哪些想法可行,哪些不可行.每一个正确设计的背后都有数百个错误的设计方案,通过建立原型,我们能够在早期剔除掉不良的设计方案,以此来减少风险.换句话说,越早的建立原型,离你的软件公布的时间越近.
你的软件公布了吗?
从開始接触软件project開始起,我们的前辈就告诉我们:”软件永远不会有开发完的时候,记住,是永远!”.
“怎么会完不成呢,我仅仅要不做了不即可了么?”,如今想想,这比让一个沉迷在购物中的女人停下脚步更难(假设钱是无尽的话).编写软件亦如此,你永远都会想要加入的很多其它的功能.想加入的很多其它功能的可能不是你,或者是你的产品经理,当然你的boss也会掺一脚.
我一直在向周围的朋友传递这么一种观点”世界上唯有不变的事物那就是变“,对于软件project相同如此.既然变化无可避免,那软件是怎么完毕的?
虽然我们做事都希望看到最后的结局,可是对于软件而言并不是如此.能够说,没有做完的软件,仅仅有公布的软件.
我曾犯过相似的错误.16年我在负责一款移动端产品的开发,希望在一个月内上线第一个版本号.因为个人疏忽,当我着手原型工作时离公布时间仅仅有20天的时间了,在这期间发现原有的一些方案无法奏效,我不得不暂时更改一些既有的设计.终于导致第一个版本号正式公布的时间超出15天.我也曾因此被觉得是个糟糕的project师.在团队没有不论什么移动应用产品开发的经验下,及早的開始建立原型或许不会导致如此后果.在离开这家公司之后,我仍倍感羞愧.
原则四:舍弃高效率而取可移植性
偏向高效率往往会导致代码不可移植,而选择可移植性往往会让软件的的性能不那么尽如人意.每当有为了追求高效率而放弃移植性的想法的时候,请在心中默念下面两句话:
- 速度欠佳的缺点会被明天的机器克服
- 好程序不会消失,而被移植到新平台.
关于优化的两点建议
在unix环境中,可移植性的含义通常意味着人们要转而採用shell脚本来编写软件.抛开平台不谈,关于优化,我有下面两点建议:
- 不要立马优化:如无必要,无须优化.换句话说,不要想当然的优化,尤其是在用户无感觉的情况下.
- 关注微优化:影响性能的往往仅仅有几处,在须要优化的时候仅仅要解决这几处就好,切莫以优化的名义重构全部.
原则五:使用纯文本来存储数据
文本不一定是性能最好的格式,但却是最通用的.另外,文本文件易于阅读和编辑:在不论什么平台上我们能够轻松的阅读文本数据,或使用标准文本编辑器对其进行编辑.
你可能会考虑到使用纯文本文件拖慢了系统的处理速度,并会找出一系列的证据来证明处理字符串的性能更低.我们承认文本文件确实拖累了系统的性能,可是记住明天系统的机器的性能必将有大幅度的提高.
原则六:利用软件的杠杆效应
给你一个杠杆,在不考虑杠杆质量的前提下,你真的能够撬动地球.一个人精力仅仅有这么多,假设想要取得非凡的成就,你就必须放大自己对这个世界的影响力,这就须要你找到当中的”杠杆点”,也就是关键点.
君子性非异也,善假于物也
软件中的杠杆效应就是要善于利用他人已有成果,详细点就是学会利用他人写的代码.在早期,我希望每一行代码都是从自己手中出来,并以为为傲,并觉得这就是所谓的优秀的程序猿.多年之后,我才明确成为一个优秀程序猿的关键却和手敲每行代码并无必要联系.
善于利用他人的代码会给程序猿自身添加砝码.这可能和非常多人的认知相违背.查看别人工作并夸口说自己做的更好,不代表你能力更强;推导现有的方案在重来,那仅仅是模仿不是创造.想要解决掉你手中的任务,编写很多其它软件的最好方法就是善于借用别人的成果.和大多程序猿一样,我曾觉得亲自编写代码能带来”就业保障”,并将这样的做法视为核心竞争力.但实际工作中却是相反,在实现功能的前提下,企业往往觉得花费时间更少的程序猿更具有高效的生产了,你可能对此感到委屈和不解.这里,我想要说的是:认识企业对你的认识和你对自己认识之间的差异是非常重要的.
假设有可能,请尽量让你的工作自己主动化.通过加强自己主动化工作来利用软件的杠杆效应能产生巨大的生产力,而且能够更充分的利用好时间.假设你是个linux开发人员,shell脚本便是你在寻找的杠杆点.
化作春泥更护花
从另外一个角度来说,同意他人使用你的代码来发挥杠杆作用.大部分project师喜欢私藏自己的源代码,并视为独一无二,举世珍宝,仿佛自己的”核武器”.他们觉得公开自己的源代码,自己就失去地位,会被公司所抛弃.
哪些你以为是”核武器”的代码真的就有如此威力么?要记住:不论什么一个有着合理思维的正常人都能够编写出像样的代码.更何况,一个有耐心的程序猿全然能够将程序反汇编出来,通过一步一的分析,终于发现当中的蛛丝马迹.
Linux的开发人员觉得执意保留源代码的控制权并无太大必要.如今你发现,虽然你拥有全部的源代码,但却仍然不能创造出比Linux更成功的操作系统.我想这足打消你心中哪点忧虑了.
又一次认识自豪感
如今又一次认识所谓的自豪感.非常多程序猿将写出优秀的代码,使用先进的技术视为自豪感,但我们终于的产出是用来服务用户的,假设用户不能惬意,那么我们所谓的自豪感只是是”孤芳自赏”.
原则七:使用shell脚本来提高杠杆效应和可移植性
谈起脚本语言,非常多project师觉得脚本太弱了,仅仅能用来编写简单的应用无法project化,而且不少程序猿更乐于哪些看起来宏大的java或者net应用,甚至有些程序猿觉得脚本语言算不上一门语言.现实给了我们一巴掌:我们从来没有想象过javascript会有如此发展,以node为代表的新型开发平台,让整个JavaScript语言变得非常有活力.
那么我们是否也小觑了shell这样的简单的脚本语言呢?有非常长一段时间我不能正确的认识shell是什么,甚至觉得”嗨,这东西好像对我没什么用,它能用来干什么”.让我改变想法的恰好是15年的工作经历.
和其它脚本语言(如:python,JavaScript)一样,shell脚本相同由一个或者多个语句组成,通过调用本地程序,解释程序和其它脚本来执行任务.shell脚本将每条指令载入到内存执行.大部分情况下,这些指令是由无数的unix/linux开发人员事先编写完毕,我们要做的就是用shell来间接的利用这些高效,安全的代码.比方在shell中使用wget命令来下载文件时,我们实际书写的只是几行语句,背后支撑我们的确有数万行的代码,假设让你来用java写一个下载器会须要多少project量呢,又须要耗费多少时间?如今有些程序猿会反驳我:我用python写起来也非常快,代码也不多?那问题来了,python的执行环境可不是先天就存在unix/linux中的,可是大部分unix/linux却都是支持shell的.假设编写的脚本程序要执行在不同的系统中或者执行在很多设备中,shell无疑具有更好的移植性,不是么?
如你所想,及时执行
脚本语言有一个先天的优势就是他们是解释型的语言,执行前不须要事先编译.先来看看以C语言为代表的编译型语言,要构建一个程序的基本流程例如以下:
思考->编辑代码->编译->測试
而在shell当中,整个过程更短:
思考->编辑->測试
相比C语言,shell不存在编译过程,这带来的优势就是:不管shell的应用规模多大多复杂,仅仅要你想你就能够执行它观察它,而无需像C语言一样等待编译过程结束后再执行.
shell真的慢吗?
一些程序猿对shell执行效率过于担忧,觉得其效率太低,这就导致了他们为了更高的效率企图採用C语言来重写脚本.shell脚本的执行效率相对较慢,一旦C程序被装载到内存中执行,纯C程序与那些从脚本中调用C程序相比,并没有太大的性能优势.另外,因为Unix/Linux中大部分的命令做过相关的优化,反而会比由你编写的纯C程序更快.这也引出我想说的另外一点:为了追求更高的性能而更换语言这一做法有待商榷.假设真是为了追求性能,那么改变通过改良实现方法更有效,比方有序数列中查找指定数字採用二分查找比传统的遍历查找的时间复杂度更低,而不是将原来实现遍历查找的java代码改成C代码实现.
原则八:避免强制性的用户界面
我最早接触计算机系统是Windows 2000,应该是在上小学期间,虽然我不知道这个大个”计算器”能够做什么,可是却能够在没人教的情况下琢磨去做,并学会玩编辑文字,利用文本编辑器和共享来相互交流,当然,少不了的纸牌和扫雷.
window和unix/linux理念差异
用户界面能够让不论什么一个小白在不须要专业知识的前提迈出操作的第一步.window系列产品和unix/linux系列产品的不同之中的一个在于对于他们对用户的看法上:window下的设计者觉得用户是畏惧和计算机打交道的,因而提供足够的用户界面来消除用户的恐惧心理,而unix的设计理念则不同,它觉得一个接触unix/linux的用户已经具备了主要的计算机素质,并力求更全面的掌握它,从这个角度而言,unix/linux是选择用户的,而window是服务用户的.
这也是早期window比unix/linux更为大众所接受的关键因素之中的一个.但随着unix/linux的逐渐发展以及大众计算机素质的提升,越来越多的人開始接受unix/linux产品,并热衷与此.
像搭积木一样编程
对于程序猿而言,我们希望编程应该像搭积木一样,通过不同的组合来实现多样的产品,未来的产品也应该是如此:一些程序猿负责开发基础的小模块,另外一些程序猿则负责将这些小模块对接成客户所须要的产品.对Unix/Linux开发人员而言的确如此,我们能够利用系统中提供的众多非界面性小程序来组合成我们所须要的.可是对于提供用户界面的小程序而言我们却非常难做到这点:用户界面渴望与用户沟通而非还有一个程序,而模拟人在用户界面上的沟通并不是易事,你须要花费很多其它的精力放在非核心需求上.
即使我们能够模拟,从操作效率来看也不容乐观.毕竟用户界面相对命令程序而言本身意味着很多其它的资源消耗,我想没人愿意在server上装一个KDE吧?这就是window下相同拥有众多的小程序但却非常难将其组合成新产品的原因之中的一个,换言之我们非常难利用前人已产生的成果来发挥杠杆作用.
嗨,我们须要再加个button
程序猿和产品之间总有一个矛盾点,来看看下面这个对话.
PM:”这里加个button”
RD:”又没有人用,不加不行么?”
PM:”听我的,加上吧!加了button之后就会有人点击…”
RD:”好吧…”
PM:”你看这个地方空白好大,能再加一个button么?”
RD:”我….”
好吧,这是个笑话,我并不是想挑起程序猿和产品之间的战争.假设你在设计/开发一个界面化的产品,你常常会情不自禁的为他加上很多其它的button,企图让他提供更丰富的功能:你总觉得有人会须要它.终于导致项目更加复杂,但用户惬意度却未见提升.
有这么一件事到如今对我影响甚大.我想把Kindle中的笔记导出到印象笔记,这件事情本来非常easy,仅仅须要导出指定的文本文件,解析后导入到印象笔记就能够.来看看当时我想了什么:我应该做一个界面,能够方便的我操作,别人也可能须要一个保存笔记成html格式的功能,所以我要加入个转换button,当然,保存,导出button也不能忘了,等等…要不要编辑功能?…
这非常好笑,不是么?因为我第一时间想到了图形界面,接下来情不自禁地想在界面上加入很多其它的功能,更重要的是我明明是自己使用的,却站在别人的角度上去给自己提了需求?
假设终于呈现出的是图形化的产品,会发生非常有意思的事情.来想一下,我希望它能在每天十二点自己主动完毕导出任务?难道我要再写一个程序来模拟点击操作么?
既然这样,为什么不能让两个程序有能够直接交流的能力么?
(感谢unix/linux中的管道机制)
如今来看究竟发生了什么?当我们想提供界面的时候,就假设是人在操作.这个隐形的假设终于让这个程序失去了自由,好比送给孩子一个用胶水粘合积木而成的城堡而非一盒积木.
原则九:让每一个程序都成为过滤器
程序是什么?早期觉得程序=算法+数据
.但从功能的角度来说,程序即过滤器.
先不要着急骂我或者反驳我.你不觉得在你编写的每一个程序中,不管是复杂还是简单,都是以某种形式接受数据,并产生一些数据作为输出么?这些要输出的数据不就是取决于程序中的算法么?有一些人为过滤器就该是过滤掉不符合期望的东西,而非转换,比方存在一个程序用于过滤掉集合中元素值为0的元素,这对于大部分人而言是最直观的有关过滤的理解.但要记住过滤器相同也包括转换的概念.
对于计算器而言,我们输入错误会产生错误提示,而决定产生什么样错误信息的算法就是错误状态输入的过滤器.能够说算法是人依据需求定义的规则,即算法由人定义.那数据又是怎么来的?
一个没有数据输入/输出的程序就像一个不会进食和排泄的人,这样的程序没有存在的价值,现实世界也不存在这样的人.
原则十:并行思考
计算机界有个经典的笑话:假设一个女人要花是十个月生下一个婴儿,是否意味着能让十个女人在一个月内生出一个婴儿呢?笑话中透出的含义非常明显:自然特性导致某些任务必须被串行,不论什么试图让其并行执行的举动都无法加快它的进程.
在数字计算机的整个历史中,有两个需求不断的驱动我们:一是我们想计算机做的很多其它,令一个是我们想要计算机执行的更快.而并发则是实现这两个需求有效途径.对程序设计而言,并行思考意味着我们应该尽可能利用CPU运算性能,这也要求我们要对任务进行仔细有效的分解,寻找其串行路径和并行路径.
现代操作系统通过提供进程,线程及I/O多路复用作为并行思考的实现手段,这里我们对这三者做个简单的说明:
- 进程:每一个逻辑控制流都是一个进程,由内核来调度和维护.因为进程有独立的虚拟地址空间,想要和其它控制流通信必须依靠显示的进程间通信,即我们所说的IPC机制
- I/O多路复用:应用程序在一个进程的上下文中显式地调度他们自己的逻辑流.逻辑流被模型化为状态机,数据到达文件描写叙述符之后,主程序显式地从一个状态转换为还有一个状态.因为程序都是以一个单独的进程,所以全部的流都共享同一个地址空间.主要的思路就是使用select函数要求内核挂起进程,仅仅有一个或多个I/O事件发生后,才将控制权返回给应用程序
- 线程:线程应该是我们最为熟知的.它本质是执行在一个单一进程上下文中的逻辑流,由内核进行调度.
现代程序设计语言大都提供对这三种开发方式的支持,比方C,Node,Python中常常使用多进程/线程技术,java中的多线程及NIO技术等等.除此之外,协程也是一种不错的技术方案,比方Lua,Python中也提供了对协程的支持.关于这几种实现并发编程的技术方案,我将在随后的文章中去解析.
最后补充一点,不管机器速度快慢,我们都能够将多个机器串联在一起,从而得到一个执行速度更快的集群,这就是现代server技术核心之中的一个:大凡高性能的server应用背后都有集群的身影,而这些集群大都依托于高性能,便宜的Unix/Linux平台.
原则十一:各部分之和大于总体
水泥、沙子、石子和水个各自的硬度不高,可是混合起来去能得到高硬度的混凝土.这个现实展示了一个非常普通的道理就是对不同特性的物质进行组合往往能产出令人意外的结果,这样的不遵循数学上”1+1=2”的规律却和化合反应非常相似.
放在软件project中相同如此:通过组合小程序来构建集成性的应用程序.这就和我在上文中提到像搭积木一样编程.深究下来,不管是搭积木还是编程,当中共性就是组合的思想.从原子到分子,从树木到高楼大厦,从函数到程序,看似不相关的东西经组合产生出意想不到的结果,在某种意义上,组合的思想是我们人类大脑最重要的能力之中的一个.
原则十二:寻找90%的解决方式
“金无足赤,人无完人”这朗朗上口的话放在软件领域却代表一个不争的事实:没有一个软件能百分百的满足用户.说的更直白点,你的软件在用户看来总缺少点什么,不管你做出什么努力,这也从还有一个角度说明”仅仅有已公布的软件而没有完毕的软件”.
中国邮政 vs 顺丰
既然没有完美的软件,那对于软件开发人员而言,有一个非常艰难的决定:”我们该向用户提供什么”.这是个非常有意思的问题,其答案取决你所开发软件的性质以及面向的用户群体.
讲到这,就不得不谈起中国邮政和顺丰速递.在中国的每一个地方,你都能够用中国邮政来收发快递,而顺丰却仅仅见于经济发展不错的地区.非常多人像我一样曾抱怨过邮政的效率太低,接下来感叹一句要是有顺丰该多好.如今我们客观的来谈谈同为快递这两者本质差异:邮政作为一家国企,在政府的要求下,邮政必须服务全部的人,必须提供100%的解决方式,而顺丰作为一家独立的商业公司,却能够选择性服务,通过专注于高利润且easy做到的90%.终于的结果就是我们普遍觉得顺丰具有更高的效率.
这当中的关键在于我们须要有益忽略哪些代价昂贵,费时费力或难以解决的问题.从商业的角度来说,这是一种”低投入,高回报”的解决方式.如今我们能够来谈谈软件开发了.不管你是个人开发人员还是商业软件公司负责人,都应该考虑这个问题”向用户提供什么才最有价值”,然后去解决这当中的90%.这可能令非常多人不适,但如今互联公司最不应该做的就是企图提供向邮政一样的100%的服务.提供90%的方案除了能获得更高的效益之外,还能够帮助聚集你的用户群体,这也是15年创业期间最大的感触之中的一个.
原则十三:层次化思考
层次化思想是什么?说起来非常抽象,不如直接的问自己一个问题”金字塔是怎样建成的?”假设你的回答是一层一层建成的,那么你能够直接略过本章节了.
层次化思考并并不是新名词,对大部分程序猿而言,”分层”是全部解决方式的指导思想,这里的分层便是层次化思考的结果.与层次化思考相关的一种分析方法是AHP(Analytic hierarchy process),即层次分析法.(关于AHP很多其它的信息就不多讲了),它是思考和构造复杂系统的一个基本方法,依照该方法设计出的系统具有明显的层次体系.
现实世界充斥着层次化结构,小到细胞结构大到宇宙,从小团队到跨国公司,其都呈现出层次化结构,对计算机软件而言亦如此.在层次体系中,下层构件为上层构件提供服务支撑,上层和下层之间的关系就像是方法的”调用-返回”.採用层次化设计的应用就像金字塔,先有底层构件,然后在之上构建高层构件,相对低层构件而言,高层构件更easy理解.
能够说,一个系统不管最初採用什么样的组织方式,终于都会走向分层体系.
我常常说的一句话是:无分层不架构,通俗点就是没有分层的应用是没有架构可言的.分层结构在计算机世界中无处不在,来看几个最典型的样例:
ISO/OSI七层网络模型
WEB应用分层结构
Unix/Linux系统分层结构
Android 系统分层结构
MVC & MVP
除了上述几个典型演示样例外,两种典型的开发方式MVC 和MVP也都是典型的分层结构:
不管是MVC还是MVP,亦或是MVVM,还是将来出现的什么M*P,仅仅要记住全部的开发方式本质都是层次思考的结果,终于呈现分层体系,这就是所谓的万变不离当中.假设将分层体系和小程序结合起来,我们能够得到一个更为通用的程序结构设计图:
总结
或许你会像我当初一样纳闷这么优秀的操作系统就靠这些看起来无比简单理念引导?事实确是如此,这有点像我们所说的”大道至简”,复杂的东西简单做,也是我们解决这个问题的最重要的一步.
关于Unix/Linux中的编程哲学,我想以上十三条已经足够.当中最有启发的应属”小既是美”,这也是我决定以后不写长文的原因.
posted on 2018-02-03 11:00 yjbjingcha 阅读(183) 评论(0) 编辑 收藏 举报