这是否值得为只有一个实现的服务定义一个接口

huangapple go评论73阅读模式
英文:

Is it worth defining an interface for a service with a single implementation

问题

在我的Spring应用程序中,通常为每个服务都有一个接口,即使只有一个实现,例如。

public interface FooService {
  Foo getFoo(long id)

  Iterable<Foo> findAllFoos()

  void deleteFoo(long id)
}

@Service
@Transactional
public class FooServiceImpl implements FooService {
    // method implementations omitted
}

我认为这种做法起源于过去的时代,当时的模拟库只能为接口生成模拟。但是现代的模拟库,如Mockito,可以像接口一样轻松地模拟类,因此我不确定为具有单一实现的(Spring/Spring Boot)服务定义接口是否有任何实际好处?

英文:

In my Spring application, there's typically an interface for each service, even if there's only a single implementation, e.g.

public interface FooService {
  Foo getFoo(long id)

  Iterable&lt;Foo&gt; findAllFoos()

  void deleteFoo(long id)
}

@Service
@Transactional
public class FooServiceImpl implements FooService {
    // method implementations omitted
}

I think this practice originated in the olden days when mocking libraries could only generate a mock for an interface. But modern mocking libraries like Mockito can mock a class just as easily as an interface, so I'm not sure if there's any practical benefit to defining an interface for (Spring/Spring Boot) services with a single implementation?

答案1

得分: 1

我更喜欢在@Service中使用interface,因为我们可以将接口设置为公开,而实现则可以设置为包访问级别。这会使作用域更加紧凑。

public interface FooService {

}

@Service
class FooServiceImpl implements FooService {

}

但这仅适用于仅用作门面的服务。
Controller -> 门面服务 -> Spring上下文中的其他类

对于Spring上下文中的“其他类”,可以被“门面服务”使用,我通常不使用接口。

@Service
class FooServiceImpl {

    private final FooServiceHelper helper;

    @Autowired
    public FooServiceImpl(FooServiceHelper helper) {
        this.helper = helper;
    }

}

我们甚至可以更进一步,可以说:即使有多个实现,也许更好的选择是使用抽象类或默认实现,而不是接口。

英文:

I prefer to use an interface for @Service because we can make interface public and implementation package access. So it makes the scope tighter.

public interface FooService {

}

@Service
class FooServiceImpl implements FooService {

}

But it is for service that is used like a facade only.
Controller -&gt; Facade Service -&gt; other classes from Spring context

For "other classes" from Spring context that can be used by Facade Service I never use interfaces.

@Service
class FooServiceImpl {

    private final FooServiceHelper helper;

    @Autowired
    public FooServiceImpl(FooServiceHelper helper) {
        this.helper = helper;
    }

}

We can go even further and say: even we have multiple implementations, maybe better to have an abstract class or default implementation rather than an interface.

答案2

得分: -1

在Java应用程序中,创建仅具有单个实现的接口的一个很好的理由是为了实现依赖反转(D,即SOLID中的D)

例如,在具有洋葱/六边形样式架构的应用程序中,基础设施层包围了应用程序层,应用程序层包围了模型层,您可以在应用程序层定义一个PersonRepository接口,然后在基础设施层中实现PersonRepositoryJdbcPersonRepository类。应用程序层中定义的类的方法调用PersonRepository上的方法来保存和搜索Person领域对象。基础设施层中的JdbcPersonRepository允许应用程序在MySQL数据库中使用JDBC保存和搜索Person对象状态。

在这种设计中,尽管代码执行从应用程序层代码流向基础设施层代码,但代码依赖关系是从基础设施层指向应用程序层的。

搜索洋葱架构、六边形架构、端口和适配器架构以及特别是依赖反转的解释。

英文:

In Java applications, one good reason to create an interface that only has a single implementation is to implement Dependency inversion (D as in SOLID).

For example, in an application that has an onion / hexagonal style architecture with an infrastructure layer surrounding an application layer surrounding a model layer, you might define a PersonRepository interface in the application layer and a JdbcPersonRepository class that implements PersonRepository in the infrastructure layer. Methods of classes defined in the application layer call methods on PersonRepository to save and search for Person domain objects. JdbcPersonRepository in the infrastructure layer allows the application to save and search for Person object state in a MySQL database using JDBC.

In this design, although code execution flows down from application layer code to infrastructure layer code, code dependencies are directed up from the infrastructure layer to the application layer.

Search for explanations of onion architecture, hexagonal architecture, ports and adapters architecture and, in particular, dependency inversion.

huangapple
  • 本文由 发表于 2023年3月3日 19:23:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/75626455.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定