Java私有方法签名的清晰性和更好的实践

Java私有方法签名的清晰性和更好的实践,java,code-readability,Java,Code Readability,我收到了以下代码片段的代码审阅注释- public void doWork(String a, Integer b) { .. .. SomeService service = getService(); for (Integer i : numbers) { doMoreWork(a, b, service); } } private void doMoreWork(String a, Integer b, SomeService servi

我收到了以下代码片段的代码审阅注释-

public void doWork(String a, Integer b) {
    ..
    ..
    SomeService service = getService();
    for (Integer i : numbers) {
      doMoreWork(a, b, service);
    }
}
private void doMoreWork(String a, Integer b, SomeService service) {
    ...
    ...
    ...
    service.doingMoreWork(a, b);
}
审查建议-

  • SomeService=getService()doMoreWork
    中调用code>,以确保签名清晰。所以签名变成了
    doMoreWork(a,b)
    ,这更容易理解 我的问题-

    由于
    doMoreWork()
    是在循环中发生的,因此我将向它传递一个服务对象。doMoreWork()只是代码中的一个私有逻辑单元,可以将“service”作为方法参数。这种方法永远不会公开。在这种情况下,指导原则是什么?这里的清晰度或可读性如何受到影响

    (注:

  • 调用
    getService()
    没有太多的性能开销,所以性能不是我的标准
  • 服务注入在这里不是一个选项。它需要按照示例中所示的方式获取
  • doMoreWork()不仅仅是调用service.doingMoreWork()。它还需要遵循一些预先的步骤

  • )由于建议是正确的,您只需要在
    doMoreWork
    方法中使用
    Service
    对象。因此,最好只在执行操作的
    doMoreWork
    方法中获取
    Service
    对象


    如果在
    循环
    之后添加了更多语句,那么
    服务
    对象将持续很长时间,直到其作用域存在为止(直到没有遇到关闭
    }
    ),它将不会被垃圾收集,因此您应该在
    域工作
    中调用
    getService()
    ,并在
    域工作(a,b)中传递2个参数
    。这样会更容易理解

    从代码清晰性的角度来看,
    doMoreWork
    是类中知道其服务的实例方法(即,它有一个
    getService()
    方法)。将
    服务
    放在签名中会让读者想知道这个方法指的是什么
    服务
    ,因此有些混乱。但是,在一个拥有多个服务并且必须对其中几个服务执行相同类型的工作的类中,这样的签名是完全有意义的。

    老实说,除了在
    doMoreWork
    方法中声明该变量之外,声明该变量对任何人都没有好处。原因如下:

    • doWork
    • getService()
      似乎总是返回同一个
      SomeService

    如果
    getService
    只是一个字段的getter,那么最好直接使用该字段,而不是使用该方法。但是,确实不需要将此值传递给方法。

    如果将
    doMoreWork()
    重构为以下内容:

    private void doMoreWork(String a, Integer b) {
        SomeService service = getService();
        service.doingMoreWork(a, b);
    }
    
    然后,您使
    doMoreWork()
    的功能依赖于
    getService()
    。如果您想要使用不同的方法来获取
    SomeService
    对象,您必须重构此代码。因此,出于这个原因,您可能希望继续使用原始实现

    如果您使用的是Spring之类的框架,则可以将
    SomeService
    注入到您的类中,如下所示:

    @Autowired
    private SomeService service;
    
    // use the injected service here
    private void doMoreWork(String a, Integer b) {
        service.doingMoreWork(a, b);
    }
    
    public void doWork(String a, Integer b) {
        ..
        ..
        for (Integer i : numbers) {
            getService().doingMoreWork(a, b);
        }
    }
    

    如果每次
    getService()
    都返回一个新实例,但其名称应该是
    createNewService()
    ,那么将服务作为参数传递是有意义的

    在当前场景中,
    getService()
    似乎总是返回相同的实例,因此将服务作为参数传递并没有任何区别,反而会让读者感到困惑

    进一步添加,
    getService()
    是在同一个类中定义的,
    doMoreWork()
    是一个私有方法,因此它总是引用同一个服务,而不是每次都添加一个额外的步骤来通过
    service

    另一件事,如果所有的
    doMoreWork()
    都是调用
    service.doingMoreWork(a,b)除此之外,最好删除此方法并在循环中直接调用它,如下所示:

    @Autowired
    private SomeService service;
    
    // use the injected service here
    private void doMoreWork(String a, Integer b) {
        service.doingMoreWork(a, b);
    }
    
    public void doWork(String a, Integer b) {
        ..
        ..
        for (Integer i : numbers) {
            getService().doingMoreWork(a, b);
        }
    }
    

    我同意代码审查,
    getService()
    应该在
    doMoreWork()

    此外,我建议将服务作为类的依赖项,也就是说,服务可以是类的一个字段。一些DI框架可以为您注入服务,例如Spring框架

    如果是这样,
    此.service
    可以在类的每个方法中引用。

    这并不重要,因为:
    doMoreWork()
    标记为
    private
    它是类的隐藏细节。 由于它不是
    public
    它不是
    public
    API或合同的一部分,因此它是一个可以更改的实现细节

    所以签名是什么并不重要,你问题中给出的理由只是个人偏好

    您永远不会在一个循环中创建一个新的JDBC连接,这将是非常低效的,即使有一个好的连接池,这样做也是错误的

    所有这些都表明我会这样做。
    private
    方法是不需要的,只会增加混乱和意见

    public void doWork(@Nonnull final String s, @Nonnull final Integer i) 
    {
        final SomeService service = getService();
        for (final Integer n : numbers) 
        {
          service.doingMoreWork(s, i);
        }
    }
    

    如果这是真正的代码,我会内联“doMoreWork”,我不明白为什么这里需要一个方法(它是1loc),我现在已经编辑了示例代码。doMoreWork()正在做更多的工作!我问这个问题是想知道这个建议背后的最佳实践,甚至是事实。这是我从书中找不到的东西,所以我把它贴在这里。我不确定它是否真的是“保持”的候选人。即使是回答也是合理的,而不仅仅是基于观点的。+1对我来说,这是最干净的解决方案——名义上的代码和最大的灵活性。doMoreWork方法不应该关心用于执行更多工作的服务。你可以用模块化的方式与DI.yeah交换服务,我们确实考虑了服务注入。但就我而言,我们不能这样做。一定是这样