在我的项目的核心库中,我们有一个非常大的类,它倾向于成为God object。其中一个原因是,在一段时间内,应该在不同模块中的任务已被纳入本课程。对于前 -
class HugeClass{
public void DoModuleXJob(){}
public void DoModuleYJob(){}
}
重构和移动不需要的模块特定行为的问题之一是模块X和模块Y更改其代码将需要做很多工作。 作为一种解决方法,我正在考虑将这些方法转换为扩展方法,然后将它们移动到相关的模块中。对于前 -
// in module X
static class HugeClassExtensions{
public static void DoModuleXJob(this HugeClass instance){}
}
// in module Y
static class HugeClassExtensions{
public static void DoModuleYJob(this HugeClass instance){}
}
我发现这不会产生任何编译问题,只要模块Y没有使用DoModuleXJob,反之亦然,我相信。
这是一个很好的解决方案吗?在这种情况下有没有更好的方法?
答案 0 :(得分:1)
这不是一个糟糕的中间步骤,因为它至少为您提供了一种分区功能并证明扩展“模块”之间没有方法相互依赖关系的方法。这是创建真正的子类的第一步,虽然它仍然不理想(你无法单独为单元测试实例化模块类。)
一旦进行了这种分区,就可以更容易地创建新类,因为您已经确定了模块边界。这个过程会是这样的:
传递给扩展方法的参数成为新类的一个字段,该字段在构造函数中设置。
所有扩展方法都成为新类的方法。
您现在可以提取主类的接口,因此子类不再依赖于完整实现。在某些情况下,您可以通过将功能分解为多个接口来进一步减少依赖性
现在您已通过接口进行依赖关系隔离,您可以为各个模块编写单元测试。
答案 1 :(得分:0)
扩展方法只是一种“语法糖”。您可以定义公共静态方法,并使HugeClass实例成为其中一个参数。 所以没有区别。编译后的CIL文件将是相同的。
答案 2 :(得分:0)
我看到你的设计不同,但为什么你没有使用Workflow Foundation 4.0?它简单灵活。您可以在工作流程中将代码编写为CodeActivity。我认为您可以将工作流程(Activity)假设为可以添加到核心的新模块作业。
您可以动态生成非常有用的工作流程(活动)。
(对不起我的英语不好)
答案 3 :(得分:0)
我建议您按原样创建设计,将HugeClass中的功能移动到应该的位置,然后将方法调用留在HugeClass中,但是让它遵循功能到它的位置移动:
class HugeClass
{
[Obsolete("Use ModuleX.DoModuleXJob() instead", false)]
public void DoModuleXJob() {
ModuleX mod = new ModuleX();
mod.DoModuleXJob();
}
}
class ModuleX
{
public void DoModuleXJob() {
}
}
这样,随着时间的推移,您将Facade Pattern与HugeClass一起使用。我已经应用于HugeClass方法的Obsolete attribute意味着每次编译调用HugeClass中的方法的内容时,都会生成警告,指向新功能的位置。属性中的'false'参数是使其成为警告的原因,可以将其更改为true以使其成为错误。通过这种方式,你没有做太多额外的工作,它代表了你想要的进展,我不相信你的扩展方法技术必然会做。随着时间的推移,可以删除HugeClass中的方法,直到它是一个空类,并且可以删除它。
很明显,如果你还没有读过Martin Fowler的书Refactoring,这是一本很好的读物。在其中,他讨论了这个和许多其他技术。