简体   繁体   English

如何重构这个巨大的switch语句?

[英]How to refactor this huge switch statement?

I've inherited some code and within it is a 500 line switch statement. 我继承了一些代码,其中包含500行开关语句。 Basically, it switches on a string task and executes the corresponding actions. 基本上,它会打开string任务并执行相应的操作。

I have since moved each case statement in to their own method in a new class. 之后我将每个case语句移动到一个新类中的自己的方法中。 The giant switch statement still exists but instead of inlining the logic each case just calls a method so it's much neater. 巨大的switch语句仍然存在,但不是内联逻辑,而是每种情况只调用一个方法,所以它更整洁。

The problem is that the methods modify a lot of different things. 问题是这些方法修改了很多不同的东西。 50% of the methods require 0 arguments passed in. Some 40% require 5 arguments and the remaining 10% require 10 arguments each. 50%的方法需要传入0个参数。大约40%需要5个参数,剩下的10%需要10个参数。

Currently this works but I'd like to make it better. 目前这有效,但我想让它变得更好。 Either get rid of the switch statement or lower the amount of passed in parameters somehow. 要么以某种方式摆脱switch语句或降低传入参数的数量。

I was thinking of using a Dictionary that mapped string s to Action s to eliminate the entire switch, but this wouldn't work because I'm using a lot of ref parameters (primitive types) and there'd be no way to pass those in to the constructor and have them later be referentially modified. 我正在考虑使用一个Dictionary ,将string s映射到Action s以消除整个开关,但这不起作用,因为我使用了很多ref参数(原始类型),并且没有办法传递那些在构造函数中,稍后将对它们进行引用修改。

The obvious solution to that problem is just to place all 16 or so variables in to a separate class and pass that but a lot of them aren't very related so it just replaces one problem with another (long parameter list with non-cohesive data class). 这个问题的显而易见的解决方案就是将所有16个左右的变量放入一个单独的类中并传递它,但是它们中的很多都不是很相关,因此它只是将一个问题替换为另一个问题(具有非内聚数据的长参数列表)类)。

Was wondering if there were any other ways to improve this code. 想知道是否有任何其他方法来改进此代码。 Thanks for reading. 谢谢阅读。

Without being able to look at any kind of code, the only advice I can give is that you is that you should think about refactoring with testing in mind using SOLID design principles . 无法查看任何类型的代码,我可以给出的唯一建议是,您应该考虑使用SOLID设计原则进行重构测试。 I would try to create different classes for each module of logic (or condition of the switch), pass in dependencies through the constructors of those objects (rather than as parameters of methods) and try to create some uniform interfaces that you can use to work in some tests. 我会尝试为每个逻辑模块(或交换机的条件)创建不同的类,通过这些对象的构造函数(而不是方法的参数)传递依赖关系,并尝试创建一些可用于工作的统一接口在一些测试中。 You may want to extract the conditional creation of those objects by throwing in a factory. 您可能希望通过投入工厂来提取这些对象的条件创建。 Sounds like a mess though. 听起来像是一团糟。 Good luck. 祝好运。

Since your question includes no code, the answer can't really either. 由于您的问题不包含任何代码,因此答案也不是。 I think the best thing to do is to point you to page 82 of one of the all-time best software books: Refactoring: Improving the Design of Existing Code . 我认为最好的办法是为您指出其中一本史上最好的软件书籍的第82页: 重构:改进现有代码的设计

"One of the most obvious symptoms of object-oriented code is its comparative lack of switch statements. Most times you see a switch statement you should consider polymorphism." “面向对象代码最明显的症状之一是它相对缺乏switch语句。大多数时候你会看到一个switch语句,你应该考虑多态性。”

He then lists some of the specific patterns to be used to help make this happen. 然后,他列出了一些用于帮助实现这一目标的具体模式。

You can use ref parameters in delegates but you can't use the built-in Action or Func generic delegates. 您可以在委托中使用ref参数,但不能使用内置的ActionFunc泛型委托。 You must define your own like so: 您必须像这样定义自己的:

public delegate void DelegateWithRefParameters(ref int i, ref long l, ref bool b, ref object o);

public class Program
{
    public static void Main(string[] args)
    {
        int i = 0;
        long l = 0;
        bool b = false;
        object o = null;

        var lookup = new Dictionary<string, DelegateWithRefParameters>() 
        {
            { "object", ModifyObject },
            { "int", ModifyInt },
            { "bool", ModifyBool },
        };

        string s = "object";

        lookup[s](ref i, ref l, ref b, ref o);
    }

    private static void ModifyObject(ref int i, ref long l, ref bool b, ref object o)
    {
        o = new object();
    }

    private static void ModifyInt(ref int i, ref long l, ref bool b, ref object o)
    {
        i++;
    }

    private static void ModifyBool(ref int i, ref long l, ref bool b, ref object o)
    {
        b = !b;
    }              

}

You will just have to modify all your methods to use the same signature. 您只需修改所有方法即可使用相同的签名。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM