1

在我项目的核心库中,我们有一个非常大的类,它趋向于成为上帝对象。原因之一是,在一段时间内,应该在不同模块中的任务被放到了这个类中。对于前 -

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,反之亦然,我确信这一点。

这是一个好的解决方案吗?在这种情况下有没有更好的方法?

4

4 回答 4

1

这不是一个糟糕的中间步骤,因为它至少为您提供了一种划分功能并证明扩展“模块”之间没有方法相互依赖关系的方法。这是朝着创建真正的子类迈出的重要一步,尽管它仍然不理想(您不能单独实例化模块类以进行单元测试。)

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

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

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

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

  4. 现在您已经通过接口进行了依赖隔离,您可以为各个模块编写单元测试。

于 2010-10-14T18:29:17.013 回答
0

扩展方法只是一个“语法糖”。您可以定义通用静态方法并将 HugeClass 实例作为其参数之一。所以没有区别。编译后的 CIL 文件也是一样的。

于 2010-10-14T18:28:06.403 回答
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() {
    }
}

通过这种方式,随着时间的推移,您正在使用带有 HugeClass的外观模式。我应用到 HugeClass 方法的Obsolete 属性意味着每次编译调用 HugeClass 中的方法的东西都会生成一个警告,指出新功能的位置。属性中的 'false' 参数使其成为警告,可以将其更改为 true 以使其成为错误。通过这种方式,您不会做太多额外的工作,它代表了您想要达到的进步,我不相信您的扩展方法技术一定会这样做。随着时间的推移,HugeClass 中的方法可以被删除,直到它是一个空类并且本身可以被删除。

顺便说一句,如果您还没有读过 Martin Fowler 的书Refactoring,那么它是一本极好的读物。在其中,他讨论了这个和许多其他技术。

于 2010-10-14T19:35:42.860 回答
0

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

此外,您可以动态生成非常有用的工作流(活动)。

(对不起我的英语不好)

于 2010-10-14T18:59:48.430 回答