这种模式有什么问题吗?如果类的状态保存在字段和属性中,或者使用参数在静态方法中传递,这是否只是个人选择的问题?
从我自己的个人经验来看,我已经研究了100个KLOC应用程序,这些应用程序具有非常非常深的对象层次结构,所有内容都继承并覆盖了其他所有内容,所有内容都实现了六个接口,甚至接口继承了六个接口,系统实现了书中的每个设计模式,等等。
最终结果:一个真正的 OOP 架构,具有如此多的间接层,调试任何内容都需要花费数小时。我最近开始了这样一份工作,在这个系统中,学习曲线对我来说被描述为“一堵砖墙,然后是一座山”。
有时,过分热心的OOP会导致类变得如此细粒度,以至于它实际上是一种净伤害。
相比之下,许多函数式编程语言,甚至是像F#和OCaml(以及C#!)这样的OO编程语言,都鼓励扁平和浅层的层次结构。这些语言的库往往具有以下属性:
- 大多数对象都是POCO,或者最多有一个或两个继承级别,其中对象只不过是逻辑相关数据的容器。
- 不是类相互调用,而是使用模块(等效于静态类)来控制对象之间的交互。
- 模块往往作用于非常有限的数据类型,因此范围很窄。例如,OCaml 列表模块表示对列表的操作,客户模块表示对客户的操作。虽然模块或多或少具有与类上的实例方法相同的功能,但与基于模块的库的主要区别在于,模块更加独立,粒度要小得多,并且往往对其他模块几乎没有任何依赖关系。
- 通常不需要子类对象重写方法,因为您可以将函数作为第一类对象进行专用化。
- 尽管 C# 不支持此功能,但函子提供了一种对专用模块进行子类化的方法。
大多数大型库往往比深度更宽,例如Win32 API,PHP库,Erlang BIF,OCaml和Haskell库,数据库中的存储过程等。因此,这种编程风格是战斗测试,似乎在现实世界中运行良好。
在我看来,设计最好的基于模块的API往往比设计最好的OOP API更容易使用。但是,编码风格在API设计中同样重要,因此,如果团队中的其他人都在使用OOP,并且有人以完全不同的风格实现某些内容,那么您应该要求重写以更紧密地匹配您的团队编码标准。