Should you avoid static classes?
静态类被认为是不好的实践吗?几天前我读了一篇关于这个的文章(很抱歉找不到),它基本上说拥有静态类(尤其是那些"助手"类)通常是坏代码的标志。这是正确的吗?如果是,原因是什么?
滥用静态类被认为是不好的做法。但滥用任何语言的特征也是如此。
我不区分只有静态方法的非静态类和静态类。它们实际上是相同的,除了静态类允许编译器强制执行开发人员的意图(没有实例化这个类,访问其功能的方便语法等)。
正如您所说,大量的"助手"类会给您带来麻烦(设计、可维护性、可读性、可发现性、其他能力…)。这里没有争论。但是你能说"助手"类永远不合适吗?我对此表示怀疑。
实际上,负责任地使用静态类对您的代码有很大的好处:
Enumerable 静态类提供了一组我们大多数人都喜欢的扩展方法。它们是功能/业务逻辑的逻辑集,与任何特定类型的实例都不相关。- 环境/上下文提供的服务:例如日志记录、配置(有时)
- 其他(我现在想不起来)
所以,不,总的来说,这是一个不错的做法。明智地使用它们…
它是指"静态类的使用是错误的"(在这种情况下,文章是错误的)还是"静态类通常在写得不好的代码中被发现"(在这种情况下,它不是说静态类本身是错误的,而是说它们有时被错误地使用)
静态函数比非静态函数更有效,因为您不需要创建对象的实例来使用它们,也不需要将"this"指针传递给方法调用。
使用静态类来保存全局变量是另一回事——在这种情况下,底层规则不是"静态是坏的",而是"全局是坏的"。
我认为一般的论点是反对在静态类中保持可变状态,并基本上将它们用作全局变量。静态类中的静态助手方法没有任何问题。
至于为什么全局变量是坏的,我敢肯定,在这里和谷歌之间,你会找到50万页的网页和博客文章。
不,这不太正确。
有许多函数不是特定于对象实例的,不需要状态。例如,考虑"数学"函数。
几乎所有语言都有这样的特点:
1 | y = Math.round(x); |
所以"round"函数是静态的。如果你疯了,你可以为(c)这样的事情辩护:
1 2 3 4 5 6 | class RoundFunction<T> : GeneralMathFunction<T> { public override T Operate (params object[] variables) { .. } } |
但是,天哪,你这样做有点奇怪。
当然,有一段时间,过多的静态函数是出了问题的征兆,但在合理的范围内,这并不是"坏的"。
下面是一些链接,指向一些谷歌测试博客文章,说明为什么静态方法会损害代码的可测试性,以及为什么静态方法(静态类中不好的部分)会引入各种可能令人惊讶的组件之间的耦合和交互。
如何思考OO
独生子女
静态方法是可测试性的死
在我的代码中,我一直在使用静态实用程序类来处理那些经常调用的方法,但是要声明这些方法会很困难。一个例子是一个简单的日志类,比如:
1 2 3 4 5 6 7 8 | public static class Logging { public static UpdateAction(int id, object data) { SqlConnection connection = new SqlConnection("conn string from config file"); // more logic here... } } |
现在,我绝不会让这些类和方法存储任何类型的全局状态,因为这会导致巨大的一致性问题,一般来说,这只是一个糟糕的设计。
所以不要避免静态类,只要避免让这些静态类保持某种全局状态。
在实用程序类中,所有方法都是静态的,这是有必要的。在这种情况下,如果您使类静态化,它将清楚地指示您的意图。至少在C中,静态类中不能有非静态方法。