![](/img/trans.png)
[英]When should I use public, private, or [SerializeField]? Unity C#
[英]when should i create a private method in c#
自从关注DI和TDD之后,我对何时应该创建私有方法感到困惑。 您能否告诉我在制定方法私有保持可测试性和依赖注入时,应该考虑哪些经验法则?
我相信一个例子可能会有所帮助:
假设我有一个包含3个方法的接口,如下所示:
public interface IWordFrequencyAnalyzer
{
int CalculateHighestFrequency(string forText);
int CalculateFrequencyForWord(string text, string word);
IList<IWordFrequency> CalculateMostFrequentNWords(
string text, int n);
}
现在,我可以编写一个类,它可以实现一个私有方法,它接受一个字符串,并可以计算其中的单词的频率,然后在每个公共方法中,我可以根据它的要求进行操作。在这种情况下,我将是能够测试合同。
要么
我可以将私有方法提取到单独的类中,例如WordProcessor,它实现IWordProcessor,使用单个公共方法将句子拆分为单词并将其作为依赖项传递给IWordFrequencyAnalyzer的实现。 这样,分割单词的实现也是可测试的。
你会建议采用哪种方法?
谢谢,-Mike
由于越来越多地使用DI和TDD,我最终越来越少地使用私有方法,但原因并不是因为我需要将它们公开用于测试。 更多的是因为,作为使用DI的副产品,我正在学习更多关于将SOLID原则应用于我的代码的知识,而这(反过来)正在引导我编写整体方法较少且几乎没有私有的类。
所以,假设您在课程的各种方法中使用了一段代码。 你知道DRY,你将它重构为私有方法,一切都很好。 除了通常你意识到你可以概括那个私有方法做什么并将该功能作为类的外部依赖注入:这样,你可以测试它并模拟它,当然,但最重要的是你可以重用那个方法甚至在其他课程或其他项目,如果需要。 将其移出原始类是单一责任原则的应用。
正如我所说,我对代码的改变并不直接取决于我使用TDD或DI的事实,但它是TDD鼓励我强制执行的原则的副产品以及DI容器在组成许多小的时候提供的便利性这种方法产生的类。
编辑:您添加到您的问题的示例中的第二种方法是我所谈论的一个很好的例子。 您的新WordProcessor类现在可测试的事实是一个优点,但它现在可组合和可重用的事实是真正的好处。
您的方法应该是private
除非他们需要public
您的应用程序,而不是您的测试。
一般来说,你不应该public
只是为了支持单元测试( internal
可能有帮助)。 在这种情况下,您通常应该测试public
接口,而不是类的private
细节,这更有可能改变并破坏您的测试。
如果您可以访问副本,Roy Osherove的“ 单元测试艺术 ”可以很好地解决这个问题
当特定方法仅由对象在内部使用时,它们通常从其他方法调用,其中一些方法将是公共的或受保护的。 由于遵循DRY(不要重复自己)原则,您更有可能创建私有方法。 在这种情况下,您将几个方法使用的一些常用代码提取到这些方法调用的私有方法中。
将类的每个方法公开并为此类的每个方法编写单元测试都会很快造成维护噩梦,因为您必须为生产代码中的每一个小重构更改测试。 您希望测试类本身的行为,为此您不需要公开每个方法。
你应该尽可能保持你的方法私有。 不要将它们更改为公开用于单元测试。 当你发现很难测试它时,请考虑改变你的类的一点点架构。 根据我的经验,通常当我需要测试私有方法时,类有错误的责任,所以我改变了它。
单一责任政策将帮助您解决此问题。 考虑这个例子:
internal class Boss
{
private bool _notEnoughStaff;
private IList<Employee> _staff;
public Boss(bool notEnoughStaff)
{
_notEnoughStaff = notEnoughStaff;
}
public void GiveOrders()
{
if (_notEnoughStaff)
HireStaff();
foreach (Employee employee in _staff)
{
employee.DoWork();
}
}
private void HireStaff()
{
_staff.Add(new Employee());
}
}
public class Employee
{
public void DoWork()
{
}
}
在这种情况下,我看到的不仅仅是两个责任:老板代表工作和雇用新员工。 在这个例子中,我总是将私有方法HireStaff提取到一个新类(让我们称之为HR),然后将它注入到Boss类中。 这是一个非常简单的例子,但随着您在TDD思维方式方面的经验越来越丰富,您会发现没有多少私有方法具有合法性。
此致,莫滕
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.