将公共方法转换为扩展方法

发布于 2024-09-27 04:29:35 字数 724 浏览 0 评论 0原文

在我的项目的核心库中,我们有一个非常大的类,它往往会成为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 ,反之亦然,我确信这一点。

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

In my project's core library we have a very big class, which is tending to become a God object. One of the reasons is that, over a period of time, tasks which should have been in different modules have been put into this class. For ex -

class HugeClass{
    public void DoModuleXJob(){}
    public void DoModuleYJob(){}
}

One of the problems in refactoring and moving the unwanted, module specific behavior out of this class is that it will be a lot of work for Module X and Module Y to change their code.
As a work around I was thinking about converting these methods into extension methods and then move them to their concerned modules. For ex -

// 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){}
}

I found that this does not create any compilation problems, as long as Module Y is not using DoModuleXJob and vice-versa, which I am sure about.

Is this a good solution and are there any better methods in such a case?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

时光礼记 2024-10-04 04:29:35

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

一旦进行了此分区,它应该可以更轻松地创建新类,因为您已经已经确定了模块边界。该过程将如下所示:

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

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

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

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

This is not a bad intermediate step, as it at least gives you a way to partition out the functionality and prove that there are no method inter-dependencies between the extension 'modules'. That's a great first step toward creating true subclasses, though it's still not ideal (you can't instantiate the module classes individually for unit testing.)

Once you have this partitioning, it should make it easier to create new classes, as you've already identified the module boundaries. The process would go like this:

  1. The parameter passed to the extension method becomes a field on the new class, which is set in the constructor.

  2. All of the extension methods become methods of the new class.

  3. You can now extract an interface for the main class, so the sub-classes no longer depend on the full implementation. In some cases, you might be able to further reduce dependencies by breaking the functionality into multiple interfaces

  4. Now that you have dependency isolation through interfaces, you can write unit tests for individual modules.

篱下浅笙歌 2024-10-04 04:29:35

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

Extension methods is just a "syntax sugar". You can define common static method and make HugeClass instance one of it parameters.
So it is no difference. CIL file after compilation will be the same.

叹梦 2024-10-04 04:29:35

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

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

(请原谅我的英语不好)

I see your design is different, but why you did not use the Workflow Foundation 4.0? It's easy and flexible. You can write your code as CodeActivity in workflows. I think you can suppose a workflow (Activity) as a new module job which could be added to the core.

More over you can dynamically generate the workflows (Activities) which will be very useful.

(Excuse me for my bad english)

满天都是小星星 2024-10-04 04:29:35

它应该在的位置,然后将方法调用保留在 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 的 外观模式。我应用于 HugeClass 方法的 Obsolete 属性 意味着每次编译调用 HugeClass 中的方法时,都会生成一个警告,指出新功能的位置。属性中的“false”参数使其成为警告,可以将其更改为 true 以使其成为错误。通过这种方式,您不需要做太多额外的工作,它代表了您想要达到的目标的进展,我不相信您的扩展方法技术一定会做到这一点。随着时间的推移,HugeClass 中的方法可以被删除,直到它成为一个空类并且本身可以被删除。

顺便说一句,如果您还没有读过 Martin Fowler 的书重构,那么这是一本很好的读物。他在其中讨论了这一技术以及许多其他技术。

I would suggest that you create the design as it should be, moving the functionality that is in HugeClass to the spot that it should be, and then leave the method call in HugeClass but have it defer to the functionality to where it was moved:

class HugeClass
{
    [Obsolete("Use ModuleX.DoModuleXJob() instead", false)]
    public void DoModuleXJob() {
        ModuleX mod = new ModuleX();
        mod.DoModuleXJob();
    }
}
class ModuleX
{
    public void DoModuleXJob() {
    }
}

In this way over time you are employing the Facade Pattern with HugeClass. The Obsolete attribute that I have applied to the HugeClass method means that every time something is compiled that calls the method in HugeClass a warning will be generated, pointing to where the new functionality is. The 'false' parameter in the attribute is what makes it a warning, this could be changed to true to make it an error. In this way you are not doing much extra work and it represents progress to where you want to be, which I don't believe your extension method technique would do necessarily. Over time the methods in HugeClass can be deleted until it is an empty class and itself can be deleted.

Incidently, if you have not read Martin Fowler's book Refactoring it is an excellent read. In it he discusses this and many other techniques.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文