java - java - 委托给私有静态方法比springboot webflux中的私有方法有什么好处(函数式程序风格)
问题描述
我有一个关于在 java springboot webflux 项目的上下文中使用私有静态方法的问题。
让我先放一些代码:
一个spring项目的简单代码:一个Main类,config包下的Configuration类,包repository下的Repository类,service包下的Service接口。
@SpringBootApplication
public class SomeApplication {
public static void main(String[] args) {
SpringApplication.run(SomeApplication.class, args);
}
}
@Configuration
public class SomeConfiguration {
@Value("${someConfiguration}")
private String someConfiguration;
public String getSomeConfiguration() {
return someConfiguration;
}
}
@Repository
public interface SomeRepository extends Reactive[...]Repository<String, String> { }
public interface SomeService {
Mono<String> someCompute(String string);
}
(问题不在上面)
现在,作为服务层的实现:首先,面向公众的方法将所有计算委托给后续私有静态方法的版本,将字段作为参数传递。(选项1)
@Service
public class SomeServiceImpl implements SomeService {
private final SomeConfiguration someConfiguration;
private final SomeRepository someRepository;
private final WebClient webClient;
@Autowired
public SomeServiceImpl(SomeConfiguration someConfiguration, SomeRepository someRepository, WebClient webClient) {
this.someConfiguration = someConfiguration;
this.someRepository = someRepository;
this.webClient = webClient;
}
@Override
public Mono<String> someCompute(String string) {
Mono<String> s1Mono = sendHttpRequestToSomewhere(webClient);
Mono<String> s2Mono = s1Mono.map(x -> computeSomethingWithConfiguration(x, someConfiguration));
Mono<Object> s3Mono = s2Mono.map(x -> saveToSomewhere(x, someRepository));
return s3Mono.map(x -> computeSomethingElse(x));
}
private static Mono<String> sendHttpRequestToSomewhere(WebClient webClient) {
return webClient.get().retrieve().bodyToMono(String.class);
}
private static String computeSomethingWithConfiguration(String x, SomeConfiguration someConfiguration) {
return x + someConfiguration.getSomeConfiguration();
}
private static Mono<String> saveToSomewhere(String x, SomeRepository someRepository) {
return someRepository.save(x);
}
private static String computeSomethingElse(Object x) {
return x.toString();
}
}
与在私有但非静态方法中直接使用字段相反。(选项 2)
@Service
public class SomeServiceImpl implements SomeService {
private final SomeConfiguration someConfiguration;
private final SomeRepository someRepository;
private final WebClient webClient;
@Autowired
public SomeServiceImpl(SomeConfiguration someConfiguration, SomeRepository someRepository, WebClient webClient) {
this.someConfiguration = someConfiguration;
this.someRepository = someRepository;
this.webClient = webClient;
}
@Override
public Mono<String> someCompute(String string) {
Mono<String> s1Mono = sendHttpRequestToSomewhere();
Mono<String> s2Mono = s1Mono.map(x -> computeSomethingWithConfiguration(x));
Mono<Object> s3Mono = s2Mono.map(x -> saveToSomewhere(x));
return s3Mono.map(x -> computeSomethingElse(x));
}
private Mono<String> sendHttpRequestToSomewhere() {
return webClient.get().retrieve().bodyToMono(String.class);
}
private String computeSomethingWithConfiguration(String x) {
return x + someConfiguration.getSomeConfiguration();
}
private Mono<String> saveToSomewhere(String x) {
return someRepository.save(x);
}
private String computeSomethingElse(Object x) {
return x.toString();
}
}
(把它们放在一起)
问题:
选项1可以带来什么好处?
这是一个技术问题,不是基于意见的。我相信不仅仅是代码风格偏好。我看到越来越多的项目在 java webflux 功能程序的上下文中采用选项 1。
在编译时性能方面,选项 1 相对于选项 2 有什么好处或缺少什么?
就运行时性能而言,选项 1 与选项 2 相比有哪些优势或不足?
线程安全选项 1 相对于选项 2 有哪些好处或缺少哪些好处?
就可测试性而言,选项 1 相对于选项 2 有什么好处或缺少什么?
就模拟选项 1 而言,与选项 2 相比有什么好处或缺少什么?
就可维护性而言,选项 1 相对于选项 2 有哪些好处或缺少哪些好处?
就可读性而言,选项 1 相对于选项 2 有什么好处或缺少什么?
请问选项 1 比选项 2 有哪些其他好处或缺少什么?
谢谢
解决方案
我认为这个问题通常与 WebFlux 和 Spring 无关,而是与任何以函数式样式编写的代码有关(Java 8 流也会遇到同样的问题),甚至与以“传统”编写的代码有关命令式风格:什么叫私有静态或私有方法?
一般来说,我只能看到私有静态方法和私有方法之间的一个区别:
私有非静态方法可以访问类的状态/依赖项(非静态数据字段),而私有静态方法不能
这意味着您可能希望在以下情况下使用私有static methods
:
- 你只在课堂上使用它们
- 您想强调该方法不依赖(读取不访问)其定义的对象的内部状态。
相反,如果您已经维护了状态/依赖关系,就像WebClient
在示例中一样,那么使用static
会使您将此参数传递给方法。在我看来,这是不必要的:如果您没有 1 个,而是说 3 个要传递的参数,并且您从源类中的许多地方调用此方法,该怎么办。
除此之外,我没有看到太大的区别:
模拟(测试)是一样的,因为无论如何您都不测试私有方法,并且您可以通过使用构造函数注入或一些高级模拟技术以相同的方式模拟两种情况下的依赖关系。
性能损失 - 大致相同,我无法考虑使用一种方法而不是另一种方法会导致性能问题的情况。
可维护性——同样,取决于你的用例,如果方法正在访问内部状态,你最好使用非静态变体来减少混乱,如果你想强调你使用不依赖于状态的“util”方法——使用
private static
方法。多线程 - 如果需要,您应该在两种情况下同步状态,该方法本身具有修饰符这一事实
static
根本不处理多线程。
我还发现这个线程对这个问题很有用,它同样适用于一般编程风格(代码组织),不仅适用于 webflux。
推荐阅读
- .net - 如何在 Linux 容器中重新启动 Azure 函数?
- reactjs - redux 只返回初始状态?
- .net - 在 .Net 5.0 隔离过程函数中使用 SignalR
- javascript - 编辑 Formik 表单时如何禁用输入文件
- php - 如何在资源类中加载嵌套关系的数据
- visual-studio - 如何修复 Visual Studio 中的附加按钮和运行按钮?
- systemd - Puma systemd 重启超时并且似乎失败,即使它实际上已经成功
- json - 如何将对象参数作为哈希表传递给 json arm 模板?
- youtube-iframe-api - Youtube iframe API - origin 参数问题 - origin=https%3A%2F%2Fwww.test.com
- tableau-desktop - 如何开始使用行级安全性?