2010-10-14 61 views
1

在我的项目的核心库,我们有一个非常大的类,它正趋向于成为一个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,反之亦然,这我知道这不会产生任何编译问题,只要。

这是一个很好的解决方案,并有在这样的情况下,任何更好的方法?

回答

1

这是个不错的中间步骤,因为它至少给你一个划分出来的功能,并证明有扩展名为“模块”之间没有方法间的依赖关系。这是创建真实子类的第一步,虽然它仍然不理想(你不能单独实例化模块类进行单元测试)。

一旦你有了这个分区,它应该更容易创建新的类,因为你已经确定了模块边界。该过程将如下所示:

  1. 传递给扩展方法的参数成为新类的字段,它在构造函数中设置。

  2. 所有的扩展方法成为新类的方法。

  3. 现在,您可以提取主类的接口,让子类不再依赖于全面实施。在某些情况下,您可以通过将功能分解为多个接口来进一步减少依赖关系

  4. 既然您已通过接口进行依赖关系隔离,则可以为单个模块编写单元测试。

0

扩展方法只是一个“语法糖”。您可以定义常用的静态方法,并使HugeClass实例成为其中一个参数。 所以它没有区别。编译后的CIL文件将是相同的。

+0

是的,但这会打破我想避免的模块的编译。 – 2010-10-14 18:33:09

0

我看到您的设计不同,但您为什么没有使用Workflow Foundation 4.0?它很容易和灵活。您可以在工作流程中将代码编写为CodeActivity。我认为你可以假设一个工作流(活动)作为一个新的模块作业,可以添加到核心。

更多了,可以动态生成工作流(活动),这将是非常有用的。

(对不起我的英文不好)

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这是一本很棒的阅读材料。其中他讨论了这一点以及其他许多技术。