为什么我的 ViewModel 不应该依赖于服务的具体实现?

Why shouldn't my ViewModel depends on concrete implementation of services?

我的 ViewModel 通常通过接口 依赖某些服务(DI 容器将注入实际实现)。这样我就可以为单元测试创​​建这些服务的模拟行为。

public class MyViewModel 
{
        public MyViewModel(IMyService myService)
        {
        }
}

但是我们有一些模拟框架存在,例如 Moq,您可以在其中为服务的具体实现设置模拟行为,即使没有接口。 这是否意味着,ViewModel 可以依赖于具体服务 类 而不是接口? 除了 UnitTests 之外,接口还有其他用途吗?

总的想法是拥有一个可以轻松发展的项目。接口让你少了一点耦合,因为你可以有不同的实现,包括测试实现(模拟)。这就是理论。

根据我的经验:如果您只有一个服务实现并且可以轻松模拟它,那么只有实现没有接口就足够了。如果将来您需要另一个实现,您可以重构。但它仍然需要两件事。

  • 定义的接口:您仍然需要明确定义您的服务所提供的合同。所以你需要一些方法 public,另一些方法是私有的。并且您的视图不能使用私有方法,否则将很难进行任何更改
  • 开发者必须了解界面。如果您明确定义了接口,那么它就是一个很好的文档。如果您没有,您的团队可以更轻松地以开始使用本应是内部服务实现的功能的方式对其进行更改

But we have some mocking framework exists like Moq, where you can setup mock behavior for your concrete implementations of services even without interfaces

不完全是。使用最小起订量,您只能模拟可以是 overriden/implemented 的东西。在大多数情况下,这将是一个接口,但有时是一个 class 和 virtual/abstract 方法。

现在,如果您的服务将方法公开为虚拟方法(问题是,为什么 他们会那样做?)那么当然,您可以使用 Moq 并能够模拟它们。否则不行。

传递接口的意义在于依赖抽象而不是具体实现。这是 SOLID principles - Dependency Inversion PrincipleD