降低系统复杂度,减少重复代码,减少代码的变更。
软件架构设计的原则
一、单一职责原则SRP(Single Responsibility Principle)
对于一个类而言,应该仅有一个引起它变化的原因。不同的类具备不同的职责,各施其责,互不影响,各做各的事情。
千万不要让一个类干的事情太多!
二、开放封闭原则OCP(Open Closed Principle)
一个功能(类、模块、函数),对于扩展应该是开放的,但对于修改应该是封闭的。
当然,如果能够确保对整体架构不会产生任何影响,何必搞得那么复杂,直接改吧。
三、里氏替换原则LSP(Liskov Substitution Principle)
父类能够替换为子类,但子类不一定能替换为父类。也就是说,在代码中可以将父类全部替换为子类,程序不会报错,也不会在运行时出现任何异常,但反过来却不一定成立。
四、最少知识原则LKP(Least Knowledge Principle)
尽量减少对象之间的交互,从而减小类之间的耦合。简言之,一定要做到:低耦合,高内聚。
在做系统设计时,不要让一个类依赖于太多的其他类,需尽量减小依赖关系,否则,您死都不知道自己怎么死的。
五、接口隔离原则ISP(Interface Segregation Principle)
一个类与另一个类之间的依赖性,应该依赖于尽可能小的接口。
不要对外暴露没有实际意义的接口。接口是给别人调用的,那就不要为难别人了,尽可能保证接口的实用性。她好,我也好。
当需要对外暴露接口时,需要再三斟酌,如果真的没有必要对外提供的,就删了吧。
六、依赖倒置原则DIP(Dependence Inversion Principle)
高层模块不应该依赖于低层模块,它们应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。
应该面向接口编程,不应该面向实现类编程。面向实现类编程,相当于就是论事,那是正向依赖(正常人思维);面向接口编程,相当于通过事物表象来看本质,那是反向依赖,即依赖倒置(程序员思维)。
七、补充
组合/聚合复用原则(Composition/Aggregation Reuse Principle - CARP)
当要扩展类的功能时,优先考虑使用组合,而不是继承。这条原则在 23 种经典设计模式中频繁使用!
无环依赖原则(Acyclic Dependencies Principle - ADP)
当 A 依赖于 B ,B 依赖于 C ,C 于 A ,此时将出现循环依赖。在设计中应该避免这个问题,可通过引入“中介者模式”解决该问题。
共同封装原则(Common Closure Principle - CCP)
应该将易变的类放在同一个包里,将变化隔离出来。该原则是“开放-封闭原则”的衍生。
共同重用原则(Common Reuse Principle - CRP)
如果重用了包中的一个类,那么也就相当于重用了包中的所有类,我们要尽可能减小包的大小。
好莱坞原则(Hollywood Principle - HP)
好莱坞明星的经纪人一般都很忙,他们不想被打扰,往往会说:Don’t call me, I’ll call you. 翻译为:不要联系我,我会联系你。对应于软件设计而言,最著名的就是“控制反转”(或称为“依赖注入”),我们不需要在代码中主动的创建对象,而是由容器帮我们来创建并管理这些对象。
不要重复你自己(Don’t repeat yourself - DRY)
不要让重复的代码到处都是,要让它们足够的重用,所以要尽可能地封装。
保持简单与傻瓜(Keep it simple and stupid - KISS)
不要让系统变得复杂,界面简洁,功能实用,操作方便,要让它足够的简单,足够的傻瓜。
高内聚与低耦合(High Cohesion and Low Coupling - HCLC)
模块内部需要做到内聚度高,模块之间需要做到耦合度低。
约定优于配置(Convention over Configuration - COC)
尽量用约定来减少配置,这样才能提高开发效率,尽量做到“零配置”。很多开发框架都是这样做的。
命令查询分离(Command Query Separation - CQS)
在定义接口时,要做到哪些是命令,哪些是查询,要将它们分离。
关注点分离(Separation of Concerns - SOC)
将一个复杂的问题分离为多个简单的问题,然后逐个解决这些简单的问题,那么这个复杂的问题就解决了。难就难在如何进行分离。
契约式设计(Design by Contract - DBC)
模块或系统之间的交互,都是基于契约(接口或抽象)的,而不要依赖于具体实现。该原则建议我们要面向契约编程。
你不需要它(You aren’t gonna need it - YAGNI)
不要一开始就把系统设计得非常复杂,不要陷入“过度设计”的深渊。应该让系统足够的简单,而又不失扩展性,这是其中的难点。
编程范式与方法论
编程范式(Programming Paradigm)是某种编程语言的典型编程风格或者说是编程方式。
编程范式是编程语言的一种分类方式,它并不针对某种编程语言。就编程语言而言,一种语言可以适用多种编程范式。
简单来说,编程范式是程序员看待程序应该具有的观点。
多重编程范式: 并发编程,约束编程,数据流编程,声明式编程,分布式编程,函数式编程,泛型编程,命令式编程,逻辑编程,元编程,面向对象编程,和响应式编程…
面向对象编程OOP
面向对象的程序设计包括了三个基本概念:封装性、继承性、多态性。
面向对象的程序语言通过类、方法、对象和消息传递,来支持面向对象的程序设计范式。
对象
世间万事万物都是对象。
面向对象的程序设计的抽象机制是将待解问题抽象为面向对象的程序中的对象。利用封装使每个对象都拥有个体的身份。程序便是成堆的对象,彼此通过消息的传递,请求其它对象 进行工作。类
每个对象都是类的一个实体。
物以类聚——就是说明:类是相似对象的集合。类中的对象可以接受相同的消息。
换句话说:类包含和描述了“具有共同特性(数据元素)和共同行为(功能)”的一组对象。封装
封装(有时也被称为信息隐藏)就是把数据和行为结合在一个包中,并对对象的使用者隐藏数据的实现过程。
信息隐藏是面向对象编程的基本原则,而封装是实现这一原则的一种方式。接口
每个对象都有接口。接口不是类,而是对符合接口需求的类所作的一套规范。
接口说明类应该做什么但不指定如何作的方法。一个类可以有一个或多个接口。方法
方法决定了某个对象究竟能够接受什么样的消息。面向对象的设计有时也会简单地归纳为“将消息发送给对象”。
继承
继承的思想就是允许在已存在类的基础上构建新的类。
一个子类能够继承父类的所有成员,包括属性和方法。
继承的主要作用:通过实现继承完成代码重用;通过接口继承完成代码被重用。
继承是一种规范的技巧,而不是一种实现的技巧。多态
多态提供了“接口与实现分离”。多态不但能改善程序的组织架构及可读性,更利于开发出“可扩充”的程序。
继承是多态的基础。多态是继承的目的。
解决问题的方法
解决问题的关键是定位问题,问题一旦准确定位了,解决掉它往往就是水到渠成的事情。
想尽办法让错误现象再现
连错误现象都不能再现就去尝试解决问题,可能成功解决吗?就算被蒙对了,你确定问题哪天不会再次出现?
所以你必须把错误的重现路径找出来,让错误随时可以重现。把问题分段——切香肠法
把问题分成几个阶段,按照相关性猜测去逐个排查,最终就会比较准确的定位到问题的所在。
通过异常来解决问题—–专家法
通过异常可以精准的定位问题所在,精确到代码行,也许你不知道怎么解决,但是 有了那一堆的异常,到百度、Google或者stackoverflow.com上你至少有了搜索的资本,剩下的不多说了,就是一篇篇看帖子,不要抱怨有太多的重复帖子。
通过比较来解决问题—–比较法
比较法其实就是找不同,我们应该从程序本身,程序运行环境,操作系统,甚至浏览器等等多个角度去发现可能的不同。
要实践,不要臆断。要全面,不要片面。有时候重新来一遍是最快的方法——重生法
重来一遍?这个算方法吗?我也觉得不算,可是有时候重新来一遍往往就能够解决问题。
让问题简单化为来解决问题—–去干扰法
大概确定了程序BUG的问题所在,但是这个时候发现可能存在多个原因导致这一问题,这个时候应当采取每次只让一个原因产生作用,这样才能帮助我们更加准确的判断。总之,要去除干扰,不要让多个你怀疑的原因同时作用于问题。
寻找别人的帮助,收集更多的解决思路—–乱棍法
让多个人帮你提出一些思路,思路就够了,大家都很忙,你也不要太依赖别人啦。大家的思路是更加开放分散的,所以很乱,收集到思路之后你一个个尝试就是了,这就是所谓的乱棍法。
设计模式
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。
一、创建型模式
这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。
- 工厂模式(Factory Pattern)
- 抽象工厂模式(Abstract Factory Pattern)
- 单例模式(Singleton Pattern)
- 建造者模式(Builder Pattern)
- 原型模式(Prototype Pattern)
二、结构型模式
这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。
- 适配器模式(Adapter Pattern)
- 桥接模式(Bridge Pattern)
- 过滤器模式(Filter、Criteria Pattern)
- 组合模式(Composite Pattern)
- 装饰器模式(Decorator Pattern)
- 外观模式(Facade Pattern)
- 享元模式(Flyweight Pattern)
- 代理模式(Proxy Pattern)
三、行为型模式
这些设计模式特别关注对象之间的通信。
- 责任链模式(Chain of Responsibility Pattern)
- 命令模式(Command Pattern)
- 解释器模式(Interpreter Pattern)
- 迭代器模式(Iterator Pattern)
- 中介者模式(Mediator Pattern)
- 备忘录模式(Memento Pattern)
- 观察者模式(Observer Pattern)
- 状态模式(State Pattern)
- 空对象模式(Null Object Pattern)
- 策略模式(Strategy Pattern)
- 模板模式(Template Pattern)
- 访问者模式(Visitor Pattern)
四、J2EE 模式
这些设计模式特别关注表示层。这些模式是由 Sun Java Center 鉴定的。
- MVC 模式(MVC Pattern)
- 业务代表模式(Business Delegate Pattern)
- 组合实体模式(Composite Entity Pattern)
- 数据访问对象模式(Data Access Object Pattern)
- 前端控制器模式(Front Controller Pattern)
- 拦截过滤器模式(Intercepting Filter Pattern)
- 服务定位器模式(Service Locator Pattern)
- 传输对象模式(Transfer Object Pattern)
【瞎子】熟视无睹:自己天天在用但是一直都没有关注细节——能用就行了!!!
【聋子】充耳不闻:别人说过很多遍了自己从来没有上心过——管我鸟事啊???
【瘸子】浅尝辄止:让问题现象消失了就认为是彻底解决了——自我感觉良好啊
【傻子】人云亦云:别人随口说了一句自己就拿着当真理了——纸上得来终觉浅