一、从软件工程说起
现在的软件行业已经是非常繁荣了,但是软件行业的发展不是一蹴而就的,也是随着硬件以及外部环境的变化不断来的,在计算机发展的初期,大部分都是具备一定规模的行业(银行、航空等)、为民众服务的政府部门通过引入计算机以及相关软件来提升效率的,所以开发的软件也大多数是相对大型的软件系统,在相关软件的开发中,当时这个新兴的行业碰到的问题也越来越多,甚至由于大型软件的开发、维护难题,有人还提出了“软件危机”
为了解决“软件危机”,那么就有一群牛人开了个会,讨论解决这些问题的应对办法,然后经过归纳总结,形成了软件定义、开发、维护工程化的相关概念,称之为“软件工程”。目前大多数软件工程师日常工作中的流程:需求评估、方案设计、开发、测试、更新、开发过程(敏捷、瀑布等等)都是软件工程的范畴
经过软件工程概念的落地和应用,软件开发整体的效率和质量终于得到了改善,
现在“软件工程”也发展成了一门专门的学科
二、设计模式的由来及作用
有了“软件工程”作为指导思想,大型软件的开发质量、效率都所有改善,但是这毕竟是从大的流程层面来看的,还没有具象到Coding环节,解决了大问题之后,Coding环节的问题也就凸显出来,这些问题往往都是由于软件设计环节没有做好而带来的,1990年,就有大牛把建筑学中的设计模式的概念引入了软件开发领域,并且出了一本书《设计模式:可复用面向对象软件的基础》,书中介绍了23种设计模式,来解决不同场景下所碰到的问题
所以设计模式更像是一种指导思想或者编程模板,在对应的场景下,直接引用对应的最佳实践即可,使入行的新人少走弯路
后来,随着面向对象编程语言的发展,由大神罗伯特·C·马丁在《敏捷软件开发》中正式提出了SOLID面向对象设计,也是现在常说的面向对象设计原则,用来指导软件的设计和开发,也主要是为了配合“敏捷开发”
首字母 | 原则 | 说明 |
---|---|---|
S | 单一职责原则 | 认为对象应该仅具有一种单一功能的概念。 |
O | 开闭原则 | 认为“软件体应该是对于扩展开放的,但是对于修改封闭的”的概念。 |
L | 里氏替换原则 | 认为“程序中的对象应该是可以在不改变程序正确性的前提下被它的子类所替换的”的概念。参考契约式设计。 |
I | 接口隔离原则 | 认为“多个特定客户端接口要好于一个宽泛用途的接口”的概念。 |
D | 依赖反转原则 | 认为一个方法应该遵从“依赖于抽象而不是一个实例的概念。依赖注入是该原则的一种实现方式。 |
23设计模式以及面向对象设计软件,强调的还是代码解耦与复用,而后来,大神Eric Evans ,在《领域驱动设计》中,提出了领域驱动设计的概念,是一套完整的一套解决复杂软件设计的思想,这是完全区别于之前设计模式与原则的一套设计思想,但同时这套思想也更为复杂。
三、如何运用设计模式与原则
可能有些人尤其是刚入行的工程师,对于23中设计模式、面向对象设计原则以及领域驱动设计,看了相关知识之后,觉得云里雾里,不知道该如何使用。那么就会出现两种情况:
- 都是大牛总结的,大家都在用,先练习吧,生搬硬套也要用
- 没发现哪些地方能用上,等能用上了再说,后面就干脆不用了
这两种情况并没有谁更好一些或者更差一些,出现这种情况其实不能怪新手,因为能查到的资料都在讲这是什么,而鲜有讲如何用
对于以我个人经验来说,只要记住以下几点就好
1、思想和原则都是为了解决问题
很多人学习到新的知识以后,都容易进入拿着“锤子”找“钉子”的状态,学到新技术、知识,就想赶紧用,没有条件创造条件也要用,那么可能会适得其反,曾经我有个同事为了做个企业官网,用了不下三种设计模式,这种高射炮打蚊子的操作,真的挺要命的。
不能解决问题的投入,都是没有产出价值的
2、设计思想和原则不是铁律
设计思想和原则,并不是一旦未被就会付出代价的法则,它只是一种指引,告诉开发人员,当你这么做,你就会在某些方面提高维护成本
这里以比较具象的数据库设计范式中的第三范式为例,订单表中不应带存储用户名,应该存储uid,但是实际电商设计都不会参考,多会把uid、用户名都存储到订单表,以提高查询效率,并接受因此带来的存储成本
设计模式和原则同理,纵使你打开明星项目,也会发现有不符合主流设计思想/原则的设计。这种情况在领域驱动设计的应用中更加明显,大部分互联网公司都会引入领域驱动设计来解决一些软件设计和维护中的问题,但是没有完全照搬领域驱动设计的
3、设计往往都是在平衡
什么是好的设计模式与思想的运用?
能以最少的成本,顺利达成设计目标的设计,就是好的设计
软件系统的设计,有目标、同样也有资源要求、成本要求、时间要求等,一个软件系统细分的子系统也同样如此,一个系统分拆的模块也同样如此。设计好一个大的平台、一个系统、一个模块,都需要考虑这些因素,并在这些因素中取的一个平衡
要追求完美,也要接受不完美