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. 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 belie开发者_开发知识库ve an example might help here:
Assume I have an interface with 3 methods like the following:
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. This way the implementation of splitting the words is testable as well.
Which approach will you suggest?
Thanks, -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. 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.
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. 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.
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.
Your methods should be private
unless they need to be public
for your application, not your test.
Generally you shouldn't make things public
just to support unit testing (internal
might help there). 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.
If you have access to a copy, Roy Osherove's "The Art Of Unit Testing" addresses this issue pretty well
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. 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. 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.
Regards, Morten
精彩评论