我正在重写一个程序的野兽,它可以完成所有事情并且它是厨房水槽。这是一个电话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项目正在绊倒我。此外,如果我的整个解决方案架构是某种反模式,有人会在我走得太远之前让我知道。
答案 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.