在做系统架构时,一个重要的思考方向就是如何让系统拥有高扩展性,高扩展性本身目的就是能够快速响应变化带来的新问题,并解决这些问题。
拥抱变化指的是什么?
我们经常听到这样一句话:拥抱变化。
作为开发人员如何拥抱变化?被动的接受需求,然后埋头苦干?还是高高兴兴的接受需求,然后埋头苦干?这两种都不是我们期望的拥抱变化的方式,因为这两种方式只是心理、心态上的不同,在拥抱变化的技能上依旧没有什么明显的变化。
在 《为什么要关注代码的可读性?》这篇文章结尾中给出了一些线索,这些线索不单单能够提升代码的可读性,同时能够带给我们在技术上拥抱变化的能力--让代码易读、易变动。
这些提升技术拥抱变化的能力主要分为两类:
技术部分:
1. 熟悉工具:[《短时间让你扔掉鼠标的Intellij IDEA的插件》](https://www.jianshu.com/p/14e9fed878fd)
2. 开发语言特性和工具类库
3. 代码结构;
4. Simple Design
5. 设计原则;
6. 设计模式;
非技术部分:
1. 接受反馈;
2. 走出舒适区;
3. 刻意练习
技术上拥抱变化并不是仅在某个特定的时间点才去关注,不是做架构时才考虑高扩展性,不是出现问题了才去使用技巧来应对问题。今年是2019年,翻翻20多年前的书不难发现,早在20多年前人们就应该开始整理拥抱变化上的方法,并在20多年的时间内不断喜欢、演进。
本文先来聚焦技术部分,如何让我们提升拥抱变化的能力。
技术上如何拥抱变化
为了让本文内容不至于离大家太远,就从手边能做的和技术相关的内容来说明,如何在技术上提升拥抱变化的能力。
1. 熟悉工具
你每天用的工具都有哪些?Git、Intellij Idea、Docker、Terminal等等。
熟练使用这些工具在基本功能至上,学习和探索如何能够让这些工具更为高效的为你工作。
可以按照下面的清单来审查需要在哪个环节提升效率:
1. 基本功能和特性。例如:git stash、Idea中Refactoring中的功能等等
2. 这些功能的快捷键或者alias是什么
3. 工具间的切换如何快速完成。
按照上面的清单,不断提升工具的熟悉程度,能够为我们节省下很多碎片时间,将节省下的时间用在其他地方时争取时间的好办法。
2. 开发语言特性和工具类库
和工具一样,我们使用工具就是为了能够更加高效的处理日常重复性工作。熟悉了解开发语言特性能够让我们事半功倍。将时间留给那些真正需要重复造的轮子上。
下面是几个简单的例子:
1. 如何减少代码中的非空判断?
2. 如何将两个数组合并?
3. 如何将Domain转为DTO?
熟悉这些工具类,能够让我们有能力快速应对一些修改、变化。
3. 代码结构
没有一劳永逸的代码结构。
我们的架构在演进,我们的代码在变的复杂,并不是简单定一些条条框框的开发规范就能够将问题解决的。
代码结构并不是规范,而是应该留意团队中实际遇到的问题,通过调整目录结构来让代码相对于之前更清晰、更易维护。
下面是一些思路:
1. 根目录下的内容存在重复、多而分散,适当的进行内聚;
2. 已经无法通过一个类型的前缀快速定位到一个类,即使通过IDE也需要更对的信息才能够准确定位到一个类。
3. 让整体结构变得混乱的某些包 或者 代码
4. 职责越来越大的类和包,已经无法清晰表达业务,拆分其职责。
4. Simple Design(简单设计原则)
Simple Design正式众多原则中的一个,不过对很多问题都适用。
- 实现功能
- 揭示意图
- 消除重复
- 最少元素
为什么要用Simple Design?
通过代码来实现业务需求,这是我们的目的。如果想要让实现需求的代码容易维护,就是我们在实现的时候就保持其易读,易修改,而简单的事物是容易修改和处理的。所以让代码保持简单是面对变化,能够拥抱变化一个很好的选择。
不管是使用简单设计原则、还是熟悉工具,其目都应该是聚焦价值的,即我们所做的都为为了实现某个价值。所以Simple Design中四个对代码设计活动也就有了一个先后的顺序。首先实现业务功能,但并不能仅止于实现业务。为了后续能够快速修改,我们每次实现了部分业务代码后,就应该考虑,实现业务的代码中的包、类、方法、参数、变量是否揭示了业务意图。如果没有我们就需要修改这些内容的位置和名称,从而能够得到一段意图明显的代码。
意图明显但是充满重复的代码,同样是不易修改和维护的。现实中发现很多开发人员会期望提前将公用代码做好封装,例如我们代码中的工具类,但是在业务代码时却又将重复忽略不见。所以消除重复不是开发者不做,而是并没有形成意识,哪些环节都需要去消除重复。
最少元素,使的代码更加简洁。例如一个方法的如入参应该尽可能少,超过3个入参就应该将参数封装在一个类中。话是这样说,但是最少元素也是最不好做到的。因为不单单需要我们对开发语言熟悉,对业务熟悉,还要求对设计原则,设计模式有一定的掌握,才能真正做的最少元素。
最后,在反问一句,做这些有价值吗?有价值,毕竟修改代码时,读代码和写代码的时间比例时10:1。保持多简单代码,能够让我们事半功倍。不过其价值的大小,我认为可以按照上面的1,2,3,4来进行排序的,实现功能的价值最大,揭示意图的价值其次,消除重复再次,最后是最少元素。
那么什么时候使用Simple Desin呢?
添加新的代码、修改旧的代码时都应该遵循。先实现功能、在用1分钟审视一遍是否刚才加入的代码揭示了意图,是否存在重复,是否应该用最少元素。
《从Simple Design入手让代码易维护》一文中讲解了对Simple Design不同熟悉度的开发人员如何进一步提升系统的易维护性。
5. 设计原则
为什么我们在谈让开发拥有拥抱变化的能力的时候要谈到设计原则?
因为通过设计原则,我们能够发现我们代码中的问题。我们实现的业务的代码之所以不易修改,很大原因是我们并没有遵循这些原则,久而久之代码就越来越不易修改。如果我们维护的一份结构、意图清晰的代码,设计原则,有助于帮助开发人员维持好这份清晰。
设计原则指的是哪个设计原则?
- 单一职责原则
- 开放封闭原则
- 里氏替换原则
- 依赖倒置原则
- 接口隔离原则
但让止于上面5种原则,还有很多,比如:好莱坞原则(HP)无循环依赖原则(ADP)等等,从以上5个原则开始或许是维护好代码,让代码易修改的入手点。
上面 5个设计原则都分别指什么?
【单一职责原则】
对一个类或者一个方法而言,应该只有一个引起它变化的原因。
【开放封闭原则】
软件实体等(模块、类、方法等)应该是可以活站的,但是不可以修改。当软件实体发生变化时,尽量通过扩展软件实体的行为,而不是通过修改已有代码实现变化。
【里氏替换原则】
在继承时,应该遵循里氏替换原则。任何基类出现的地方,子类一定能够出现。子类可以活站基类的功能,但是不能改变基类的功能。(子类可以实现基类的抽象方法,但是不能覆盖基类的抽象方法;子类可以增加自己特有的方法;当子类的方法重载基类的方法时,方法的形参要比基类的输入更加宽松;当子类的方法实现基类的抽象方法时,方法的返回值要比基类的更加严格。)
【依赖倒置原则】
高层模块不应该依赖底层模块,二者应该依赖与抽象。抽象不应该依赖于细节,细节应该依赖于抽象。
【接口隔离原则】
不再在一个接口中放置很多的方法,这样会让接口变的臃肿;接口应该尽量细化,一个接口对应一个功能的模块,同时接口中的方法应该尽量少,使得接口更加灵活。
6,设计模式
开发者可以通过设计原则来发现问题或者确定修改思路,通过设计模式来解决问题。
设计模式并不是唯一解决问题的途径。我们必须先来聚焦我们为什么要用设计模式。还是为了让代码拥有拥抱变化、易修改的能能力。遵循设计模式是让程序拥有这种能力的一种实现方法。
对于那23种设计模式,会在后续整理出来。
结尾
读到这里估计很多人开始想,我要擅用工具,又要使用Simple Design、设计原则,最后还要用上设计模式,感觉绕了很大一个圈子?是的,不过是围绕价值来的。如果不熟,那么循序渐进或许是一个好的选择。如果对上面的很熟,当遇到一个问题时,上面的过程只是瞬间完成的。
不管对上面的内容熟悉与不熟悉,关键点不要忘记,都是为了让开发者真正具有拥抱变化的技术能力。
最可怕的人是那些注重细节的人并行动的人。
技术人员如何拥抱变化?
网友评论