02 架构的方法论
设计文档
上一节说到了架构设计文档的编写,架构师做架构,做设计是第一步,设计中架构视图又是最重要的一环,UML作图是基本功,怎么画容易,但如何把握一个度,让架构的相关方能够见图知意,清晰理解就不那么容易了。UML有10种视图,常见的有7种,在不同的架构阶段,表现形式如下图。
李老师通过分享了2个案例,来说明自己怎么是突破一般开发,成为”架构师“的,对大部分人有一定的启发意义,这些虽然不是技术但与我们生活息息相关,当机会来临能结合人、时、利,充分发挥自己的主观能动性来达到破局,让自己成为公司团队中不可或缺的那类人。
其中比较清晰的一项是:主动承担”架构“的角色,去做超出一般开发所做的事情,去梳理”业务和技术“,通过做架构设计让周围的人认可你,依赖你。并能引导大家向所期望的方向走。现在开发人员大多是心里明白,表达不清晰,更不用说画图了,这点是需要大家锻炼的。
做事情要从战略上藐视,战术上重视,既能有超越别人的眼光,从高处往下看,也能深入其中,静下心把事情看穿,开发也如此,多向前看一步,多往后想一点。面对开发中的问题才能更加游刃有余,从容不迫。
编程语言
软件的发展,离不开语言的发展。
任何事物的发展都不是一蹴而就的,计算机的语言也如此,由莱布尼茨发明的微积分和二进制,以及后来布尔对前者的体系化丰富了逻辑运算,就有了布尔逻辑符号等语言。
人类第一位程序员,Ada用打孔纸带写出了第一个软件程序,包含了循环和子程序。
有了对语言的诉求,才有了后来图灵、冯诺依曼对计算机的开创。
每一种cpu都有独特的机器语言,因而需要不同的汇编语言。
50年代初,记住指令,助记符 的汇编语言——面向机器的编程
高级语言:按照逻辑编程,不是按照指令,架构化的basic语言(quick basic、visual basic等)——面向人的编程
面向对象的语言:c++、go、java等
由此由语言的发展史可见,语言主要分为以下三种:
其一 是过程式。过程式就是以一条条命令的方式,让计算机按我们的意愿来执行。
其二 是函数式。函数式本质上是过程式编程的一种约束,它最核心的主张就是变量不可变,函数尽可能没有副作用(对于通用语言来说,所有函数都没副作用是不可能的,内部有 IO 行为的函数就有副作用)。既然变量不可变,函数没有副作用,自然人们犯错的机会也就更少,代码质量就会更高。函数式语言的代表是 Haskell、Erlang 等等。
其三是 面向对象。面向对象在过程式的基础上,引入了对象(类)和对象方法(类成员函数),面向对象语言的代表是 Java、C#、C++、Go 等等,核心思想是契约。
计算机包含硬件和软件,硬件一般通常有“五大件”组成:输入设备、输出设备、存储器、运算器和控制器;软件又是其中最重要的,没有软件计算机就没有了灵魂。
编程的目的:用计算机来解决现实世界的问题。
什么是对象?
Booch对于对象的描述:对象具有状态、行为和标识。
状态:表明每个对象可以有自己的数据。
行为:表明每个对象可以产生行为。
标识:表明每个对象都区别于其它的对象。(唯一的地址)
对象的三要素:封装、继承、多态。核心是多态
存在虽然就是合理的,但我们不能觉得是理所当然的,就好比现实是这样的,能超越这个现实,新的概念或新的想法的时候,能做出判断是好是坏。是否代表先进生产力的发展方向。更不要觉得代码就是这个样子,生活就是这个样子,因为明天会更好,未来会更好。当然新的变化会带来新的挑战, 只有用犀利的眼光去衡量判断做出正确的选择,敢于去尝试,既能俯视他们,也能扎根于深处,就能立于不败之地。
什么是框架?
框架是构成一类特定软件可复用设计的一组相互协作的类,是对某一类架构方案可复用的设计与实现
解决特定域问题的方案。框架本身也是一个架构,规定了应用的体系结构。任何对框架设计的实际性修改都会大大降低框架所带来的好处,因为框架对应用的最主要贡献在于它所定义的体系结构,框架的设计必须尽可能的灵活、可扩充。
框架的作用
如同框架结构的大厦的框架
简化应用开发者的工作
实现了多种设计模式,是应用开发不需要花太大的力气,就能设计出结构良好的程序来
对应的就是:模块化、可重用、可扩展、简单性和可维护性
设计模式
软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
设计模式是用于解决某一种问题的通用的解决方案。
设计模式也是语言中立的。
设计模式贯彻了设计原则。
GOF提出了三大类23种基本的设计模式:
创建模式
1. Factory Method(工厂方法)
2. Abstract Factory(抽象工厂)
3. Builder(建造者)
4. Prototype(原型)
5. Singleton(单例)
行为模式
13. Interpreter(解释器)
14. Template Method(模板方法)
15. Chain of Responsibility(责任链)
16. Command(命令)
17. Iterator(迭代器)
18. Mediator(中介者)
19. Memento(备忘录)
20. Observer(观察者)
21. State(状态)
22. Strategy(策略)
23. Visitor(访问者)
结构模式
6. Adapter Class/Object(适配器)
7. Bridge(桥接)
8. Composite(组合)
9. Decorator(装饰)
10. Facade(外观)
11. Flyweight(享元)
12. Proxy(代理)
设计的原则(SOLID原则)
1、开闭原则(Open Close Principle)
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。
2、里氏代换原则(Liskov Substitution Principle)
里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。—— From Baidu 百科
3、依赖倒转原则(Dependence Inversion Principle)
这个是开闭原则的基础,具体内容:真对接口编程,依赖于抽象而不依赖于具体。
4、接口隔离原则(Interface Segregation Principle)
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。
5、迪米特法则(最少知道原则)(Demeter Principle)
为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
6、合成复用原则(Composite Reuse Principle)
原则是尽量使用合成/聚合的方式,而不是使用继承。
依赖倒置原则——举例Java开发的web应用不需要依赖Tomcat容器,只需要依赖j2ee规范,web应用实现j2ee的规范的servlet接口,然后把应用程序打包部署到容器中,然后web容器启动就可以处理http请求了,高层模块不依赖底层模块,同样spring、jdbc的实现同样如此,用到了依赖倒置原则,让我们开发人员不必关系高层。
其中,开闭原则是总纲,它告诉我们要对扩展开放,对修改关闭;里氏替换原则告诉我们不要破坏继承体系;依赖倒置原则告诉我们要面向接口编程;单一职责原则告诉我们实现类要职责单一;接口隔离原则告诉我们在设计接口的时候要精简单一;迪米特法则告诉我们要降低耦合度;合成复用原则告诉我们要优先使用组合或者聚合关系复用,少用继承关系复用。
设计模式的四要素:名称、问题、解决方案、效果
设计模式、框架和架构的关系
设计模式与框架的关系
1、设计模式比框架更抽象。框架能够用代码来表示,而设计模式只有其实例才能表示为代码。
2、设计模式比框架更小的体系结构单元。一个典型的框架包括了多个设计模式,而反之绝非如此。
3、框架比设计模式更加的特例化。框架总是针对一个特定的应用领域。
框架与架构的关系
——框架只是一种特定的软件,框架本身也有架构。
——可以通过架构框架化达到“架构重用”的目的,如spring框架的使用
软件设计的最终目的,是使软件大道“高内聚、松耦合”,从而使软件:
易扩展——易于增加新的功能
更强壮——不容易被粗心的程序员破坏
可移植——能够在多样的环境下运行
更简单——容易理解、容易维护
相反,“臭味”:
僵硬——不易改变
脆弱——只想改变A,结果B就被意外破坏
不可移植——不能适应环境的变化
导致误用的陷阱——做错误的事比做正确的事更容易,引诱程序员破坏原有的设计
晦涩——代码难以理解
过度设计、copy-paste代码。 在设计中要警惕复杂的解决方案,过于复杂的设计限制了可扩展性。测试同事能很轻松地理解解决方案来验证。
总结
做需求开发,我们需要不断迭代进行敏捷开发,把问题前置来看,我们应该对设计进行敏捷,不是过程。用软件设计的六大原则和设计模式去开发,去更快的响应需求和变化,从而真正实现软件带来的核心效益——降本增效。优秀的程序员不是懂得了多少技术而NX,而是乐于拥抱需求的变化,让自己有”空怀若谷“的心态,以不变应万变,真正体会到软件设计的奥妙之美。
评论