Initialize方法是代码味道吗?

use*_*677 15 c# coding-style

我现在正在编写一堆系统.它们不是来自通用接口.

一些实例系统:MusicSystem,PhysicsSystem,InputSystem,等等.

目前,MusicSystem在其构造函数中加载了大量音频文件,因此,首次创建对象时可能会有一些短暂的延迟.

因此,这个加载所有音频文件的代码应该放在一个Initialize()方法中吗?这允许程序员确定何时加载音频文件,但如果他忘记调用Initialize()程序将崩溃.

因为并非所有系统都需要一个Initialize()方法,所以程序员必须查看每个系统以查看该类是否有Initialize()方法,如果有,则调用它.这有点麻烦.

在一般设计原则方面哪种方法更可取?

Mat*_*all 21

考虑一下您编写代码的其他API.什么时候API需要程序员知道调用init方法,否则在运行时崩溃?

作为API的消费者,如果我必须知道在构造对象之后调用方法,那将会让我感到疯狂init.我会推荐一个我亲眼看到并使用的替代方法:记录昂贵的对象实例化.如果程序不需要崩溃,那么推迟昂贵的初始化有什么意义呢?


Mat*_*ick 12

基本上,你要权衡程序-程序的效率Mer的效率.因此,在这种情况下,它不一定是代码气味,具体取决于哪个更重要.您是否希望使代码更容易使用,更难破解,或者让程序加载更快?

但是,您可以尝试的另一种方法是延迟加载.

然后,你也可以吃蛋糕并吃掉它:

  • 客户端代码不必调用 Initialize
  • 除非需要,否则不会加载数据

  • 延迟加载的问题在于这是一个游戏(应该提到这个),并且在游戏过程中加载延迟不会很好. (3认同)

Bev*_*van 11

将重度初始化移出构造函数不是代码味道.

但是,依靠外部调用者来调用初始化是一种气味 - 它被称为时间耦合.

Initialize()在你的类上创建方法,但是要创建它private(或者protected如果必须的话).

还要编写一个EnsureInitialized()方法,在需要时触发初始化,但每个实例只触发一次.

然后,您的类的每个公共入口点应该EnsureInitialized()在开始时调用- 您的初始化将被推迟到首次使用的点.

有了这个,并且如果你对锁感到满意,你可以将调用转移EnsureInitalized()到后台线程中以在后台完成工作,对前景的影响最小.


Fer*_*cio 5

我不认为有一个初始化方法是代码气味,但如果用户未能调用您的初始化方法肯定听起来像一个崩溃(而不是优雅地失败).

如果您确保所有系统都有Initialize()方法(即使它什么都不做),那么您的用户无需担心是否要调用它.

  • 我不同意最后一句话。如果所有系统都有一个“Initialize()”方法,那么用户会更加困惑是否需要调用。**删除**正确使用 API 所需的步骤数。 (2认同)
  • 如果总是需要,那就在内部进行. (2认同)