静态方法和类是否有利于可伸缩性?我认为静态类/方法提高了应用程序的可扩展性,而实例方法的扩展性不大。那么在可能的情况下编写静态方法是一种好的编程习惯吗?
8 回答
静态方法和类是否有利于可伸缩性?
一个与另一个关系不大。
我认为静态类/方法提高了应用程序的可扩展性,而实例方法的扩展性不大。
错误的。你为什么这么认为?
那么在可能的情况下编写静态方法是一种好的编程习惯吗?
不。事实上,这是非常糟糕的做法,因为它放弃了面向对象编程的可维护性优势。
使用静态方法需要考虑三个问题:
- 如果您的静态方法具有较大的临界区,您可能会引入瓶颈。最大的当然是声明整个方法同步。如果它一次只能执行一个,那么这是一个潜在的问题;
- 如果您在不同的虚拟机和不同的机器上运行相同的方法,它所做的一切是否仍然一致?和
- 任何依赖静态方法的方法都存在单元测试问题。
它通常不被认为是最佳实践,但静态辅助方法很常见。太复杂了,可能应该考虑另一种方法。
这取决于为什么该方法是静态的。如果它是静态的,因为它确实不需要上下文,那么与类似复杂性的东西相比,它可能会很好地扩展,因为它需要上下文而不是静态的。
但是,如果它是静态的,仅仅是因为您无法保留所需的上下文并且仍然必须将其传入,或者因为一些人为的目标是拥有更多静态方法,那么我怀疑它实际上会比可比较的方法扩展更少,因为非静止的。
事实上,我认为 ASP Classic 证明了这一点。
没有静态方法本质上不能更好地扩展。事实上,编程风格(命令式或面向对象)并没有真正对缩放产生任何影响。扩展有两个主要方面,如何提高规模取决于我们的意思:
1 按每秒处理的请求数缩放
这种类型的扩展通常是关于向集群添加更多计算机以提高系统的整体吞吐量。增加扩展性通常是最初通过使用缓存减少使用的共享资源量,然后将数据访问拆分为分片。
2 数据缩放
这是当系统随着时间的推移获得越来越多的数据并且访问数据的操作(搜索、过滤等)变得更慢时,因为算法比 O(1) 更复杂。在这种情况下,正常的策略是增加读写点的数量,并使用 Map/Reduce 等并行算法。
但是这些方面都与您是否使用静态方法无关,只是多个请求是否适用于大型数据集或单一数据源。
不。我认为您可能假设每个实例都有自己的方法定义副本,为每个实例占用了那么多空间,但事实并非如此。
编辑添加:
如果您想知道如何在实例之间实际共享实例方法:这是因为对实例方法的每次调用都会隐式地将对实例对象的引用传递给该方法。这通常被称为“隐式 this” 换句话说——当你定义或调用一个带有 myMethod(a, b) 之类的两个参数的实例方法时,你可以认为它实际上是 myMethod(this, a, b) , 而 Java 会为您处理 this 参数,而无需您显式定义或传递它。
(顺便说一句,这在 Python 中的处理方式不同,您必须将对象引用显式放入实例方法定义的第一个参数中,尽管不在调用中。)
有关在 Java 字节码级别发生的事情的解释,这里有一个链接: http ://www.artima.com/underthehood/invocationP.html (参见周围的东西:“objectref 是传递给任何实例的隐式 this 指针方法。”)
您指的是哪种形式的可扩展性?可伸缩性,即代码在大小项目中可维护和可扩展?然后只使用静态方法会受到伤害。你是说性能吗?如果实例方法较慢(我不相信这种普遍性),那么这并不意味着它们不能扩展。如果它们需要两倍于静态方法的时间,那么如果您将它们全部调用 10000 次,它们也需要两倍的时间。选择正确的算法和数据表示更多地决定了性能的可扩展性。
最后,如果您认为静态方法是可行的方法,那么您不应该使用像 Java 这样的面向对象语言。试试 C 或 Pascal 或经典的基本方言。
我认为你在吠叫错误的树:
在现实世界中,可伸缩性(或缺乏可伸缩性)通常源于算法的适当性和对数据存储进行的操作的效率(想想:好的 SQL 查询)。
诸如方法是否为静态(或静态方法的百分比)之类的事情通常与系统的可伸缩性无关。您当然可以拥有一个不使用静态方法的超级可扩展系统,或者专门使用它们的超级可扩展系统。
投了反对票。OP显然不太了解OO。创建实例对象时,实例方法不会占用任何额外空间。除非您还避免创建任何实例,否则静态方法不会为您节省任何东西,在这种情况下,您与构建 OO 语言的目的相去甚远,以至于这是毫无意义的讨论。