在面向服务的体系结构中,映射器调用服务是一种好的做法吗?
In service oriented architecture, Is it a good practise that a mapper calls a service?
我想知道在自定义对象映射器中 call/inject 一个(微)服务是否是一个好习惯。
此映射器将实体转换为 DTO。在这个 DTO 中有一个字段包含一些值的总和(需要一些业务逻辑)。我定义了一个服务来集中逻辑,因为它在许多其他地方使用。
虽然严格来说从映射器调用服务并没有什么不对,但是它确实给映射器增加了依赖,通常是一个纯对象(Plain Old Java Object, POJO),它只是将一个一种类型的对象到另一种类型。另一种方法是将所需信息作为参数传递到映射器中。例如,假设您当前的设计类似于以下内容:
public class Foo { /* ... */}
public class FooDto { /* ... */}
public class FooService {
public FooResults getSomeResults() { /* ... */ }
}
public class FooMapper {
private final FooService service;
public FooMapper(FooService service) {
this.service = service;
}
public FooDto convert(Foo foo) {
FooResults results = service.getSomeResults();
// ... use results ...
}
}
您可以将 FooResults
作为参数传递给 convert
方法,而不是让 FooMapper
依赖于 FooService
:
public class FooMapper {
public FooDto convert(Foo foo, FooResults results) {
// ... use results ...
}
}
这种方法的优点是 FooMapper
不再依赖于 FooService
。相反,调用 convert
方法的客户端必须引用 FooService
以获得 FooResults
对象。
映射器将一种数据结构转换为另一种数据结构。因此它应该只依赖于这两个数据结构之一。
+------------------+ +----------+ +------------------+
| data structure 1 | <----- | mapper | -----> | data structure 2 |
+------------------+ +----------+ +------------------+
如果映射器使用服务,它也依赖于该服务。这意味着它知道数据是如何获得的。我猜你的映射器依赖于具体的服务。因此,映射器将受到其中一个数据结构的更改和该服务的更改的影响。
+------------------+ +----------+ +------------------+
| data structure 1 | <----- | mapper | -----> | data structure 2 |
+------------------+ +----------+ +------------------+
|
V
+----------+
| service |
+----------+
可能很难模拟服务进行测试。也许该服务依赖于某种存储库或者它本身 SQL。
通过引入一个从数据获取方式中抽象出来的接口,使映射器独立于数据结构的来源可能会更好。然后您的服务可以实现该接口或创建一个简单的适配器。
+------------------+ +----------+ +------------------+
| data structure 1 | <----- | mapper | -----> | data structure 2 |
+------------------+ +----------+ +------------------+
|
V
+------------------+ +--------------+
| Data1Provider | <------ | service |
+------------------+ +--------------+
使用这种方法,您可以通过引入对如何获取数据的稳定抽象来反转对服务的依赖。这就是所谓的依赖倒置。
它可能是一个看起来像这样的简单界面
public interface Data1Provider {
public FooResults getResults();
}
此接口可以很容易地模拟以进行测试。
另一个好方法是在调用映射器之前简单地调用服务。只需将服务返回的数据传递给映射器即可。我不会在这里详细介绍,因为 答案已经显示了。
我想知道在自定义对象映射器中 call/inject 一个(微)服务是否是一个好习惯。
此映射器将实体转换为 DTO。在这个 DTO 中有一个字段包含一些值的总和(需要一些业务逻辑)。我定义了一个服务来集中逻辑,因为它在许多其他地方使用。
虽然严格来说从映射器调用服务并没有什么不对,但是它确实给映射器增加了依赖,通常是一个纯对象(Plain Old Java Object, POJO),它只是将一个一种类型的对象到另一种类型。另一种方法是将所需信息作为参数传递到映射器中。例如,假设您当前的设计类似于以下内容:
public class Foo { /* ... */}
public class FooDto { /* ... */}
public class FooService {
public FooResults getSomeResults() { /* ... */ }
}
public class FooMapper {
private final FooService service;
public FooMapper(FooService service) {
this.service = service;
}
public FooDto convert(Foo foo) {
FooResults results = service.getSomeResults();
// ... use results ...
}
}
您可以将 FooResults
作为参数传递给 convert
方法,而不是让 FooMapper
依赖于 FooService
:
public class FooMapper {
public FooDto convert(Foo foo, FooResults results) {
// ... use results ...
}
}
这种方法的优点是 FooMapper
不再依赖于 FooService
。相反,调用 convert
方法的客户端必须引用 FooService
以获得 FooResults
对象。
映射器将一种数据结构转换为另一种数据结构。因此它应该只依赖于这两个数据结构之一。
+------------------+ +----------+ +------------------+
| data structure 1 | <----- | mapper | -----> | data structure 2 |
+------------------+ +----------+ +------------------+
如果映射器使用服务,它也依赖于该服务。这意味着它知道数据是如何获得的。我猜你的映射器依赖于具体的服务。因此,映射器将受到其中一个数据结构的更改和该服务的更改的影响。
+------------------+ +----------+ +------------------+
| data structure 1 | <----- | mapper | -----> | data structure 2 |
+------------------+ +----------+ +------------------+
|
V
+----------+
| service |
+----------+
可能很难模拟服务进行测试。也许该服务依赖于某种存储库或者它本身 SQL。
通过引入一个从数据获取方式中抽象出来的接口,使映射器独立于数据结构的来源可能会更好。然后您的服务可以实现该接口或创建一个简单的适配器。
+------------------+ +----------+ +------------------+
| data structure 1 | <----- | mapper | -----> | data structure 2 |
+------------------+ +----------+ +------------------+
|
V
+------------------+ +--------------+
| Data1Provider | <------ | service |
+------------------+ +--------------+
使用这种方法,您可以通过引入对如何获取数据的稳定抽象来反转对服务的依赖。这就是所谓的依赖倒置。
它可能是一个看起来像这样的简单界面
public interface Data1Provider {
public FooResults getResults();
}
此接口可以很容易地模拟以进行测试。
另一个好方法是在调用映射器之前简单地调用服务。只需将服务返回的数据传递给映射器即可。我不会在这里详细介绍,因为