Java中的私有辅助方法与公共静态实用方法

29

我有一个Java类,它变得越来越长。当我将它通过代码质量工具运行时,我会因为类中的行数而被标记。

这是一个较低层次的类,由上层使用Spring@Autowired。该类有许多私有实例方法,这些方法不是静态的。它们不使用任何实例字段,只在方法参数上工作。

我能否安全地将这些方法作为public static移动到某个单独的实用程序类中?有哪些缺点?


你可以把它们移动到一个包私有类中,这样就可以将无状态方法与其他代码分开而不将其暴露在包外。 - dimo414
我想知道,这个类里有多少实例变量? - fabfas
@fabfas:两个 - 一个是使用@Autowired注入的JdbcTemplate,另一个是使用@Value注入的String - Sabir Khan
“JdbcTemplate”实例变量表明该类将执行JDBC工作流。我认为,数据库接口层应负责获取数据,填充“数据记录”,并在应用程序层实现接口。 - fabfas
5个回答

67

这里存在着一个“错误”的心态。

你不应该仅因为工具对某些方面进行抱怨就重新设计你的类。

你想要提高你的源代码的质量;这些工具可以帮助你找出值得思考的“话题”。你应该把它们的反馈看作是提示而不是命令。

因此,你不用担心类中有多少“代码行数”。相反,你应该关注这个类所承担的职责。也就是说,代码行数本身并不是问题——但是违反了单一职责原则才是问题所在。

因此:你需要退后一步,查看你的类到底在做什么。当一个类明显在做多于一个的事情时,你就需要将这些方面分离成其他类!

也就是说:如果你确实发现所有的这些代码都“属于”该类的职责;那么你就应该让它留在那里。不要仅仅因为一些工具警告你代码行数而将一些内部实现细节放到无关联的辅助类中。

另一方面,将私有方法转换为静态/包保护的方式可以让你对这些方法进行单元测试。这可能是一个优势。但是正如之前所说的:只要涉及实现细节,它们应该保持私有,并且无需进行单元测试。

最后,了解并理解“干净代码”的含义,并尝试遵循其中阐述的思想。


4
nods,班级职责! - Jude Niroshan
我假设你在这里表示同意? - GhostCat
1
我宁愿说,“喵” :P - Jude Niroshan
11
还是有些困惑,但假设点赞是你的,那就随便怎样吧。喵。 - GhostCat

4

方法的划分应该按照目的/应用程序/逻辑(你可以自己命名),而不是按照技术属性。

长源代码可能可以分成几个小型类,每个类都有自己独立的目的/责任。


目前为止,这些私有方法仅由包含类使用,但行为类似于静态实用方法,因为这些方法中没有引用类实例或静态字段。我猜这些可以移动,但我应该尝试将它们分组到具有相似目的的类中。 - Sabir Khan

2
我经常使用包含静态方法的实用程序类,我觉得这非常方便。如果这些方法确实只适用于单个类,您可以将实用程序类作为静态私有类放在原始类中。但是我发现,在许多情况下,一般的静态实用程序方法可以被几个类使用,因此在这种情况下,我会创建一个单独的实用程序类,其中包含一组静态方法,可供几个类使用。
此外,我强烈同意GhostCat的回答,就一般思维方式而言。至于类的大小,可能是一个问题,但通常我不太担心这个。我真正关注的是方法的大小。我喜欢方法简短明了,从其名称和参数名称和顺序开始到逻辑。如果有大量内部逻辑,请将其提取为单独的方法。这样使代码更易读和可维护。

1
代码质量不能仅通过行数来衡量。如果你发现类文件日益增长,请确保你的类遵循单一职责原则。
当你的类不遵循这个原则时,将它们分成单独的类并将这些类打包。
否则,您可以将基类作为 抽象类,并将您的实用方法设置为 abstract。有一个子类扩展基类,并提供基类中抽象方法的实现。
这里有一个很好的 SO答案,关于何时可以将方法设置为静态 正如 @Zack Jannsen 所说,
"static"通常在您知道某些内容不会跨实例更改时非常有价值。如果是这种情况,我真的会考虑“单一职责原则”,这意味着一个类应该有一个职责,因此只有一个更改原因。我认为应该考虑将“ConvertMpgToKpl(double mpg)”函数和类似方法移动到它们自己的类中。汽车对象的目的是允许实例化汽车,而不是提供它们之间的比较。那些应该是类外部的。
尽管使用静态方法可以避免创建对象就能访问该方法,但在尝试使该方法成为静态方法时,请始终记住以下内容:
  • 该方法基于输入参数产生一致的结果
  • 您总是需要该方法在内存中(即:您经常需要该方法)- 与通过 static 访问具有多次访问的大型方法相比,通过对象创建访问它可能更好
  • 经常使用的实用程序方法可以被制作为 static

0
在我看来,使用一些“神奇”的私有方法有点危险,因为你无法真正地对其进行单元测试。当然,你可以对调用该私有方法的公共方法进行单元测试,但是请考虑一下你将拥有的渐近复杂度。通常,我更喜欢为这样的方法编写实用类,并编写一些充分的单元测试。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接