如何保持我的功能(对象/方法)'精益和意味'

时间:2010-06-09 11:52:46

标签: c# .net unit-testing agile

在我读到的所有(敏捷)文章中:保持代码和函数的小巧且易于测试。

我应该如何使用'控制器'或'协调员'课程?

在我的情况下,我必须导入数据。最后,我有一个协调这个的对象,我想知道是否有一种方法可以保持协调员精益(呃)和意味着(呃)。

我的协调员现在执行跟随(伪代码)

//Write to the log that the import has started
Log.StartImport()
//Get the data in Excel sheet format
result = new Downloader().GetExcelFile()
//Log this step
Log.LogStep(result )
//convert the data to intern objects
result = new Converter().Convertdata(result);
//Log this step
Log.LogStep(result )
//write the data
result = Repository.SaveData(result);
//Log this step
Log.LogStep(result )
Imho,这是“知道所有”课程中的一个,或者至少有一个是“不瘦和卑鄙”? 或者,我是否正在采取这种精益而且意味深远的事情,如果没有某种“肥胖”的进口商/协调员,是不可能对进口进行编程?

米歇尔

EDIT 这实际上是一个二合一的问题:一个是如何测试它,第二个是如果可以拥有一个'全部知道/粘合在一起'的协调员

5 个答案:

答案 0 :(得分:11)

我相信很多人都不同意,但我认为你的方法总体来说足够精益。你在这里缺少的关键部分是依赖注入(也称为控制反转) - 所以不要在你的方法中新建Downloader,Converter等,你应该为这些类定义接口并在你的构造函数中“注入”它们类:

private Downloader downloader;
private Converter converter;

public MyClass(Downloader downloader, Converter converter)
{
  this.downloader = downloader;
  this.converter = converter;
  //same with repository, it can't be a static class anymore
}

然后你只需在你的方法中使用这些实例:

//Write to the log that the import has started
Log.StartImport()
//Get the data in Excel sheet format
result = downloader.GetExcelFile()
//Log this step
Log.LogStep(result )
//convert the data to intern objects
result = converter.Convertdata(result);
//Log this step
Log.LogStep(result )
//write the data
result = repository.SaveData(result);
//Log this step
Log.LogStep(result )

现在执行此更改后,在测试中,您可以使用其中一个模拟框架(我使用RhinoMocks)将依赖项的模拟实现注入到您的类中。这样您就可以验证在转换器和下载器上调用了正确的方法,而无需从磁盘读取任何内容并解析任何电子表格。

如何使用RhinoMocks的示例在他们的文档中:http://ayende.com/wiki/Rhino+Mocks+Documentation.ashx

如果你遇到问题,请不要犹豫,提出另一个问题:)

答案 1 :(得分:3)

我有类似的问题,我解决它的方法是真正正确看待SRP(单一责任委托人)。

ExcelFileReader 谁可以读取excel文件并返回一组List(行)

解析器它的工作是使用分隔符解析从ExcelFileReader返回的行

导入程序,它处理从FileParser返回的DataSet导入正确的表。

这使其保持可测试形式,因为ExcelFileReader不依赖于Parser或Importer。这适用于Parser,只需将TextReader传递给它就可以测试。

这有帮助吗?

答案 2 :(得分:1)

有一个班级可以做我认为的 mediator pattern

我发现打击必须有合作者的课程(这就是你现在遇到的)的一种方法是做模拟单元测试

你基本上嘲笑你的合作者并为这些合作者设定期望。

不幸的是你正在使用C#而我不知道C#的任何Mock库。 但是我相信谷歌可以帮你找到一个模拟库。

您可以只使用模拟库来实现或扩展协作者的类,并覆盖和实现您希望使用产生预期输出的方法调用的方法。

正如迈克尔所指出的那样,如果你的协作者有依赖注入接线,那就更容易了。

答案 3 :(得分:1)

您的评论和记录器(单身?)太吵了:

Log.StartImport();
result = new Downloader().GetExcelFile()
Log.Step(result);
result = new Converter().Convertdata(result);
Log.Step(result);
result = Repository.SaveData(result);
Log.Step(result);

由于你有三个必须一起发生的步骤,所以它们会在Converter中完成。使用DI传递到Converter DownloaderRepository。现在你最终得到:

Log.StartConvert();
convert.ExcelToRepository(); //passed in with DI

注意所有Log步骤结果都在相应的操作中完成。

答案 4 :(得分:0)

我发现这个article在决定我的代码是否真的精简并且意味着

时特别有用