具有所有静态方法的类是否有任何问题?

2022-09-01 00:04:29

我正在做代码审查,遇到了一个使用所有静态方法的类。入口方法采用多个参数,然后开始调用其他静态方法,传递入口方法收到的所有或部分参数。

它不像一个数学课,基本上不相关的效用函数。在我自己的正常编程中,我很少编写Resharper弹出并说“这可能是一个静态方法”的方法,当我这样做时,它们往往是无意识的实用程序方法。

这种模式有什么问题吗?如果类的状态保存在字段和属性中,或者使用参数在静态方法中传递,这是否只是个人选择的问题?

更新:正在传递的特定状态是来自数据库的结果集。该类的职责是从数据库的结果集填充 Excel 电子表格模板。我不知道这是否有任何区别。


答案 1

这种模式有什么问题吗?如果类的状态保存在字段和属性中,或者使用参数在静态方法中传递,这是否只是个人选择的问题?

从我自己的个人经验来看,我已经研究了100个KLOC应用程序,这些应用程序具有非常非常深的对象层次结构,所有内容都继承并覆盖了其他所有内容,所有内容都实现了六个接口,甚至接口继承了六个接口,系统实现了书中的每个设计模式,等等。

最终结果:一个真正的 OOP 架构,具有如此多的间接层,调试任何内容都需要花费数小时。我最近开始了这样一份工作,在这个系统中,学习曲线对我来说被描述为“一堵砖墙,然后是一座山”。

有时,过分热心的OOP会导致类变得如此细粒度,以至于它实际上是一种净伤害。

相比之下,许多函数式编程语言,甚至是像F#和OCaml(以及C#!)这样的OO编程语言,都鼓励扁平和浅层的层次结构。这些语言的库往往具有以下属性:

  • 大多数对象都是POCO,或者最多有一个或两个继承级别,其中对象只不过是逻辑相关数据的容器。
  • 不是类相互调用,而是使用模块(等效于静态类)来控制对象之间的交互。
  • 模块往往作用于非常有限的数据类型,因此范围很窄。例如,OCaml 列表模块表示对列表的操作,客户模块表示对客户的操作。虽然模块或多或少具有与类上的实例方法相同的功能,但与基于模块的库的主要区别在于,模块更加独立,粒度要小得多,并且往往对其他模块几乎没有任何依赖关系。
  • 通常不需要子类对象重写方法,因为您可以将函数作为第一类对象进行专用化。
  • 尽管 C# 不支持此功能,但函子提供了一种对专用模块进行子类化的方法。

大多数大型库往往比深度更宽,例如Win32 API,PHP库,Erlang BIF,OCaml和Haskell库,数据库中的存储过程等。因此,这种编程风格是战斗测试,似乎在现实世界中运行良好。

在我看来,设计最好的基于模块的API往往比设计最好的OOP API更容易使用。但是,编码风格在API设计中同样重要,因此,如果团队中的其他人都在使用OOP,并且有人以完全不同的风格实现某些内容,那么您应该要求重写以更紧密地匹配您的团队编码标准。


答案 2

你所描述的只是简单的结构化编程,就像在C,Pascal或Algol中可以完成的那样。这没有什么本质上的错误。在某些情况下,OOP更合适,但OOP不是最终的答案,如果手头的问题最好通过结构化编程来解决,那么一个充满静态方法的类就是要走的路。