Tantan Fu

Mar 05, 2016

程序员的懒惰与面向协议编程(POP)

Laziness, impatience and hubris. 程序员的三大美德。今天我们来谈一谈三大美德之首,懒惰。(或许这能解释一下为什么我这么久没有更新博客…)
我仍然记得本科老师的谆谆教诲,『懒惰即美德,重复就是罪恶』。一个对代码有着严重洁癖的程序员,是不允许代码中出现大量重复的,从机器码到高级语言,可以类比于农耕时代到工业社会,优秀的代码总是职责单一而且简单明了的。函数作为代码复用的基本单元,已经被被大家广泛使用,当然可能还是会有人争论,代码量这么小的几行代码,只有两处调用,又抽成函数,会造成压栈出栈的性能消耗,当然我承认你说的都对,但是我就是不能忍受重复的代码,而且现代的编译器已经非常聪明,会将一些小的函数调用自动内联(inline)。所以,性能才是万恶之源啊。
函数作为代码复用的单位,已经不能解决广大程序员日益增长的懒惰曲线和现有的复用技术的矛盾了。Here comes OOP。面向对象编程在 Java 大行其道的今天,可能已经早已被大家接受了。编程的过程不再是简单的函数调用,而是不同对象之间的消息发送(sending messages between objects)。通过继承,子类对象可以获得父类的属性和方法,然而,这种复用的方式还是耦合性太强了,举个粗俗的例子,一个人想要获得另一个人的资源,就要认他做父,在 Java 和很多其他编程语言中,都是只支持单继承的,可以认很多的父亲(比如 C++),管理起来就很混乱。然而,人总是懒惰和贪婪的,我又想要其他人的资源,这时候该怎么办呢?找个满足你所有需求的爹…
以 iOS 为例,我想要继承自一个 ViewController1,然而,还想要有另外的一个 ViewController2,该怎么办呢,创建一个新的 ViewController3,复制粘贴 ViewController1 和 ViewController2 的代码,然后在继承自 ViewController3,然而代码又有重复了。
可以看出,继承,作为代码复用的一种方式,耦合性还是太强。那么有没有一种方法,能够在不改变现有代码的基础上,实现代码的复用呢。
其实像 Ruby 中的 Mix-in 或 Trait 可以实现类似的功能,这里不展开讨论了。
当然会有人说,面向协议编程,这里的 protocol 不就是 Java 中的 interface 吗,对,也不对。Java 中的 interface,更多的功能是处理类型信息,更像是多态的效果,然而并没有提供代码的复用机制,因为拥有相同接口的不同的类,即使他们的接口实现都相同,也必须同时实现这个接口,于是,重复代码又出现了!
在 Swift 2.0 之后,我们可以使用 extension 为 protocol 添加默认的实现,也就是说,在大多数情况下,我们使用这种低耦合的方式,让你的类站出来说,我要遵循 XXX 协议,然后,就完成了! https://www.futantan.com/blog/%E7%A8%8B%E5%BA%8F%E5%91%98%E7%9A%84%E6%87%92%E6%83%B0%E4%B8%8E%E9%9D%A2%E5%90%91%E5%8D%8F%E8%AE%AE%E7%BC%96%E7%A8%8B(POP)

Copyright © 2023 Tantan Fu