我有一个遗留的C#库(一组相互关联的算法),其中有一个传递给所有类的全局神对象。这个上帝对象(简称为Manager:D)有一个Parameters成员和一个ObjectCollection成员(在很多其他成员中)。
public class Manager
{
public Parameters {get; private set;}
public ObjectCollection {get; private set;}
...
...
}
我无法测试算法,因为所有内容都将管理器作为依赖项,初始化意味着我必须初始化所有内容。所以我想重构这个设计。
参数中包含100多个字段,这些值控制着不同的算法。 ObjectCollection具有整体执行引擎所需的实体,由Id,Name等存储。
以下是我所采用的方法,但不满意:
传递参数和ObjectCollection(或IParameters和IObjectCollection)而不是Manager,但我认为这不会解决任何问题。我不知道算法将依赖哪些参数。
将参数类拆分为较小的参数类也很困难,因为一个参数可能影响许多算法,因此逻辑分离很困难。此外,每种算法的依赖关系最终可能会很多。
类似单例模式通常是为Logger完成的,但这也是不可测试的。
某些参数控制算法逻辑,算法只需要一些参数。我正在考虑使每个算法成为一个实现接口的独立类,并在应用程序启动时,根据参数决定实例化哪个算法。我可能最终将当前的一组算法类别拆分为更多,我担心我最终会使它更复杂并失去算法的结构。
有没有任何标准的方法来处理这个问题,或者只是将大类拆分为较小的类并通过构造函数传递依赖关系是唯一的一般建议?
答案 0 :(得分:2)
为了让自己做出小步骤,我将从一个算法开始,并确定它需要的参数。然后可以在接口中公开这些......
public interface IAmTheParametersForAlgorithm1
{
int OneThing {get;}
int AnotherThing {get;}
}
然后你可以改变Manager
以便它实现那个接口,就像在@marcel的答案中直接在Manager上公开那些参数一样。
现在,您可以使用非常小的模拟或自分析来测试Algorithm1,因为您不需要初始化巨大的Manager来运行测试。而Algorithm1不再知道它需要一个Manager对象。
public Manager : IAmTheParametersForAlgorithm1 {}
public class Algorithm1
{
public Algorithm1(IAmTheParametersForAlgorithm1 parameters){}
}
您可以一点一点地继续将其扩展到每个参数集,并且处理小的特定接口将允许您识别不同算法具有共同参数的位置。
public Manager :
IAmTheParametersForAlgorithm1,
IAmTheParametersForAlgorithm2,
IAmTheParametersForAlgorithm3,
IAmTheParametersForAlgorithm4 {}
这也意味着当您识别其参数不再在其接口外部访问的算法时,您可以停止将Manager注入这些算法,将参数从Manager中取出,并创建一个仅提供这些参数的新类。
这意味着,如果您无法投入时间进行巨大的重大变更,那么您可以在进行此更改的整个过程中保持应用程序正常运行
答案 1 :(得分:0)
对于参数,我会用这样的东西:
public class Parameters
{
public int MyProperty1 { get; set; }
public int MyProperty2 { get; set; }
public int MyProperty3 { get; set; }
}
public class AlgorithmParameters1
{
private Parameters parameters;
public int MyProperty1 { get { return parameters.MyProperty1; } }
public int MyProperty3 { get { return parameters.MyProperty3; } }
public AlgorithmParameters1(Parameters parameters)
{
this.parameters = parameters;
}
}
public class Algorithm1
{
public void Run(AlgorithmParameters1 parameters)
{
//Access only MyProperty1 and MyProperty3...
}
}
用法如下:
var parameters = new Parameters()
{
MyProperty1 = 4,
MyProperty2 = 5,
MyProperty3 = 6,
};
new Algorithm1().Run(new AlgorithmParameters1(parameters));
顺便说一下,我不知道你如何区分控制算法的参数和它所需的参数。通过控制你的意思是他们习惯于决定采用哪种算法?