最优雅的延迟或可重复初始化方式

时间:2016-05-30 12:41:17

标签: c# .net delegates

我正在尝试在一个应用程序中重写非常难看的类。在我们的一个类中,有数百行代码可确保某些类的初始化和重新初始化。目前,这是以可怕的暴力方式完成的,您可以在其中编写初始化代码并手动将其复制到重新初始化部分(因为它们非常相似)。

因此,我开始将其重写为一个委托列表的形式,然后在两个地方都使用参数调用(bool isReinit)。然后我注意到大多数委托也是相同的,因为90%的类的初始化过程是相同的。这意味着我应该能够创建一些默认初始化函数来大大简化代码。目前我创建了这样的东西:

https://dotnetfiddle.net/RVS5UT

我还创建了类CustomInitializer,它实现了IInitializer,只接受一个Func作为参数并在Initialize中运行它,适用于初始化有很大不同的情况。

现在,这个简化的匿名工作代码,但它的工作原理。问题是整个方法非常尴尬,构造函数签名很丑陋。有没有办法简化这个?我找不到任何可以帮助我的模式或方法?任何迈向更好代码的步骤都是受欢迎的,也许我只是缺少一些东西。

还有另一个问题。我想出的一个解决方案是将属性对(var1a + var1b,var2a + var2b,..)存储在一个对象中,并将其直接传递给Initialize方法。但这意味着移动属性,这在目前是不可能的,因为该文件有超过18k行,并且代码审查者会因为重构一个方法(即使它很长)而杀死我改变其中的第三个。我需要将目标属性(var1a,var1b,var2a,..)保留在现在的位置。这也可能意味着没有优雅的方法来解决这个问题。

我使用的是.NET 4.0,C#5.0

编辑:我无法访问初始化类型(另一个愚蠢的捕获)

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

  

该文件有超过18k行

哇,看起来很有趣。

尝试改进它是绝对好的。并且相信我,无论你的同事怎么想,除了这个代码不需要进化之外,没有什么比在这里重构更能做到的了。

但是,在我看来,你走的是复杂的道路,试图干,而不是试图表达。让StandardInitializer和CustomInitializer管理lambda的想法非常复杂。类的初始化应该在它负责初始化的类中。如果某些行为真的是共享的,那么它们可能共享基类或协作类。

我建议你在Working Effectively With Legacy Code进行讨论。正如您所看到的并且可能已经知道的那样,第一个关键点是进行测试。 如果没有测试工具,请不要尝试重构这样的课程。否则你会引入回归,你会感到沮丧,你的同事会在他们的愿景中得到安慰,在没有破坏一切的情况下,什么也做不了。

并且不要忘记,如果测试很难创建,那是因为代码不好,而不是因为测试很昂贵。糟糕的代码很贵。

经过一些测试保护你,尝试从责任和生命周期的角度思考。例如,在WPF应用程序中,具有" initializable"是一个常见的问题。 ViewModel因为他们做了一些异步Web服务调用来初始化自己。

在这种情况下,具有给定ViewModel生命周期责任的对象也有责任初始化它。如果它管理几个可初始化的视图模型,那么这种代码就可以了:

foreach (var initializable in initializables)
{
    initializable.Initialize();
}

但是,无论您选择何种解决方案,请在Initialize和Reinitialize之间保持清晰的分离(如果它们有共同点,则将它们称为内部共享函数)。写下这样的东西是一个非常糟糕的主意:

init.Initialize(true);

它清楚地表明Initialize函数的行为将根据布尔值而改变。如果您有2个行为,则应该有2个具有明确命名的功能。