1、前言
首先,我认为学习总结,要有所总,所结,就是有归纳后,能用自己的话
告诉别人!有所结,就是有所收获输出,一般我认为是思维导图
,所以,每篇文章前,我都会先给出文章的脑图:
2、正文
注意,本系列总结不会引用或提供原课程文章所有的内容或代码,只会作出思维导图,需要学习可购买课程 《iOS开发高手课 - 极客时间》
带问题找答案
- 模块粒度应该如何划分?
- 为什么要分层?
- 如何分层?
- 多团队如何协作?
文中提了4个问题,那么这4个问题怎么解答呢?解答前,我觉得还是要先说说为什么有架构这东西?只有理解为什么出现一个新事物,才能理解出现的原因和解决的问题,并且才能知道未来可能会出现什么新事物!
项目架构
为什么?
为什么有架构这东西?有过几年开发经验的同学一定听过或看过 23种设计模式
、SOLID 原则
、GRASP 原则
、奥卡姆剃刀定律
、敏捷开发
等,那么为什么设计模式是23种呢? SOLID 分别代表什么呢?如果只是学习设计模式,SOLID 分别代表什么,那样的话,其实并不能理解为什么?只是解答了,是什么!所以,首先,要给大家介绍一下这些历史和背景,大家才能更好的明白这些原则和模式。
1994 年 10 月 21 日,Erich Gamma(埃里希·伽玛)、Richard Helm(理查德·赫尔姆)、Ralph Johnson(拉尔夫·约翰逊)和John Vlissides(约翰·弗利西德斯)合著《设计模式:可复用面向对象软件的基础》
(Design Patterns: Elements of Reusable Object-Oriented Software)出版!后以“四人帮”著称,GoF
,又称 Gang of Four
,所以本书也被称为 GoF book
。此书是软件工程领域有关软件设计的巨著,提出和总结了对于一些常见软件设计问题的标准解决方案,称为软件设计模式,书中提出的 23 种设计模式
,书中的设计模式也被成为“四人帮设计模式”,这些模式当初他们是打算写成论文发表,写着后来发现太长了,最后不得以改为出版书。
所以,大家明白了现在很多xx语言的设计模式,从那里来?为什么是23种?这本书很牛逼,并且这四位作者也很利害,大家自行搜索。关于设计模式就先说到这里,下面在看看其它。
1997 年 10 月 30 日,Craig Larman(克雷格·拉曼)出版《UML和模式应用》
(Applying UML and Patterns),书中提出 GRASP
(General Responsibility Assignment Software Principles,通用职责分配软件原则),与其将 GRASP 称之为设计模式(Pattern),不如称之为设计原则(Principles),因为它是站在面向对象设计
(OOD:Object-Oriented Design)的角度,告诉我们怎样设计问题空间中的类与分配它们的行为职责,以及明确类之间的相互关系等,GRASP 核心思想是职责分配,用职责设计对象。而不像 GoF设计模式那样是针对特定问题而提出的解决方案。因此 GRASP 站在一个更高的角度来看待面向对象软件的设计,它是 GoF设计模式 的基础(可以理解为更宏观的角度)。
2001 年 10 月 12 日,Robert C. Martin(罗伯特·C·马丁)出版了《敏捷软件开发:原则、模式与实践》
(Agile Software Development: Principles, Patterns, and Practices)一书,描述了面向对象编程
(OOP:Object-oriented Programming)和面向对象设计
(OOD:Object-Oriented Design)的五个原则,他称之为 SOLID 原则
(单一功能、开闭原则、里氏替换、接口隔离以及依赖反转,每个原则的首字母组合在一起)。需要注意的时,这些原则有些在此书前就提出或相似的概念,其中依赖倒转原则就是1996年提出来的。关于世界顶级软件开发大师罗伯特·C·马丁
(Robert C. Martin),大家可能更熟悉 Bob大叔
、鲍勃叔叔
等称呼,因为他已经有50多年
的软件开发经验(1969年至今),如今 67 岁啦!其中《架构整洁之道》是创造“Clean神话”的Bob大叔在架构领域的登峰之作,还有《代码整洁之道》(Clean Code: A Handbook of Agile Software Craftsmanship)不知道大家熟悉吗?
以上就是经典的面向对象的设计原则或模式的由来,大家是不是有一点印象啦!总体来说,GRASP
处于最上层,SOLID
基于它再进一步细化阐述,GOF
再根据这些原则进一步的归纳出更具体的模式。
是什么?
不知道大家有没有发现上面提到的 OOD
和 OOP
,OOD 是:面向对象设计
(Object-Oriented Design),OOP 是:面向对象编程
(Object-oriented Programming)。
是什么?当我们在谈论项目架构时,我们在说什么?
,其实就是面向对象
编程!那么面向对象
前,又是怎么样的呢?所以,我们不得不回到历史,看看究竟发生了什么,为什么现在如今的面向对象那么流行?
- 1940年以前:
面向机器
- 脱离机器第一步:
面向过程
- 第一次软件危机:
结构化程序设计
- 第二次软件危机:
面向对象程序设计
面向机器
使用二进制码来表示机器能够识别和执行的指令和数据。简单来说,就是直接编写 0 和 1 的序列来代表程序语言。由于机器语言实在是太难编写了,于是就发展出了汇编语言。
面向过程
相比面向机器的语言来说,已经不再关注机器本身的操作指令、存储等方面,而是关注如何一步一步的解决具体的问题,即:解决问题的过程。
结构化程序设计
(Structured Programming)是一种编程范型,它采取“自顶向下、逐步细化、模块化”的指导思想,使用子程序(函数就是一种子程序)、代码区块、for循环以及while循环等结构,来替换传统的goto,希望借此来改善计算机程序的明晰性、质量以及开发时间,并且避免写出面条式代码。结构化程序设计本质上还是一种面向过程的设计思想。
面向对象程序设计
早在 1967 年的 Simula 语言中就开始提出来了,但第二次软件危机促进了面向对象的发展。 面向对象真正开始流行是在 1980s 年代,主要得益于 C++ 的功劳,后来的 Java、C# 把面向对象推向了新的高峰。到现在为止,面向对象已经成为了主流的开发思想。
分支故事1:第一次软件危机最典型的例子莫过于 IBM 的 System/360 的操作系统开发。佛瑞德·布鲁克斯
(Frederick P. Brooks, Jr.)作为项目主管,率领 2000 多个程序员夜以继日的工作,共计花费了 5000 人一年的工作量,写出将近 100 万行的源码,总共投入 5 亿美元,是美国的“曼哈顿”原子弹计划投入的 1/4。尽管投入如此巨大,但项目进度却一再延迟,软件质量也得不到保障。布鲁克斯后来基于这个项目经验而总结的《人月神话》
(The Mythical Man-Month)一书,成了史上最畅销的软件工程书籍。这本书也值得大家看看,银弹
就是书中提到的经典概念。(引用来源:程序设计思想发展 - 二十一岁的有德)
分支故事2:实际上面向对象就是个形容词,那么这个词最早出现在哪里呢?最早大概1970年左右,已经提出了“面向对象系统”这个概念,面向对象系统有两层含义,第一,系统是由对象组成的;第二,对象之间可以互相发消息。从这个角度来讲这两点才是“面向对象”的第一义,后来的封装、继承、多态则是非第一义,或者称为最佳实践。(引用来源:面向对象编程的兴衰-InfoQ)
说到这里,大家是不是有什么新想法啦!这个就是为什么大家现在编程和软件开发行业中,只剩下这些原则和模式,因为都是面向对象
!详细的历史和资料可以参考查看:编程语言历史 - 维基百科,无法翻墙的可以看:程序设计思想发展 - 二十一岁的有德。这里就不深入描述了,大学时应该学习过,如果忘记了再重温一次吧!
软件开发基本概念
- 面向过程编程(OPP:Procedure-Oriented Programming)
- 结构化程序设计(Structured Programming)
- 面向对象分析(OOA:Object-Oriented Analysis)
- 面向对象设计(OOD:Object-Oriented Design)
- 面向对象编程(OOP:Object-oriented Programming)
- 面向切面编程(AOP:Aspect Oriented Programming)
以上就是软件开发概念一些概念,从历史上了解这些东西,对我们理解项目架构起了必要的作用。现在我们知道了为什么,是什么,软件开发直到现在,都是为了更好的编程!更好的开发!
,所以我们理解了编程的历史,知道面对对象编程的重要性后,自然就需要知道有这些原则和模式,优秀的实践,来解决软件危机的银弹!
STUPID 原则
抱歉,你的代码就是那么的
STUPID
!烂代码有什么特点呢?没有人喜欢听到别人评价他的代码很愚蠢,而且这样做也很容易冒犯别人,所以不要说出来?平心而论:全世界中大部分代码都是不可维护的,因为它们都是乱糟糟一团的!
Singleton - 单态
Tightcoupling - 紧密耦合
Untestability - 不可测试
Premature Optimization - 过早优化
Indescriptive Naming - 胡乱命名
Duplication - 重复代码
本节内容来源:Don’t be STUPID: GRASP SOLID!,中文译文:面向对象设计原则:不要STUPID - rcom10002的专栏。
SOLID 原则
单一功能
原则(TheSingle
Responsibility Principle):对象功能要单一,不要在一个对象里添加很多功能。开放封闭
原则(TheOpen
Closed Principle):扩展是开放的,修改是封闭的。里氏替换
原则(Liskov
Substitution Principle):子类对象是可以替代基类对象的。(子类可以扩展父类的功能,但不能改变父类原有的功能。)接口隔离
原则(TheInterface
Segregation Principle):接口的用途要单一,不要在一个接口上根据不同入参实现多个功能。依赖反转
原则(TheDependency
Inversion Principle):方法应该依赖抽象,不要依赖实例。iOS 开发就是高层业务方法依赖于协议。
SOLID 原则在前面已经讲解了由来,称为五大设计原则
,但后来,又出现六大设计原则、七大设计原则
,另外2个原则:
迪米特
法则(Law of Demeter):一个对象对其他对象有尽可能少的了解,不和陌生人说话。
合成复用
原则(CARP,Composition/Aggregate Reuse Principle,合成复用原则(组合/聚合复用原则)):将已有的对象纳入新对象中,使之成为新对象的一部分,作为新对象的成员对象来实现的,新对象可以调用已有对象的功能,从而达到复用。
所以,大家在网上如果看到 x条设计原则
、面向对象设计原则xxx
时,大家是不是能更加理解这些编程思想,而不是看到一条一条的规则,学习怎么使用它们,但是并不清楚为什么要学习,这是学习最可怕的地方
,这是我认为最可怕的。另外,这里强调设计原则
(Principle),而非设计模式
(Patterns),也是需要注意的点。
GRASP 原则
- 创造者模式 (Creator Pattern)
- 信息专家模式 (Information Expert Pattern)
- 低耦合模式 (Low Coupling Pattern)
- 高内聚模式 (High Cohesion Pattern)
- 控制器模式 (Controller Pattern)
- 多态模式 (Polymorphism Pattern)
- 纯虚构模式 (Pure Fabrication Pattern)
- 中介模式 (Indirection Pattern)
- 受保护变化模式 (Protected Variations Pattern)
GRASP
(General Responsibility Assignment Software Principles,通用职责分配软件原则) 共有9种模式,这里也不细说了,大家自行搜索学习,如果需要可以购买书本 《UML和模式应用》
(Applying UML and Patterns) 。
Design Patterns (设计模式)
- 创建范例
- 抽象工厂 (Abstract Factory)
- 构造器 (Builder pattern)
- 工厂方法 (Factory Method pattern)
- 原型 (Prototype pattern)
- 单例模式 (Singleton pattern)
- 结构范例
- 适配器(Adapter pattern)
- 桥接(Bridge pattern)
- 组合(Composite pattern)
- 装饰(Decorator pattern)
- 外观(Façade pattern)
- 享元(Flyweight pattern)
- 代理(Proxy pattern)
- 行为范例
- 职责链(Chain-of-responsibility pattern)
- 命令(Command pattern)
- 翻译器(Interpreter pattern)
- 迭代器(Iterator pattern)
- 中介者(Mediator pattern)
- 回忆(Memento pattern)
- 观察者(Observer pattern)
- 状态机(State pattern)
- 策略(Strategy pattern)
- 模板方法(Template method pattern)
- 参观者(Visitor pattern)
设计模式中书 《设计模式:可复用面向对象软件的基础》
(Design Patterns: Elements of Reusable Object-Oriented Software)把设计模式分为创建型模式、结构型模式、行为型模式,共有23种,可能后面大家又添加了一些,这里就不补充了,因为还是经典的23条已经很足啦!具体的模式意义大家自行搜索吧。
软件分层
- 应用层
- 中间层
- 底层
一个项目
、系统
、模型
,基础上都是至少3层,如果不够就多加一层呗!具体大家可以看看 GitHub 上的库和项目等,说到分层都是这样,这是为什么呢?举例来说,HTTP
与 HTTPS
,HTTPS 是再 HTTP 基础上加了一层 SSL/TLS
,这样对原有的兼容性是最好的,也是最容易实现的,所以这就是分层的意义!我们的项目为什么分层,怎么分层,大家可以思考一下,多问一个为什么?
软件架构
- MVC(Model-View-Controller)
- MVP(Model-View-Presenter)
- MVVM(Model-View-ViewModel)
从 MVC、MVP 到 MVVM,实际上是模型和视图的分离过程。MVC 中模型和视图没有完全分离,造成 Activity 代码臃肿,MVP 中通过 Presenter 来进行中转,模型和视图彻底分离,但由于 V 和 P 互相引用,代码不够优雅。ViewModel 通过 Data Binding 实现了视图和数据的绑定,解决了这种MVP的缺陷。
本节内容来源:MVC、MVP、MVVM架构分析与比较 - 简书
调度
URL/Protocol 注册调度
Runtime 调度
本文唯一与原文相关的可能就是这一节啦,原文中提到 CTMediator 库来架构 iOS 项目,具体的分析和细节这里就不讨论了,本文后面在做统一的回应吧。所以本节注意说 iOS调度
的问题,原文中提到 CTMediator 的2个缺点:
- 直接硬编码的调用方式,参数是以string的方法保存在内存里,虽然和将参数保存在Text字段里占用的内存差不多,同时还可以避免.h文件的耦合,但是其对代码编写效率的降低也比较明显。
- 由于是在运行时才确定的调用方法,调用方式由
[obj method]
变成[obj performSelector:@""]
。这样的话,在调用时就缺少类型检查,是个很大的缺憾。因为,如果方法和参数比较多的时候,代码编写效率就会比较低。
避免.h文件的耦合
这个大家理解吗?在这个项目后,阿里开源了 BeeHive,基于 Protocol
注册调度,那么它的缺点是什么?就是这个 .h文件的声明编译时经常报错找不到,需要很多全局的变量。当然,任何架构都无法百分百完美!
,更多问题欢迎评论区交流。
代码质量
可读性
可维护性
可拓展性
必要注释?
commit规范
CodeReview
代码质量不是由开发人员里技术最强的人决定的
,前面提到,如果代码很烂,那么很难维护,所以对于项目架构来说,代码质量也是必要关注的!以上是我认为必须要关注的事项,具体这样就不展开了,大家可以根据自己的项目或团队来规划。
其它概念
DRY
(Don’t Repeat Yourself! 不要重复你自己)KISS
(Keep It Simple, Stupid! 让事情简单化,傻瓜化) :翻译成中⽂就是“保持简单、愚蠢”。Make it run, then make it right, then make it fast.
(先求运行,再求正确,最后求快。)- 敏捷开发(Agile Development)
- 奥卡姆剃刀(Occam’s Razo)
例如“奥卡姆剃刀”,爱因斯坦的“一切尽可能简单”、达芬奇的“简单是最终的复杂性” 、安德鲁·圣艾修伯里的“完美不是当它不能再添加时,它似乎是在它不能被进一步刮除时实现的”。“如无必要,勿增实体”,即“简单有效原理”。大量的例子,都是希望在软件开发中,乔布斯的“简洁之道”
,希望大家都可以平时多注意~
3、项目架构
大家是不是觉得说了那么多,感觉还是没有说明白项目架构
?是的,基本架构就在里面,只是大家没有把它们串联起来,没有从整体上来理解。
上面说到的原则和模式,他们到底是在干嘛呢?不就是在架构
嘛!对,这些原则和模型都是希望给项目提供更好的架构,最终目的还是提高开发效率!
,敏捷开发就在其中!所以,当我们谈论架构时,就是在说项目的瓶颈
在那里?怎么避免进度被拖拉,保持软件开发的顺利上线!
更高视角思考架构师
所以,明白了架构的目的,那么架构是不是必要的呢?如果是一个人的项目,架构是不是必要的呢?如果是5个人的团队项目,架构是不是必要的呢?如果是20个人的团队项目,架构是不是必要的呢?
如果是100个人的团队项目呢?
如果是500个人的团队项目呢?
如果是5000个人的团队项目呢?
如果是50000个人的团队项目呢?
在我看来,不管是多少人的项目,架构都是必要考虑的。当然,针对不同人数的项目,需要的架构必然也不一样!所以,当我们谈论架构时,请先确认项目的大小!
,当然,项目的人员数量不可以固定不变,比如创业项目,不同阶段人员变化可能很大,这个时候,你问是不是一开始就需要做一个牛逼的基础架构?其实并不是!因为人员就是减少或增加,减少多少或增加多少,永远是无法评估的,所以最后的答案:万事开头难,只需要评估2-5倍人数,比如开始项目是5个人,那你项目架构就考虑最多10-25个人员的水平就差不多啦!最后,在需要的时候,需要一个牛逼的架构师!
,没有解决不了的问题,所以也没有解决不了的架构。
最后,我们平时怎么思考架构?可以从下面3点开始关注:
- 现在架构是怎样的
- 哪些地方可以改进的
- 业界有哪些好的架构思想可以运用
4、总结
- 模块粒度应该如何划分?
- 为什么要分层?
- 如何分层?
- 多团队如何协作?
最后,回到本文一开始说的4个问题?现在你能自己想一下答案了吗?明白了吗?
彩蛋
随着时间的流逝,人们开始意识到,严格的面向对象方法会带来很多问题。这些问题往往会使代码更复杂、更难以理解且更难以测试。事实证明,OOP 更适合某些特定的问题领域。例如,OOP 仍然是构建用户界面(窗口和按钮)最自然的方式 。但是,试图将面向对象技术应用于关系数据库一直是一场灾难。
虽然面向对象并不是解决软件危机的银弹,但和面向过程相比,面向对象的思想更加贴近人类思维的特点,更加脱离机器思维,是一次软件设计思想上的飞跃。
引用自:面向对象编程的兴衰-InfoQ
很多人都喜欢跟团队中的其他成员争论某些代码到底属于哪种模式。
,架构和模式是不是必要的呢?我认为我们开发过程中不要认为一定要用xx原则/xx模式一用到底!设计模式不是不用,是不能一味地用!
。想一想,在1994年就能提出23种设计模式的概念!真的是大神!我想现在大多数人都不没有领悟其中或达到这样的思想深度,不由得心中自发地佩服!而现在很多流行的库都利用模式来架构,比如Spring
,用的就是抽象工厂和工厂模式,回调函数用的是观察者模式,servlet
中的filter使用的是chain of responsibility模式。最后,我想引用 GoF 书中最后一章的一句话:一般而言,了解 “做什么” 要比 “为什么” 来的容易;而一个模式的 “为什么” 就是它要解决的问题。
。
作为中国区,我们的软件工程行业确实与美国有一定的差距,从这些书籍和伟人就看出来,30年前美国作为计算机首发站,有先天的优势条件。而现在,我认为我们与美国的技术的底蕴
还有较大差距,但是技术的高度
,技术创新和新技术,我们是可以弯道超车。同时,作为一名普通的程序员,我认为大家积累足够的软件开发经验,也可以总结出更多的新的理论或模式,这也是我希望中国区未来能做的到,而不是 996 的业务到底,开发的效率不是通过加班提高,而应该通过技术的创新解决!
所以,我们要架构好自己的编程~
注:更多关于 iOS 开发和程序开发相关的内容,可以查看系列,目前还在连载中 【学习总结】iOS开发高手课 – (连载中) | iHTCboy’s blog,以上,希望对你有用!
参考
面向对象设计原则:不要STUPID,坚持GRASP和SOLID_KNIGHTRCOM(rcom10002的专栏)-CSDN博客
Reclaiming Design Patterns (20 Years Later) · Ted Neward’s Blog
- 如有侵权,联系必删!
- 如有不正确的地方,欢迎指导!
- 如有疑问,欢迎在评论区一起讨论!
注:本文首发于 iHTCboy’s blog,如若转载,请注来源