给定如下界面:
public interface IFoo
{
string Bar();
}
还有一个实现它的类:
public class Foo : IFoo
{
public string Bar()
{
returns "Bar";
}
public string SomeOtherMethod()
{
returns "Something else";
}
}
这段代码有问题吗?我们是否应该将所有方法都添加到接口(interface)中?
一个例子:想象一个私有(private)方法变得复杂到需要单元测试。您能否将其公开(以便可以从测试项目中调用它)但不将其添加到接口(interface)中(因为没有客户端需要调用它)?
最佳答案
如果一个类做的事情足够简单,我们可以同时测试它的公共(public)方法和私有(private)方法,那么我们可以只测试公共(public)方法。
如果私有(private)方法变得如此复杂以至于在公共(public)方法和私有(private)方法之间我们需要太多的测试组合,那么是时候将私有(private)方法分离到它自己的类中了。公开私有(private)方法会破坏类的封装。即使我们不将方法添加到 interface
,将类方法设为 public 仍然会将方法添加到类本身的公共(public)接口(interface)。
所以如果我们有这个:
public class ClassWithComplexPrivateMethod
{
public void DoSomething(int value)
{
PrivateMethodThatNeedsItsOwnTests(value);
}
private string PrivateMethodThatNeedsItsOwnTests(int value)
{
// This method has gotten really complicated!
return value.ToString();
}
}
我们可能会重构为这样的东西:
public interface IRepresentsWhatThePrivateMethodDid
{
string MethodThatNeedsItsOwnTests(int value);
}
public class RefactoredClass
{
private readonly IRepresentsWhatThePrivateMethodDid _dependency;
public RefactoredClass(IRepresentsWhatThePrivateMethodDid dependency)
{
_dependency = dependency;
}
public string DoSomething(int value)
{
return _dependency.MethodThatNeedsItsOwnTests(value);
}
}
现在一个新类实现了 IRepresentsWhatThePrivateMethodDid
。
现在,当我们测试重构的类时,我们模拟 IRepresentsWhatThePrivateMethodDid
,并且我们为任何实现 IRepresentsWhatThePrivateMethodDid
的类编写单独的单元测试。
将私有(private)方法公开为公共(public)方法会破坏封装,但将其作为自己的独立类公开则不会,这似乎是自相矛盾的。有两个区别:
- 重构后的类不依赖于包含以前私有(private)方法的新类。这取决于新界面。
- 重构后的类和接口(interface)之间的交互仍然隐藏在它的方法中。调用其公共(public)方法的其他类并不“知道”它如何使用其依赖项。 (事实上,其他类可能会依赖于抽象而不是直接依赖于重构的类。)
当我们本可以通过公共(public)方法测试该类(包括其私有(private)方法)时,也很容易被它冲昏头脑并过早引入单独的依赖项。我已经这样做过很多次了,它会导致很多很多不必要的接口(interface)和额外的类。没有完美,只有我们尽最大努力来平衡它。
还有一个想法:我们倾向于使用接口(interface)来表示依赖关系,但我们不必这样做。如果我们提取的只是一个私有(private)方法,那么也许我们可以用委托(delegate)或 Func
来表示它,如下所示:
public class RefactoredClass
{
private readonly Func<int, string> _dependency;
public RefactoredClass(Func<int, string> dependency)
{
_dependency = dependency;
}
public string DoSomething(int value)
{
return _dependency(value);
}
}
或者我们可以使用委托(delegate),我比 Func
更喜欢它,因为它指示函数的作用。
关于c# - 是否应该在接口(interface)中声明所有公共(public)方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55942632/