将公共成员函数分解为许多私有成员函数

时间:2009-12-17 02:11:56

标签: private-members

当我写一个类的公共成员函数,它做了几件事,比如..

void Level::RunLogic(...);

在该功能中,我发现自己将其分成几个私有成员函数。将公共成员函数拆分为多个函数是没有意义的,因为没有其他函数你不会做一件事,我不希望用户担心什么以什么顺序等等。相反,RunLogic()函数会看起来像这样...

void Level::RunLogic(...) {
 DoFirstThing();
 DoSecondThing();
 DoThirdThing();
}

DoThing函数是私有成员函数。在Code Complete中,Steve McConnel建议减少类中的函数数量,但我不是只将所有代码放入一个函数中。我对其真正含义的假设是,一个类不应该有太多功能,但我只是想知道其他程序员对此有何看法。

此外,我一直在向公共成员函数公开越来越少的实现细节,并将大部分工作转移到小型私有成员函数。显然这会产生更多功能......但这就是问题所在。

7 个答案:

答案 0 :(得分:2)

您希望保持公共方法简单,并将其功能分成多个私有方法,这是正确的。

McConnell是对的,你应该减少你在课堂上保留的方法数量。

这两个目标并不是真的不一致。我认为McConnell不会主张让你的功能更长,以减少它们的数量。相反,您应该考虑将其中一些私有方法推送到一个或多个可供公共类使用的实用程序类中。

实现此目标的最佳方法取决于代码的详细信息。

答案 1 :(得分:1)

我建议将它们分成单独的方法,其中每个方法负责一个小任务,并对每个私有方法都有描述。打破方法和方法名称会使逻辑代码更具可读性!比较:

double average(double[] numbers) {
  double sum = 0;
  for (double n : numbers) {
    sum += n;
  }
  return sum / numbers.length;
}

为:

double sum(double[] numbers) {
  double sum = 0;
  for (double n : numbers) sum += n;
  return sum;
}

double average(double[] numbers) {
    return sum(numbers) / numbers.length;
}

代码完成解决了每个类暴露的接口,而不是实现。

将这些较小的方法作为包保护可能更有意义,因此您可以轻松地对它们进行单元测试,而只能测试复杂的RunLogic。

答案 2 :(得分:1)

我同意拆分功能。

我一直都被教导并且坚持认为函数被定义为执行单个封装任务的知识,如果它似乎做了不止一件事,那么重新考虑它可能是可行的。然后是一个将类似或相关函数封装在一起的类。

在我看来,将这些任务拆分并仍然使用单个公共成员允许班级按照预期的方式执行该重要任务,同时使维护更容易。我还经常发现在同一复杂方法中有多个相似的代码段,可以将它们重新计算到一个带参数的通用函数中 - 既提高了可读性又提高了可维护性;甚至减少了代码量。

答案 3 :(得分:0)

我使用的一条规则是三条规则。如果我在不同的地方做了三次相同的事情,那么值得拥有一个单独的(可能是私有的)成员函数来封装那个共享行为。

我在这种情况下通常使用的唯一其他规则是可读性。如果我正在查看在IDE中填充超过全屏的成员函数,我发现很难跟踪所有代码路径和可能的错误转弯。在这种情况下,将一个整体成员函数分解为两个或多个私有帮助函数是完全合理的。

关于关于类中函数数量的Code Complete注释,请记住函数数量中涉及的最大风险主要与外部可用接口的复杂性相关。您为其他人提供的入口点越多,出现问题的可能性就越大(例如,由于其中一个公共成员的错误,输入错误等)。添加私有成员函数不会增加公共API的复杂性。

答案 4 :(得分:0)

您无意中遵循了ff规则:

A class should have only one reason to change / Single responsibility principle

这是一件好事。 通过正确分离责任,您可以确保您的应用不会因change

而轻易中断

答案 5 :(得分:0)

我没有看到保持特别公共成员函数尽可能小的优点(以代码行来衡量)。通常,长函数往往不太可读,因此在大多数情况下,扩展大函数的实现会提高可读性,无论它们是否属于类的一部分。

关于保持尽可能小的类的好建议,这对于接口的公共部分和封装的数据量尤其重要。原因是具有大量数据成员和公共函数的类撤消了数据封装的优点。

答案 6 :(得分:0)

我使用的“经验法则”是,一次只有一个屏幕空间不会超过任何一个功能。虽然相当简单,但是当你可以一次在一个屏幕上“全部使用”时,它会有所帮助。它还将限制(根据定义)任何一种方法的复杂性。当您需要将您的工作交给同事进行进一步的维护,升级和错误修复(!)时,保持简单是好的。考虑到这一点,我同意保持公共方法简单几乎总是正确的选择。