简体   繁体   English

我何时应该在c#中创建一个私有方法

[英]when should i create a private method in c#

Since following DI and TDD, I'm bit confused as to when should I create a private method. 自从关注DI和TDD之后,我对何时应该创建私有方法感到困惑。 Could you please tell me what should be the rules of thumb to be considered while making a method private keeping testability and Dependency injection in mind? 您能否告诉我在制定方法私有保持可测试性和依赖注入时,应该考虑哪些经验法则?

I believe an example might help here: 我相信一个例子可能会有所帮助:

Assume I have an interface with 3 methods like the following: 假设我有一个包含3个方法的接口,如下所示:

public interface IWordFrequencyAnalyzer
{
    int CalculateHighestFrequency(string forText);
    int CalculateFrequencyForWord(string text, string word);
    IList<IWordFrequency> CalculateMostFrequentNWords(
        string text, int n);
}

Now, I can write a class which can implement a private method which takes a string and can compute the frequency of words in it, and later in each public method I can do a manipulation according to it's requirement.In this case I'll be able to test the contract. 现在,我可以编写一个类,它可以实现一个私有方法,它接受一个字符串,并可以计算其中的单词的频率,然后在每个公共方法中,我可以根据它的要求进行操作。在这种情况下,我将是能够测试合同。

OR 要么

I can extract that private method into a seperate class say something like WordProcessor which implements IWordProcessor, with a single public method which splits the sentence into words and pass it as dependency to the implementation of IWordFrequencyAnalyzer. 我可以将私有方法提取到单独的类中,例如WordProcessor,它实现IWordProcessor,使用单个公共方法将句子拆分为单词并将其作为依赖项传递给IWordFrequencyAnalyzer的实现。 This way the implementation of splitting the words is testable as well. 这样,分割单词的实现也是可测试的。

Which approach will you suggest? 你会建议采用哪种方法?

Thanks, -Mike 谢谢,-Mike

Since getting more into DI and TDD I ended up using private methods less and less, but the reason was not because I needed them to be public for tests. 由于越来越多地使用DI和TDD,我最终越来越少地使用私有方法,但原因并不是因为我需要将它们公开用于测试。 It's more because, as a by-product of using DI, I'm learning more about applying the SOLID principles to my code and this (in turn) is leading me to write classes with less methods overall and almost none private. 更多的是因为,作为使用DI的副产品,我正在学习更多关于将SOLID原则应用于我的代码的知识,而这(反过来)正在引导我编写整体方法较少且几乎没有私有的类。

So, let's say you have a piece of your code you're using throughout various methods of your class. 所以,假设您在课程的各种方法中使用了一段代码。 You know about DRY and you refactor it out to a private method and all's good. 你知道DRY,你将它重构为私有方法,一切都很好。 Except that often you realize you can generalize what that private method does and inject that functionality as an external dependency of the class: this way, you can test it and mock it, sure, but above all you can reuse what that method does even in other classes or other projects if needs be. 除了通常你意识到你可以概括那个私有方法做什么并将该功能作为类的外部依赖注入:这样,你可以测试它并模拟它,当然,但最重要的是你可以重用那个方法甚至在其他课程或其他项目,如果需要。 Moving it out of the original class is an application of the single responsibility principle. 将其移出原始类是单一责任原则的应用。

As I said this change in the way I code is not directly depending on the fact I use TDD or DI, but it's a by-product of the principles TDD encourages me to enforce and of the convenience that DI containers provide in composing the many small classes that result from this approach. 正如我所说,我对代码的改变并不直接取决于我使用TDD或DI的事实,但它是TDD鼓励我强制执行的原则的副产品以及DI容器在组成许多小的时候提供的便利性这种方法产生的类。

EDIT: The second approach in the example you added to your question is a good example of what I was talking about. 编辑:您添加到您的问题的示例中的第二种方法是我所谈论的一个很好的例子。 The fact your new WordProcessor class is now testable is a plus, but the fact it's now composable and reusable is the real benefit. 您的新WordProcessor类现在可测试的事实是一个优点,但它现在可组合和可重用的事实是真正的好处。

Your methods should be private unless they need to be public for your application, not your test. 您的方法应该是private除非他们需要public您的应用程序,而不是您的测试。

Generally you shouldn't make things public just to support unit testing ( internal might help there). 一般来说,你不应该public只是为了支持单元测试( internal可能有帮助)。 And in that case, you should generally still be testing public interfaces, not private details of the class, which are much more likely to change and break your test. 在这种情况下,您通常应该测试public接口,而不是类的private细节,这更有可能改变并破坏您的测试。

If you have access to a copy, Roy Osherove's " The Art Of Unit Testing " addresses this issue pretty well 如果您可以访问副本,Roy Osherove的“ 单元测试艺术 ”可以很好地解决这个问题

You specific methods as private when they are only used internally by the object, normally called from other methods, some of which will be public or protected. 当特定方法仅由对象在内部使用时,它们通常从其他方法调用,其中一些方法将是公共的或受保护的。 You are more likely to create private methods as a result of following the DRY (Don't Repeat Yourself) principles. 由于遵循DRY(不要重复自己)原则,您更有可能创建私有方法。 In that scenario you'd extract some common code used by several methods into a private method called by those methods. 在这种情况下,您将几个方法使用的一些常用代码提取到这些方法调用的私有方法中。

Making every method of a class public and write a unit test for every method on such class will create a maintenance nightmare quickly, because you will have to change your tests for every little refactoring in your production code. 将类的每个方法公开并为此类的每个方法编写单元测试都会很快造成维护噩梦,因为您必须为生产代码中的每一个小重构更改测试。 You want to test the behavior of the class itself and for this you don't need every method to be public. 您希望测试类本身的行为,为此您不需要公开每个方法。

You should keep your methods private always when it is possible. 你应该尽可能保持你的方法私有。 Don't change them to public only for unit tests. 不要将它们更改为公开用于单元测试。 When you see that it is hard to test it then consider to change a little bit architecture of your class. 当你发现很难测试它时,请考虑改变你的类的一点点架构。 From my experience usually when I needed to test private method the class had wrong responsibilities so I changed it. 根据我的经验,通常当我需要测试私有方法时,类有错误的责任,所以我改变了它。

The Single Responsibility Policy will help you in this matter. 单一责任政策将帮助您解决此问题。 Consider this example: 考虑这个例子:

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()
    {

    }
}

In this case I see not one but two responsibilities: The Boss delegates work AND hire new staff. 在这种情况下,我看到的不仅仅是两个责任:老板代表工作和雇用新员工。 In this example, I would always extract the private method HireStaff to a new class (let's call it HR), and inject this into the Boss class. 在这个例子中,我总是将私有方法HireStaff提取到一个新类(让我们称之为HR),然后将它注入到Boss类中。 This is a very simplified example, but as you get more and more experienced in the TDD way of thinking, you will find that not many private methods have legitimacy. 这是一个非常简单的例子,但随着您在TDD思维方式方面的经验越来越丰富,您会发现没有多少私有方法具有合法性。

Regards, Morten 此致,莫滕

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM