缘起
最近,因为多个因素综合作用的情况下,我有幸得以负责一个项目的重构事项,并且时间/空间上都是相当宽松。而且由于系统较为复杂,需要对接多个业务开发部门,导致各种大需求小需求特别多,因此如果我代码设计得烂,那么我就要面临加班擦屁股的尴尬局面。这也导致了我不敢随意写烂代码,尽量避免各种『破窗效应』。因此想记录一些比较杂碎的感想,基本上是想到哪写到哪,不会注重文章的结构布局。
面向对象仍然是主流的设计风格
这里要理解什么是面向对象,而不是去背教材中的『封装,继承,多态』。软件开发本来就是讲究实践的东西,背教材是最没用的。『封装,继承,多态』可能恰恰是最不重要的,重要的是这些:
- 什么是『控制反转』,什么是『依赖注入』,除了在Spring/Angular这样的框架中见到之外,对我们实际设计代码有什么实际的启示。
- 什么是『SOLID』原则,有什么实际启示,哪些很容易做到,哪些看似容易实际上很难做到。
世界是有状态的,导致我们的代码也是充满了各种各样的状态
这其实是第一点的原因,大概也是面向对象风格流行的原因?各种各样的,肮脏的状态,可以让其隐藏在一个又一个的class后面,从而限制其影响范围。
什么是『组合』,什么是『组合优于继承』
『组合优于继承』,至今不知道是什么意思,也没有见到比较有说服力的答案。我感觉这句话很像『高内聚低耦合』这样很正确但是没有什么实际作用的废话。比如『装饰器模式』是组合一个很经典的例子,OK,讲完『装饰器模式』之后,我大概懂了这个模式,但是我还是没懂『组合优于继承』这句话的具体意思。大概只能靠意会了吧?
『继承』没有那么不堪,『多继承』可能要避免
承接上一段。貌似总有人将『组合』与『继承』对立起来,然后有选择地举几个例子,说『继承』哪哪不好,『组合』哪哪好,然后得出上面那句话的结论。这种文章一般犯了『幸存者偏差』的错误,一般也夹带了很多私货,没有啥营养。
其实我倒觉得,没有孰优孰劣,因为两者只不过是两种不同的手段而已,比如吃饭可以用刀叉,也可以用筷子,解决问题还是要看场景。继承没有大V们吹的那么恶心,毕竟也是根据实际问题而发明的手段,总不能一点用处也没有吧?简单用用其实挺好的,也能重用很多代码。
但是Java有种特别不好的风气,就是搞巨多class,然后设计很复杂的继承(接口)关系,层层封装,真实意图往往隐藏在层层代码之后。更有甚者,几乎每一个class都搞一个interface,美名其曰为拓展设计,其实是『过度工程』。这种风气下来,让人写Java缺少快乐的感觉,我猜大V批判Java主要是指的这个吧。
反正我写Java是挺快乐的,想到哪写到哪,也不刻意搞很多interface,大不了到后期再提取interface就行了,反正现在的IDE工具都是这样强大。
『设计模式』很有用
这个东西真是强求不得,如果是强行搞『设计模式』,基本死得很惨,还不如不搞。在项目重构的过程中,我主要使用了『工厂方法、模板方法』这几个模式,搞出来的代码确实让人感到赏心悦目。特别是『模板方法』模式,我们的业务过程中有太多场景适合这个模式了,我几乎全部都使用了它,改起Bug来嗖嗖的。
OOP 与 FP
OOP懂一点,FP基本不懂,不懂得领域,就不随意评论了。对于FP,我发现一点,就是总有人拿它和OOP进行类比,列举出个OOP的几个缺点和FP的几个优点,然后将OOP批判一番,然后得出『FP更优』的结论。讲真,计算机世界的很多概念和事物,是不适合用类比来理解的,就像人的食指和中指,在实际生活中,各自完成不同的功能,各司其职,从而使我们能完成各种各样的动作。如果你硬是将其对立起来,有其一就不能有其二,这不扯淡吗?OOP和FP同理,本来就是两种不同场景下的手段,如果硬是将它们对立起来,得出个孰优孰劣的结论,反而没有什么意义。各司其职,融合着使用,才是解决之道。
分层思路
任何软件都是分层的,分层可以显著降低人脑思考的难度,从而设计更加大型的软件。在这种语境下面,『模块化』『分层』等概念,基本上是某种概念的不同侧重点,基本上是同一个意思。
但是分层也不能太细太碎太多,这样基本走向了反面,带来了累赘。『中庸之道』才是硬道理,得靠大量积累的实际经验。
《重构》、《Clean Code》
两本好书,很影响人。看了好几遍了,每次看都有新的收获,看得次数越多,逐渐地会吸收作者『只可意会不可言传』的某些内容。