极客时间-左耳听风-程序员攻略-软件设计

程序员练级攻略:软件设计

编程范式

学习编程范式可让你明白编程的本质和各类语言的编程方式。所以,我推荐如下一些资料,以帮助你系统化地学习和理解。html

一些软件设计的相关原则

  • Don’t Repeat Yourself (DRY) ,DRY 是一个最简单的法则,也是最容易被理解的。但它也多是最难被应用的(由于要作到这样,咱们须要在泛型设计上作至关的努力,这并非一件容易的事)。它意味着,当在两个或多个地方发现一些类似代码的时候,咱们须要把它们的共性抽象出来造成一个惟一的新方法,而且改变现有地方的代码让它们以一些合适的参数调用这个新的方法。git

  • Keep It Simple, Stupid(KISS) ,KISS 原则在设计上可能最被推崇,在家装设计、界面设计和操做设计上,复杂的东西愈来愈被众人所鄙视了,而简单的东西愈来愈被人所承认。宜家(IKEA)简约、高效的家居设计和生产思路;微软(Microsoft)“所见即所得”的理念;谷歌(Google)简约、直接的商业风格,无一例外地遵循了“KISS”原则。也正是“KISS”原则,成就了这些看似神奇的商业经典。而苹果公司的 iPhone 和 iPad 将这个原则实践到了极至。程序员

  • Program to an interface, not an implementation,这是设计模式中最根本的哲学,注重接口,而不是实现,依赖接口,而不是实现。接口是抽象是稳定的,实现则是多种多样的。在面向对象的 S.O.L.I.D 原则中会提到咱们的依赖倒置原则,就是这个原则的另外一种样子。还有一条原则叫 Composition over inheritance(喜欢组合而不是继承),这两条是那 23 个经典设计模式中的设计原则。github

  • You Ain’t Gonna Need It (YAGNI) ,这个原则简而言之为——只考虑和设计必须的功能,避免过分设计。只实现目前须要的功能,在之后你须要更多功能时,能够再进行添加。如无必要,勿增复杂性。软件开发是一场 trade-off 的博弈。数据库

  • Law of Demeter,迪米特法则 (Law of Demeter),又称“最少知识原则”(Principle of Least Knowledge),其来源于 1987 年荷兰大学的一个叫作 Demeter 的项目。克雷格·拉尔曼(Craig Larman)把 Law of Demeter 又称做“不要和陌生人说话”。在《程序员修炼之道》中讲 LoD 的那一章将其叫做“解耦合与迪米特法则”。编程

    关于迪米特法则有一些很形象的比喻:1) 若是你想让你的狗跑的话,你会对狗狗说仍是对四条狗腿说?2) 若是你去店里买东西,你会把钱交给店员,仍是会把钱包交给店员让他本身拿?和狗的四肢说话?让店员本身从钱包里拿钱?这听起来有点儿荒唐,不过在咱们的代码里这几乎是见怪不怪的事情了。对于 LoD,正式的表述以下:设计模式

    对于对象 ‘O’ 中一个方法’M’,M 应该只可以访问如下对象中的方法:api

    1. 对象 O;
    2. 与 O 直接相关的 Component Object;
    3. 由方法 M 建立或者实例化的对象;
    4. 做为方法 M 的参数的对象。
  • 面向对象的 S.O.L.I.D 原则服务器

    • SRP(Single Responsibility Principle)- 职责单一原则。关于单一职责原则,其核心的思想是:一个类,只作一件事,并把这件事作好,其只有一个引发它变化的缘由。单一职责原则能够看做是低耦合、高内聚在面向对象原则上的引伸,将职责定义为引发变化的缘由,以提升内聚性来减小引发变化的缘由。

    职责过多,可能引发它变化的缘由就越多,这将致使职责依赖,相互之间就产生影响,从而极大地损伤其内聚性和耦合度。单一职责,一般意味着单一的功能,所以不要为一个模块实现过多的功能点,以保证明体只有一个引发它变化的缘由。restful

    • OCP(Open/Closed Principle)- 开闭原则。关于开发封闭原则,其核心的思想是:模块是可扩展的,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。对扩展开放,意味着有新的需求或变化时,能够对现有代码进行扩展,以适应新的状况。对修改封闭,意味着类一旦设计完成,就能够独立完成其工做,而不要对类进行任何修改。
    • LSP(Liskov substitution principle)- 里氏代换原则。软件工程大师罗伯特·马丁(Robert C. Martin)把里氏代换原则最终简化为一句话:“Subtypes must be substitutable for their base types”。也就是,子类必须可以替换成它们的基类。即子类应该能够替换任何基类可以出现的地方,而且通过替换之后,代码还能正常工做。另外,不该该在代码中出现 if/else 之类对子类类型进行判断的条件。里氏替换原则 LSP 是使代码符合开闭原则的一个重要保证。正是因为子类型的可替换性才使得父类型的模块在无需修改的状况下就能够扩展。
    • ISP(Interface Segregation Principle )- 接口隔离原则。接口隔离原则的意思是把功能实如今接口中,而不是类中,使用多个专门的接口比使用单一的总接口要好。举个例子,咱们对电脑有不一样的使用方式,好比:写做、通信、看电影、打游戏、上网、编程、计算和数据存储等。

    若是咱们把这些功能都声明在电脑的抽象类里面,那么,咱们的上网本、PC 机、服务器和笔记本的实现类都要实现全部的这些接口,这就显得太复杂了。因此,咱们能够把这些功能接口隔离开来,如工做学习接口、编程开发接口、上网娱乐接口、计算和数据服务接口,这样,咱们的不一样功能的电脑就能够有所选择地继承这些接口。

    • DIP(Dependency Inversion Principle)- 依赖倒置原则。高层模块不该该依赖于低层模块的实现,而是依赖于高层抽象。举个例子,墙面的开关不该该依赖于电灯的开关实现,而是应该依赖于一个抽象的开关的标准接口。这样,当咱们扩展程序的时候,开关一样能够控制其它不一样的灯,甚至不一样的电器。也就是说,电灯和其它电器继承并实现咱们的标准开关接口,而开关厂商就能够不须要关于其要控制什么样的设备,只须要关心那个标准的开关标准。这就是依赖倒置原则。
  • CCP(Common Closure Principle) - 共同封闭原则,一个包中全部的类应该对同一种类型的变化关闭。一个变化影响一个包,便影响了包中全部的类。一个更简短的说法是:一块儿修改的类,应该组合在一块儿(同一个包里)。若是必须修改应用程序里的代码,那么咱们但愿全部的修改都发生在一个包里(修改关闭),而不是遍及在不少包里。

    CCP 原则就是把由于某个一样的缘由而须要修改的全部类组合进一个包里。若是两个类从物理上或者从概念上联系得很是紧密,它们一般一块儿发生改变,那么它们应该属于同一个包。CCP 延伸了开闭原则(OCP)的“关闭”概念,当由于某个缘由须要修改时,把须要修改的范围限制在一个最小范围内的包里。

  • CRP(Common Reuse Principle)- 共同重用原则 ,包的全部类被一块儿重用。若是你重用了其中的一个类,就重用所有。换个说法是,没有被一块儿重用的类不该该组合在一块儿。CRP 原则帮助咱们决定哪些类应该被放到同一个包里。依赖一个包就是依赖这个包所包含的一切。

    当一个包发生了改变,并发布新的版本,使用这个包的全部用户都必须在新的包环境下验证他们的工做,即便被他们使用的部分没有发生任何改变。由于若是包中包含未被使用的类,即便用户不关心该类是否改变,但用户仍是不得不升级该包并对原来的功能加以从新测试。CCP 则让系统的维护者受益。CCP 让包尽量大(CCP 原则加入功能相关的类),CRP 则让包尽量小(CRP 原则剔除不使用的类)。它们的出发点不同,但不相互冲突。

  • 好莱坞原则 - Hollywood Principle ,好莱坞原则就是一句话——“don’t call us, we’ll call you.”。意思是,好莱坞的经纪人不但愿你去联系他们,而是他们会在须要的时候来联系你。也就是说,全部的组件都是被动的,全部的组件初始化和调用都由容器负责。

    简单来说,就是由容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:1) 不建立对象,而是描述建立对象的方式。2)在代码中,对象与服务没有直接联系,而是容器负责将这些联系在一块儿。控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。好莱坞原则就是IoC(Inversion of Control)DI(Dependency Injection)的基础原则。

  • 高内聚, 低耦合 & - High Cohesion & Low/Loose coupling,这个原则是 UNIX 操做系统设计的经典原则,把模块间的耦合降到最低,而努力让一个模块作到精益求精。内聚,指一个模块内各个元素彼此结合的紧密程度;耦合指一个软件结构内不一样模块之间互连程度的度量。内聚意味着重用和独立,耦合意味着多米诺效应牵一发动全身。对于面向对象来讲,你也能够看看马萨诸塞州戈登学院的面向对象课中的这一节讲义High Cohesion and Low Coupling

  • CoC(Convention over Configuration)- 惯例优于配置原则 ,简单点说,就是将一些公认的配置方式和信息做为内部缺省的规则来使用。例如,Hibernate 的映射文件,若是约定字段名和类属性一致的话,基本上就能够不要这个配置文件了。你的应用只须要指定不 convention 的信息便可,从而减小了大量 convention 而又不得不花时间和精力啰里啰嗦的东东。

    配置文件在不少时候至关影响开发效率。Rails 中不多有配置文件(但不是没有,数据库链接就是一个配置文件)。Rails 的 fans 号称其开发效率是 Java 开发的 10 倍,估计就是这个缘由。Maven 也使用了 CoC 原则,当你执行 mvn -compile命令的时候,不须要指定源文件放在什么地方,而编译之后的 class 文件放置在什么地方也没有指定,这就是 CoC 原则。

  • SoC (Separation of Concerns) - 关注点分离 ,SoC 是计算机科学中最重要的努力目标之一。这个原则,就是在软件开发中,经过各类手段,将问题的各个关注点分开。若是一个问题能分解为独立且较小的问题,就是相对较易解决的。问题太过于复杂,要解决问题须要关注的点太多,而程序员的能力是有限的,不能同时关注于问题的各个方面。

    正如程序员的记忆力相对于计算机知识来讲那么有限同样,程序员解决问题的能力相对于要解决的问题的复杂性也是同样的很是有限。在咱们分析问题的时候,若是咱们把全部的东西混在一块儿讨论,那么就只会有一个结果——乱。实现关注点分离的方法主要有两种,一种是标准化,另外一种是抽象与包装。标准化就是制定一套标准,让使用者都遵照它,将人们的行为统一块儿来,这样使用标准的人就不用担忧别人会有不少种不一样的实现,使本身的程序不能和别人的配合。

    就像是开发镙丝钉的人只专一于开发镙丝钉就好了,而不用关注镙帽是怎么生产的,反正镙帽和镙丝钉按照标准来就必定能合得上。不断地把程序的某些部分抽象并包装起来,也是实现关注点分离的好方法。一旦一个函数被抽象出来并实现了,那么使用函数的人就不用关心这个函数是如何实现的。一样的,一旦一个类被抽象并实现了,类的使用者也不用再关注于这个类的内部是如何实现的。诸如组件、分层、面向服务等这些概念都是在不一样的层次上作抽象和包装,以使得使用者不用关心它的内部实现细节。

  • DbC(Design by Contract)- 契约式设计 ,DbC 的核心思想是对软件系统中的元素之间相互合做以及“责任”与“义务”的比喻。这种比喻从商业活动中“客户”与“供应商”达成“契约”而得来。若是在程序设计中一个模块提供了某种功能,那么它要:

    • 指望全部调用它的客户模块都保证必定的进入条件:这就是模块的先验条件(客户的义务和供应商的权利,这样它就不用去处理不知足先验条件的状况)。
    • 保证退出时给出特定的属性:这就是模块的后验条件(供应商的义务,显然也是客户的权利)。
    • 在进入时假定,并在退出时保持一些特定的属性:不变式。
  • ADP(Acyclic Dependencies Principle)- 无环依赖原则 ,包(或服务)之间的依赖结构必须是一个直接的无环图形,也就是说,在依赖结构中不容许出现环(循环依赖)。若是包的依赖造成了环状结构,怎么样打破这种循环依赖呢?

    有两种方法能够打破这种循环依赖关系:第一种方法是建立新的包,若是 A、B、C 造成环路依赖,那么把这些共同类抽出来放在一个新的包 D 里。这样就把 C 依赖 A 变成了 C 依赖 D 以及 A 依赖 D,从而打破了循环依赖关系。第二种方法是使用 DIP(依赖倒置原则)和 ISP(接口分隔原则)设计原则。无环依赖原则(ADP)为咱们解决包之间的关系耦合问题。在设计模块时,不能有循环依赖。

一些软件设计的读物

相关文章
相关标签/搜索