将大型方法分解为较小方法时适当的访问级别实践?

Elk*_*Elk 2 java class-design

所以我是一个相对较新的程序员,我还在学习,并遇到了一些问题(如果我的标签稍微偏离,那么道歉).在早期,我有机会阅读一篇文章,讨论将包含大量代码的方法分解为许多较小的,明确命名的方法的调用的优点.总的来说,我觉得这样做的代码看起来更整洁,并且确保单元测试更容易.但是,我对是否将所有这些新方法公开或私有都有些担忧.将它们设为私有似乎是正确的做法,因为其余的代码通常不需要访问这些方法.但是,单元测试私有方法可能会很混乱.这是最好的做法吗?

我现在在做什么:

 public class WashingMachine {
      public Load wash(Load load) {
           // Removes one sock from load
           for (ClothingItem item : load.getItems()) {
                if (item.getType().equalsIgnoreCase("sock") {
                     load.removeItem(item);
                     .. // logic for sending sock to proper dimension
                     break;
                }
           }
           // rest of logic for cleaning clothes
      }
 }
Run Code Online (Sandbox Code Playgroud)

变成:

 public class WashingMachine {
      // Wash a load of laundry
      public Load wash(Load load) {
           // Removes one sock from load
           removeSock(load.getItems());
           // rest of logic for cleaning clothes
           ..
      }

      // Oh no, I can't unit test this easily!
      private void removeSock(List<ClothingItem> items) {
           ...
      }
 }
Run Code Online (Sandbox Code Playgroud)

Rev*_*nzo 5

将您的公共方法视为您希望允许任何人使用的功能.

其中一些功能可能很复杂,而且你是对的,应该将功能分成不同的方法.问题是,"他们有什么样的访问权限?"

好吧,如果它们是公开的,现在外部类可以访问您真正不需要的内部功能.即使它不会破坏任何东西,当你开始处理大型项目(拥有更大的团队)时,通过公开它,其他程序员可能会使用该功能,这现在阻止你改变它.

例如,乘车比喻.说你的方法是accelerate().这可能会打电话releaseGas().但是,您不希望任何人在外部释放气体.它应该只在受控环境中调用.

然后是受保护的访问.受保护的访问权限适用于可以通过扩展类来覆盖的方法.这些应该是执行与内部功能相关的特定工作块的方法.再次以汽车为例,可能会有使用特殊类型气体的RaceCar clas,因此它希望提供自己的释放气体的方法.这将releaseGas是受到保护的原因.

至于测试,你应该主要测试你的公共合同.这就是其他课程所使用的,最后,这才是真正重要的.您的内部方法是您的功能的内部方法,将通过测试您的公共合同进行测试.这也意味着您的类应首先根据其外部用途进行设计,并围绕该类进行测试.(即使使用测试驱动的开发,随着您获得经验,这也会变得更容易.)

当然,有时这些内部方法很复杂,他们需要自己进行单元测试.但是,您不需要对它们进行保护.在这种情况下,您可以将它们设为默认访问权限.(既不公开也不受保护).只要您的单元测试在同一个包中,您就可以调用它们.

更重要的是,如果你知道你不希望任何人把它扩大,但你需要用它来进行测试,使其protected final或只final.这仍然允许调用它,但至少可以防止它被覆盖.

编辑:

Ryan的评论如下.如果你的类变得足够复杂以至于需要测试它的内部方法,那么它们应该被提取到它们自己的类中,然后可以对它们进行独立的单元测试.

总的来说,您的测试应该是测试您单独单位的公共合同.

  • +1因为我同意除了一点之外的每一点:不要为测试目的制作"内部"方法包.如果代码足够复杂,需要自己的测试集,那么显而易见的暗示是它应该是它自己的单元.将其解压缩到具有自己职责的单独类/对象中.我曾经完全按照你的建议去做,我发现它无处可寻,但却陷入困境.始终让测试指导您. (3认同)