左耳听风_077_76_程序员练级攻略软件设计

你好,我是陈浩网名做耳朵house,学习软件设计的方法、理念、范式和模式是让你从一个程序员通向工程师的必备技能。

那如果你不懂这些设计方法,你就无法做出优质的软件。

那这个就好像写作文一样,文章人人都能写,但是能写的有条理,有章法,有血有肉就不简单了。

那软件开发啊也是一样,实现功能做出来并不难,但是要做的漂亮,做的优雅就非常的不容易了。

Linux说过,这个世界程序员之所以有高下之分,那最大的区别啊就是程序员的品味不一样,有品味的程序员和没有品味的程序员写出来的代码做出来的软件差距非常大。

所以如果你想成为一个优秀的程序员,呃,软件设计啊一定是你的必修课。

但是软件设计这个事儿并不是一朝一夕就能学会的,也不是别人能把你教会的那很多东西啊都需要你自己用实践,用时间、用错误、用教训,用痛苦。,才能真正体会到其中的精髓。

所以除了学习理论知识之外呢,你还需要大量的工程实践。

然后每过一段时间啊,就把这些设计的东西重新回炉一下。

你会发现这些软件设计的东西就像喝茶一样,嗯,一开始吃苦的,然后慢慢回甘。

最终啊你会喝出真正的滋味。

要学好这些软件开发和设计方法,你真的需要磨练和苦行,反复咀嚼,反复推敲,在实践和理论当中螺旋式的学习才能真正的掌握。

所以呢你需要有足够的耐心和恒心。

学习编程范式呢可以让你明白编程的本质和各种语言的编程方式。

因此呢我接下来会推荐一些资料来帮助你系统的学习和理解。

那第一个呢就是我在极课时间写的编程范式游记系列的文章。

呃,第二个呢是维基百科上的一个编程范式的页面。

那顺着这个页面看下去,你可以看到很多很多有用的和编程相关的知识。

那这些东西对你的编程技能的提高会非常非常的有帮助。

而第三份资料呢是一篇文章标题叫做six programming paradigms that will change how you think about coding.中文翻译版呢叫做六个编程泛型,想改变你对编程的看法。

那这一篇文章讲的默认知识并发依赖类型、连接性语言,还有生命式编程、符号式编程和基于知识的编程。

这六种不太常见的编程范式,并结合了一些你没怎么听说过的语言来分别进行讲述。

比如说在讲连接性语言concttative languages的时候,他以false cat和joy三种语言为例子,讲述了这一编程范式背后的思想啊,就是说语言中的所有内容啊都是一个函数。

用于将数据推送到堆栈,或者从堆栈弹出数据呃,程序几乎完全通过功能组合来构建。

呃,作者认为啊,这些编程范式背后的思想十分有魅力,能够改变你对编程的思考。

我看完这篇文章对此也深信不疑。

虽然这些语言和编程范式不常用到,但确实能在思想层面啊给予人很大的启发。

这也是我推荐这篇文章的目的。

第三篇文章叫做programming paradigm or dammies what every programming should know.这篇文章的作者彼得范罗伊,是比利时鲁顿大学的计算机科学教师。

那他在这篇文章里啊分析了编程语言在历史上的演进,有哪些典型的值得研究的案例里面体现了哪些值得学习的范式。

比如说在分布式编程领域呢,他提到了二line e distributed off和detective off这四种编程语言。

那虽然它们都是分布式的编程语言啊,但是各有特色,各自解决了不同的问题。

那通过这篇文章,你能学到不少在设计编程语言的时候要考虑的问题,让你重新审视自己所使用的编程语言应该怎么样才能用好,有什么局限性,以及这些局限性能否被克服啊等等。

第四份资料是斯坦福大学的编程范式公开课,嗯,这是一门比较基础,并且很详细的课程,适合学习编程语言的初学者。

他通过讲述CC加加并发编程scheme和python这五门语言介绍了他们各自不同的编程范式。

以c语言为例子,它解释了c语言的基本要素。

比如说指针啊、内存分配啊、堆啊,还有c风格的字符串等等。

并解释了为什么c语言会在泛型、编程和多态等方面有局限性。

那通过学习这门课程啊,你会对一些常用的编程范式有所了解。

呃,接着呢我们来说一些软件设计的相关原则。

第一个原则叫做don't repeat yourself,简称DRY.那DRY是一个最简单的法则,也是最容易理解的,但它也可能是最难被应用了。

因为要做到这样,我们需要在泛型设计上做很多努力,这并不是一件很容易的事儿。

它意味着当我们在两个地方或者更多地方发现一些相似代码的时候啊,我们需要把它们的共性抽象出来,形成一个唯一的新方法,并且改变现有地方的代码,让他们一些合适的参数调用这个新的方法。

第二个原则叫做keeping simple stupid,简称kiss.那kiss原则在设计上可能是最被推崇的。

在家装设计、界面设计和操作设计上,那复杂的东西越来越被众人所鄙视了,而简单的东西越来越被人所认可。

宜家的简约、高效的家具设计和生产思路,微软所见即所得的理念,google简约直接的商业风格唯一例外都遵循了case原则,也正是case原则啊,成就了这些看似神奇的商业经典。

而苹果公司的iphone和ipad向这个原则实践到了极致。

第三个原则叫做programtary, interface, not imliliitation.那这个是设计模式中最根本的哲学,注重接口,而不是实现依赖接口,而不是实现接口,是抽象的,是稳定的那实现呢则是多种多样的。

在面向对象的敛的原则当中呢,会提到我们的依赖倒置原则啊,这个就是这个原则的另一种样子。

那还有一条原则叫做composition over inheritance,意思,就是喜欢组合,而不是继承。

这两条都是那二十三个经典设计模式中的设计原则。

第四个原则就是you aren't going not needed.那这个原则简单来说呢,就是只考虑和设计必须的功能啊,避免过度设计,只实现目前需要的功能。

在以后你需要更多功能的时候呢,可以再进行添加。

那如果没有必要,就不要增加复杂性。

所以说,软件开发是一场traree love的博弈。

第五个原则叫做law of dimeter,也就是迪米特发色,又叫做最少知识原则。

他来自于一九八七年荷兰大学的一个叫做dimeter的项目。

呃,克里格拉尔曼a lot of demeter又叫做不要和陌生人说话,在程序员修炼之道中讲迪米特法则的那一章里啊,它叫做解耦合与迪米特法则。

那关于迪米特法则呢有一些很形象的比喻。

那第一个比喻就是说如果你想让你的狗跑起来,你会对狗说还是对四条狗腿说呢?那第二个比喻就是说,如果你去店里买东西,你会把钱交给店员,还是会把钱包交给店员,让他自己拿和狗的四肢说话,让店员自己从钱包里拿钱,这个听起来有点荒唐。

不过在我们的代码里啊,这几乎是见怪不怪的事情了。

那么对于迪米特法则正式的表述是这样的,对于对象o里面的一个方法,m那m只应该能够访问对象中的这几个方法,那一个是对象o自己,一个是与o直接相关的component ent object.呃,另一个呢是由方法m创建或者实例化的对象,还有一个是作为方法m的参数的对象。

那接下来啊是面向对象的狩猎的五原则,分别是职责、单一原则、开闭原则,里式替换接口隔离,还有依赖倒置。

关于单一职责原则,SRP它的核心思想就是一个累只做一件事儿啊,并把这个事儿做好。

只有一个引起它变化的原因。

单一职责原则可以看作是低耦合、高内聚。

在面向对象原则上的引申,他把职责定义成了引起变化的原因,以提高内聚性来减少引起变化的原因。

那职责过多了,可能引起他变化的原因就越多。

那这个就会导致值得依赖,相互之间呢就会产生影响,从而极大的损伤。

内聚性和耦合度。

单一职责通常意味着单一的功能。

因此呢不要给一个模块实现过多的功能点,要保证实体只有一个引起它变化的原因。

那关于开闭原则OCP,它的核心思想就是模块是可扩展的,而不可修改的。

也就是说,对扩展是开放的,而对修改是封闭的对扩展开放意味着有新的需求或者变化的时候,可以对现有的代码进行扩展,以适应新的情况。

而对修改封闭呢,就意味着类一旦设计完成了,就可以独立完成它的工作,不需要对它进行任何修改。

那关于理事替换原则,LSP软件工程大师罗伯特马丁把它最终简化成了一句话,subtypes must be substitute able for their base types.也就是说子类啊必须能够替换成它们的积肋。

也就是说子类应该可以替换任何鸡类能够出现的地方。

并且经过替换之后呢,代码还能正常工作。

呃,另外啊就是不应该在代码中出现if else之类对此类类型进行判断的条件。

那里式替换的原则是让代码符合开立原则的一个重要保证。

那正是由于子类型的可替换性,才使得父类型的模块在无需修改的情况下就可以扩展。

关于接口隔离原则ISP它的意思是把功能实现在接口中,而不是类中使用多个专门的接口。

比使用单一的总接口要好。

举个例子啊,我们对电脑呢有不同的使用方式。

比如说写作、通讯啊、看电影、打游戏、上网、编程,还有计算和数据存储啊等等。

那如果我们把这些功能都说明在电脑的抽象类当中啊,那我们的上网本和PC机,还有服务器和笔记本的实现类都要实现这些所有的接口,那这个就显得太复杂了。

所以呢我们就可以把这些功能接口隔离开。

比如说工作、学习接口、编程、开发接口、上网、娱乐接口、计算和数据服务接口。

那这样我们的各种不同功能的电脑就可以有所选择的继承这些接口。

那最后一个呢是依赖倒置原则。

Dip.他说的是高层模块不应该依赖于低层模块的实现,而是依赖于高层抽象。

我举个例子啊,墙面的开关呢不应该依赖于电灯的开关实现,而是应该依赖于一个抽象的开关标准接口。

那这样当我们扩展程序的时候啊,这个开关同样可以控制其他不同的灯,甚至不同的电器。

也就是说,电灯和其他电器继承并实现我们的标准开关接口。

而开关的厂商呢不需要关心我们要控制什么样的设备啊,只需要关心那个标准的开关标准。

那这个就是依赖倒置原则,讲完了收益的五原则。

那接下来我们再说一些其他的那第十一个原则呢叫做共同封闭原则。

Ccp他说的是一个包中所有的类啊,应该对同一种类型的变化关闭一个变化,影响了一个包,便影响了包中所有的类。

那这里有一个更简短的说法啊,就是一起修改的量应该组合在一起。

那如果必须修改应用程序里的代码,我们希望所有的修改都发生在一个包里,而不是分布在很多包里。

Ccp原则就是把因为某个同样的原因而需要修改的所有类组合到一个包里。

那如果有两个类,从物理上或者从概念上联系的非常紧密,它们通常一起发生改变,那么它们应该属于同一个包CCP原则。

延伸了开域原则里面的关闭概念。

当因为某个原因需要修改的时候,把需要修改的范围限制在一个最小的范围的包里,第十二个原则叫做共同重用原则。

Crp就是说包里的所有类要被一起重用,那如果你重用了其中一个类就要重用全部。

那换个说法呢就是说没有被一起重用的量,不应该组合在一起。

Crp原则帮助我们决定了哪些类应该放到同一个包里依赖一个包就是依赖这个包中所包含的一切。

当一个包发生了改变,并发布了新的版本。

那这个包的用户所使用的那部分可能没有任何变化,但仍然需要在新的包环境之下验证他们的工作。

所以说如果包里面包含没有被使用的类啊,即使这个用户不关心这个类是否有改变,但用户还是不得不升级这个包,并且对原来的功能加以重新测试。

那跟CCP比起来呢,CCP是让系统的维护者受益,它让包尽可能的大。

而CRP呢则让包尽可能的小,他们的出发点不一样,但是相互不冲突。

第十三个原则呢叫做好莱坞原则。

好莱坞原则就是一句话,don't call us you call you.那意思就是好莱坞的经纪人啊不希望你去联系他们,而是他们会在需要的时候来联系你。

也就是说所有的组件都是被动的,所有的组件初始化和调用都由容器来负责。

呃,简单来说呢就是由容器来控制程序之间的关系,而不是传统实现中由程序代码直接操控。

那这个也是所谓的控制反转的概念所在。

嗯,一是不创建对象,而是描述创建对象的方式。

二呢是在代码中对象与服务没有直接联系,而是用容器来负责将这些联系在一起。

控制权由应用代码中转到了外部容器。

那控制权的转移啊就是所谓的反转。

好莱坞原则就是LC或者DI的基础原则。

第十四个原则叫做高内聚低耦合。

这个原则是unix操作系统设计的经典原则啊,就是把模块间的耦合降到最低,努力让一个模块做到精益求精。

那这里的内聚呢指的是一个模块之内,各个元素彼此结合的紧密程度。

而耦合指的是一个软件结构之内,不同模块之间互联程度的度量内聚,意味着重用和独立。

而耦合呢意味着多米诺效应牵一发动全身。

那对于面向对象来说呢,你也可以看一看我在文中给的马萨诸塞州格登学院面向对象课程中的这一节讲义。

那接下来第十五个原则是惯例优于配置原则COC.那简单点说呢,就是将一些公认的配置方式和信息作为内部确诊的规则来使用。

比如说hibernate里面的映射文件。

那如果约定字段名和类属性一致的话,那基本上就可以不要这个配置文件了。

你的应用呢只需要指定不是convention的信息就可以了,从而减少了大量的convention,而又不得不花时间和精力啰里啰嗦的东西。

配置文件在很多时候啊相当影响开发效率,rails当中就很少有配置文件。

所以riils的fans号称它的开发效率是java开发的十倍。

那估计啊就是这个原因,妈妈呢也使用了COC原则。

当你执行MVN compile命令的时候啊,不需要指定源文件放在什么地方。

而编译后的class文件放置在什么地方,也不需要指定。

那这个就是COC原则。

第十六个原则叫做SOC,关注点分离SOC是计算机科学当中最重要的努力目标之一。

那这个原则就是说在软件开发当中啊,通过各种手段将问题的各个关注点分开。

那如果一个问题能分解为独立,并且较小的问题就是相对比较容易解决的。

如果问题太过于复杂,要解决问题,需要关注的点就太多了。

而程序员的能力是有限的,不能同时关注于问题的各个方面。

那正如程序员的记忆力,相对于计算机知识来说那么有限一样。

程序员解决问题的能力,相对于要解决问题的复杂性也是一样的,非常有限。

所以在我们分析问题的时候啊,如果我们把所有的东西混在一起来讨论,那么就会只有一个结果。

乱。

那实现关注点分离的方法主要有两种,一种是标准化,另一种呢是抽象和包装。

那所谓标准化呢,就是指定一套标准,让使用者都遵守它,将人们的行为统一起来。

那这样使用标准的人啊,就不用担心别人会有很多种不同的实现,让自己的程序不能和别人的配合。

就像是开发螺丝钉的人,只专注于开发螺丝钉就行了,而不用关注螺帽是怎么生产的。

反正螺帽和螺丝钉按照标准来,就一定能合得上,不断的把程序的某些部分抽象并包装起来,也是实现关注点分离的好方法。

嗯,一旦一个函数被抽象出来并实现了,那么使用函数的人就不用关心这个函数是如何实现的。

同样一旦一个类被抽象并实现了,那类的使用者也不用再关注于这个类的内部是如何实现的。

比如说组件、分层、面向服务等,这些概念都是在不同的层次上做抽象和包装,就使得使用者不用关心它的内部实现细节。

第十七个原则叫做契约式设计EBC.那DBC的核心思想呢就是对软件系统中元素之间的相互合作和责任与义务的比喻。

那这种比喻是从商业活动中客户与供应商达成契约得来的那如果在程序设计中一个模块提供了某种功能,那么首先他要期望所有调用他的客户模块都保证一定的进入条件,那这个就是模块的先验条件。

那其次呢它要保证退出时给出特定的属性。

那这个就是模块的后验条件。

另外呢,它还需要在进入的时候,假定在退出的时候保持一些特定的属性,也就是不变式。

最后第十八个原则叫做无环依赖原则ADP.也就是说包或者服务之间的依赖结构必须是一个直接的无环图形。

也就是说啊在依赖结构中不允许出现环啊,也就是循环依赖。

那如果包的依赖形成了环状结构,怎么打破这种循环依赖呢?有两种方法可以打破这种循环依赖的关系。

那第一种方法呢是创建新的包。

如果a和b还有c形成了环路依赖,那么我可以把这些共同类抽出来放到一个新的包d里面。

那这样呢就把c依赖a变成了c依赖d还有a依赖d从而打破了循环依赖的关系。

那第二种方法就是使用依赖倒置原则和接口分离原则,无环依赖原则。

Adp给我们解决了包之间关系耦合的问题。

在设计模块的时候啊,不能有循环依赖。

那谈完了这么多的软件设计原则,最后啊我再来介绍一些软件设计的读物。

第一份资料是一本书,叫做领域驱动设计。

嗯,这本书是领域驱动设计方面的经典之作。

全书围绕着设计和开发实践,结合了若干真实的项目案例,向读者阐述了如何在真实的软件开发当中应用领域驱动。

设计书里面给出了领域驱动设计的系统化方法,并将人们普遍接受的一些实践综合到一起,还融入了作者的见解和经验,展现了一些可扩展的设计新实践,以验证过的技术和便于应对复杂领域的软件项目开发的基本原则。

第二,本书叫做unix编程艺术。

那这本书主要介绍了unix系统领域中的设计和开发哲学思想、文化体系、原则与经验。

他由公认的unix编程大师开源运动领袖人物之一埃里克雷蒙德经历多年写作而程,包括unix设计者在内的多位领域专家呀也给这本书贡献了宝贵的内容。

这本书的内容涉及社群文化、软件开发设计与实现覆盖面广,内容深邃,完全展现了作者及其深厚的经验积累和领域智慧。

第三份资料呢是clean architecture的一篇文章。

那如果你读过clean code和the clean coder这两本书啊,你就能猜得到这种clean系列一也是出自鲍豹大叔之手。

没错,就是鲍勃大叔的心血之作。

那除了这个网站,clean architecture也是一本书,这是一本很不错的架构类图书,对软件架构的元素、方法等讲的很清楚,里面的例子都比较简单,并带一些软件变化。

历史的讲述很开阔视野。

那第四份资料呢也是一篇文章,叫做the twelve factor app.如今,软件通常会作为一种服务来交付,他们被称为网络应用程序或者软件及服务sars. Twelve factor也构建sars应用提供了方法论。

嗯,这个也是架构师必读的文章,这篇文章在业内的影响力很大,是必须要读的。

第五篇文章叫做avoid over engineering.有时候我们会过度设计我们的系统,而过度设计会给我们带来额外的复杂度。

所以我们呢需要一些工程上的平衡。

那这篇文章就是一篇非常不错的告诉你什么是过度设计的文章。

第六份资料是instagram工程的三个黄金法则,一是使用稳定可靠的技术,二是不要重新发明轮子。

三是keep it very simple啊,我觉得这三条很不错。

那其实amazon也有两条工程法则,一个是自动化,一个是简化。

第七份资料是how to designer good API and why it matters.作者是幺说r block,那这个是google的一个关于如何设计好一个API的分享。

第八份资料是关于rustful API的设计,你可以学习并借鉴一下我的文中罗列的这些文章。

第九篇是the problem with logging一篇关于程序打日志的短文,它可以让你知道一些可能以往不知道的打日志需要注意的问题。

那最后呢我推荐一本书叫做concurrent programming for scalleable web architecture.那这是一本在线的免费书,教你如何架构一个可扩展的高性能的网站。

那其中呢谈到了一些不错的设计方法和知识。

好了,我总结一下今天分享的内容。

我认为品味不同是各层次程序员之间最大的区别。

这个也决定了他们所做出来的软件质量和价值。

因此呢我特意撰写了软件设计这一篇章,帮助那些想成长为软件工程师、设计师或者架构师的那些程序员,提高软件设计的品味,进而实现自己的目标。

那虽然很多程序员都忽略了对编程范式的学习,但是我觉得学习编程范式啊其实是非常非常重要的事儿。

它能够让你明白编程的本质和各种语言的编程方式。

为此呢我推荐了好几份学习资料,帮助你系统化的学习和理解。

随后我介绍了DRY避免重复原则、case简单原则、伊米特法则,还有面向对象的solid五原则等等多个经典的软件设计原则。

那最后呢我精选并推荐了软件设计方面的学习资料,比如领域驱动设计、unix编程艺术和clean architecture等等。

必读好书还有如何构建sars,如何避免过度设计、如何设计API、如何用程序打日志等等方面的资料。

我希望这些内容啊能对你有帮助。

从下节课开始呢,我们将进入程序员练级攻略的第五个篇章高手成长篇,敬请期待。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值