2016-05-30 40 views
0

我正试图在工作中的一个应用程序中重写非常难看的类。在我们的一个类中,有数百行代码确保某些类的初始化和重新初始化。目前,这是通过可怕的强力-y方式完成的,在这种方式中,您编写init代码并手动将其复制到re-init部分(因为它们非常相似)。延迟或可重复初始化的最优雅方式

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

https://dotnetfiddle.net/RVS5UT

我还创建类CustomInitializer它实现IInitializer,只需要一个Func键作为参数,并运行它的初始化,对于初始化是很多不同的情况。

现在,这个简化和匿名的工作代码块,但它的工作原理。问题是整个方法非常尴尬,构造函数签名很糟糕。有什么方法可以简化吗?我找不到可以帮助我的任何模式或方法?任何迈向更好代码的步骤都是值得欢迎的,也许我只是错过了一些东西。

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

我使用.NET 4.0,C#5.0

编辑:我要初始化的类型没有接入(另一种愚蠢的捕捞)

感谢您的帮助。

+0

为什么不简单地用新的实例替换旧实例?重新初始化可以通过简单地引用新实例来完成。无论如何,一个如此之大的班级没有任何意义。所有这些属性之间的凝聚力是什么?这个班级的单一指数是多少?它有什么行为?重新初始化这个类是什么意思?有时最好解释最初的问题,并将所有当前的解决方案部分从图片中删除。 – plalx

回答

1

文件已超过18K线

哇,看起来像一个很大的乐趣。

试图改善它是绝对好的。相信我,不管你的同事怎么想,除了这个代码不需要进化,没有别的事可做。

但是,在我看来,你走在复杂性的道路上,试图做到DRY而不是试图表达。使用StandardInitializer和CustomInitializer管理lambda表达式的想法非常复杂。一个类的初始化应该在它负责初始化的类中。如果某些行为真的被共享,他们可能共享一个基类或一个协作类。

我建议你在Working Effectively With Legacy Code的这个讨论。正如你将会看到并且可能已经知道的那样,第一个关键点是要进行测试。 请不要尝试在没有测试工具的情况下重构这样的课程。否则,你会引入回归,你会感到沮丧,并且你的同事会对他们的愿景感到欣慰,即在没有破坏一切的情况下,任何事情都无法在这里完成。

不要忘记,如果测试很难创建,那是因为代码不好,不是因为测试昂贵。错误代码很昂贵。

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

在这种情况下,具有给定ViewModel生命周期责任的对象也有责任对其进行初始化。如果管理几个Initializable视图模型,那么这种代码是罚款:

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

但是,请你选择的任何解决方案,保持初始化并重新初始化(明确分开,如果他们有共同的东西,让他们打电话给一个内部共享功能)。这是一个非常糟糕的主意,写这样的东西:

init.Initialize(true); 

它明确指出您的初始化函数的行为将根据一个布尔值的改变。如果你有两种行为,你应该有两个功能,命名清晰。

+0

我没有提到(我认为这不重要),初始化的对象是由COM库构造的,所以我无法访问该类,也无法将init添加到类本身。我需要创建一些镜像辅助类,并将其保存在那里或作为扩展方法。也没有测试,可悲的是不会有测试。 。所以我故意尽量保持变化尽可能小(因为回归)。 –

+0

忘记感谢您的帮助。 。谢谢 –