有条件的大条件的设计模式

时间:2011-09-23 19:06:25

标签: c# design-patterns

我正在重写一个程序的野兽,它可以完成所有事情并且它是厨房水槽。这是一个电话IVR系统(按1表示等等,按2表示......)我已将所有功能分配到他们自己的项目中,但是当我们第一次接听电话时,我的最大痛点就出现了用户输入一个代码,让我们知道将调用者分派到哪个系统。

整个代码系统是一个混乱的TBH,但它无法更改,我已经重构了大约800行的VB6到类似下面的代码:

string code = foo.GetAccessCodeFromCaller();
if (DatabaseCheck1(code)
{
    parse = ParseCode(code);
    dbValue = GetSomethingFromDB(parse);
    if (OtherCheck1(dbValue)
    {
        // Launch the Pay Taxes project.
    }
    else if (OtherCheck2(dbValue)
    {
        // Launch the Uploaded File project
    }
    else
    {
        // Schedule Something or other project
    }
}
else if (LookForSomethingElseInDB(code)
{
    parse2 = AltParseMethod(code)
    if (Conditional(parse2))
    {
        if (LargeChunkOfCodeConditional(code))
        {
            // Report a something or other project.
        }
        else
        {
            // Talk to Tech Support.
        }
    }
    else
    {
        // Invalid Input
    }
}
else
{
    if (YetAnotherChunkOfCode(code))
    {
        // Order products project
    }
    else
    {
        // Invalid Input.
    }
}

我需要一个好的架构才能让这个系统正确完成,正确的方法就是适应更多适合让它变得更糟糕的鞋子。最初的系统是在VB4 / 5中完成的,并持续了近16年的近月变化。我想要的东西能够有条不紊地保持这种混乱,并且可以在接下来的16年里轻松添加垃圾。

到目前为止,我已经尝试了一些模式(访问者和命令),但似乎没有什么比我尝试实现它的方式更好。。这里的任何建议都将非常感激。

编辑: 为了更清楚一点,我当前的架构有一个解决方案,包括以下项目:Dispatch,PayTaxes,UploadedFiles,ScheduleSomething,ReportSomething,TechSupportRedirect,OrderProducts等...(以及HardwareAbstraction,SharedInterfaces和DatabaseAccess项目)。 Dispatch使用HardwareAbstraction项目来接听电话并询问呼叫者代码,然后将呼叫路由到执行完全不同任务的其他10个项目中的一个(然后可以由10个不同的开发人员并行重写,而不会踩到脚趾) 。

我可以很好地弄清楚目标项目的架构,但实际的Dispatch项目正在绊倒我。此外,如果我的整个解决方案架构是某种反模式,有人会在我走得太远之前让我知道。

6 个答案:

答案 0 :(得分:1)

也许你需要的只是一个简单的ExtractMethod来排除条件的大型内部体以分离方法。

答案 1 :(得分:1)

我对VB6一无所知,但是如何将代码映射到“委托”(如果VB6中存在该概念则不知道)。这个想法是:输入代码是返回调用方法的字典的“键”(如果没有找到这样的代码,则为Empty / Null / Nothing)。

<强>更新 如果这是用C#编写的,那么你不能把代码放到

Dictionary<string, Action> OpCodes;

然后执行以下操作:

if(OpCodes.ContainsKey(code))
  OpCodes[code]();

更新2: 看起来你有条件的“层次”。我想这会映射到“词典词典”。但是考虑一下这个问题:用户输入一系列选择,这些选择应该在某种行为中结束,听起来像:为每个系统行为定义“委托”,并映射到代码:

像:

OpCodes["123"] = new Action(TechSupport.StartConversation);

答案 2 :(得分:0)

如果你重新编写它来创建不同的类来处理不同的代码,它可能会使你的代码库更易于维护。

这样的东西
var codeHandler = CodeHandlerDecider.GetCodeHandlerFor(
    foo.GetAccessCodeFromCaller());
codeHandler.HandleCode();

然后你的CodeHandlerDecider会做这样的事情:

public static ICodeHandler GetCodeHandlerFor(string code)
{
    if (DatabaseCheck1(code)
    {
        return new FirstCodeHandlerClass(code);            
    }
    else if (LookForSomethingElseInDB(code)
    {
        return new SecondCodeHandlerClass(code);            
    }
    else
    {
        return new ThirdCodeHandlerClass(code);
    }
}

然后一个示例类将是

public class FirstCodeHandlerClass: ICodeHandler
{
    public void HandleCode(string code)
    {
        parse = ParseCode(code);
        dbValue = GetSomethingFromDB(parse);
        if (OtherCheck1(dbValue)
        {
            // Launch the Pay Taxes project.
        }
        else if (OtherCheck2(dbValue)
        {
            // Launch the Uploaded File project
        }
        else
        {
            // Schedule Something or other project
        }
    }
}

,界面看起来像

public interface ICodeHandler
{
    void HandleCode();
}

答案 3 :(得分:0)

这听起来像Finite-State Machine的工作!您甚至可以想象并创建外部DSL,因为状态机非常适合这种情况。事实上,我刚刚发现a project on codeplex似乎使用电话系统作为主要示例。

答案 4 :(得分:0)

这类问题有两种常见的模式:

1)子类化/继承以实现多态分派

2)表驱动编程

基本思想是放置允许您在表中做出决定的信息,然后编写遍历表的代码。如果你保持一个有趣的角度,多态方法只是表驱动的编程,直接构建在语言中。表驱动技术为您提供以下好处:更具声明性,更小的代码大小,易于扩展/添加新案例,更清晰。

正如其他人所说,您可以使用词典实现此模式。

答案 5 :(得分:0)

感谢所有在这里插话的人,由于我通过一些心理障碍的建议,发现责任链模式将很好地解决我的问题。Here's the MSDN article on how to implement it.

相关问题