如果私有方法调用公共方法,是否有代码味道?


25

在同一对象实例的私有方法中调用公共方法是否有代码味道?


AAMOI你有一个具体的例子吗?
ocodo 2011年

不,目前不行。只是想起了我与同事讨论过的一个案例。也想在这里获得一些意见。
Eimantas 2011年

5
通常,我可以根据上下文找到首字母缩写词,但我绝对必须查AAMOI
卡森·迈尔斯

@Carson-您找到了什么吗?
Eimantas 2011年

4
作为关注事项
卡森·迈尔斯,

Answers:


33

没有难闻的气味。可能需要这样做,为什么您怀疑它是错误的?原子级别的方法是执行任务的独立实体。只要它执行任务,任何有权访问它的人都可以调用它来完成任务。


我同意。某些方法提供的功能对于内部呼叫者和外部呼叫者均有用。如果public方法非常特定于内部实现,则可能会出现危险,但是即使那样,并不是每个类都打算隐藏其内部。例如,我经常在容器抽象类型层下面有一个数据结构“工具”层-这样,我就可以将某些数据结构代码重用于其他容器下面的其他数据结构。
Steve314 2011年

20

代码有异味吗?是的,这不是一个很糟糕的情况,但可以很好地表明班级可能承担了太多责任。

以此表示该类可能需要分解为不同的对象,私有方法实际上不需要调用同一对象的公共方法,当然在干净的OO设计中。

当然,一旦您检查了该类并且明确了方法调用的原因,这可能是一种非常合理的用法,通常,您希望该类的实用方法是私有的,但是如果一个有用的方法足以是公开的并被其他方法利用,我通常希望这些方法也是公开的。

与所有代码气味一样,这是进行进一步代码检查,合理化甚至重构的动机,而不是引起警报的原因。


5
+1(表示“不是警报原因”)。太多次我们看到“气味”,立即进入重构模式而没有思考。
Michael K

SRP +1。我只是遇到一个装饰器无法正常工作的情况,因为被装饰的类在绕过装饰器时调用了自己的公共函数。解决方案:将类分为两部分并注入修饰的依赖项。
乔恩·赫尔卡

18

如果尚未阅读此类源代码的某人尝试将其子类化并覆盖public方法,则可能会导致令人不快的意外。这是否真正令人担忧,显然取决于您的情况。也许您应该考虑使公共方法甚至是类最终化。


为什么?如果重写的公共方法导致令人不愉快的意外,那么谁调用该方法真的很重要吗?
user281377 2011年

4
是的,它确实。如果覆盖一个公共方法破坏了另一个公共方法,我也可以覆盖另一个公共方法。如果它破坏了私有方法,我可以....?
金,

5
覆盖公共方法而导致的令人不愉快的意外是代码本身的味道。实际上是代码恶臭。
拉里·科尔曼

Kim:如果该方法是公共方法,则必须假定其他类也同样调用该方法...
user281377 2011年

@Larry:是的!调用公共方法的私有方法(通常包含特定于实现的假设)使重写公共方法更可能破坏事物。
金,

5

我不认为我们可以概括。

这完全取决于上下文。

我可能会说,一个类中有一个公共实用程序方法供其他类使用,而同一类中还有一些私有方法。


5

否。在那种情况下还应该做什么?公开私有方法还是公开私有方法?将代码从公共方法复制粘贴到私有方法?


或者将公共方法委托给一个(新的)私有方法,该方法由另一个私有方法调用。但是,为什么要打扰呢?
劳伦斯·多尔

4

,这里没有难闻的气味。

如果我们使用List实现队列的接口,只是调用适当的List函数以轻松实现队列的实现是否难闻?

如果您有东西,并且想要将其转换为其他东西(例如包装纸),那么它的味道就不错,它在设计级别上的代码与设计模式的可重用性作用在函数级别上(函数是对象吗?)


2

我知道这是一篇旧文章,但这是我在工作中一直在争论的问题。我“认为”这是一种代码味道,不明白为什么您会想要这样做。如果私有方法必须调用公共方法,则应采用公共方法的内容并将其放在私有方法中,然后这两种方法都可以调用该私有方法。为什么?

  1. 一旦在内部执行代码,公共方法可能包含不必要的测试。例如,它可能会收到一个UserObj,并且想要测试用户权限。

  2. 进行公共调用后,如果您正在使用线程,则可能需要锁定对象,因此在内部,您不希望回调到公共方法。

  3. 我认为,更有可能引入循环错误和无限循环以及内存异常。

  4. 简单明了,糟糕的设计和“懒惰”。使用公共方法可以访问外界。当你已经在里面的时候,没有理由走回外面。


1
如果现有的公共方法被许多其他类调用怎么办?将其设为私有将打破这一点。请记住,其他类出于其他原因而不仅仅是其他类调用了公共方法。有点为什么存在公共方法。
Michael Durrant

我说过“应该采用public方法的内容,并将其放在private方法中...” public方法将保留,但是会调用新的private方法。与其他需要重用相同功能的私有方法一样。
Mark Graham

因此,您添加其他方法的唯一原因是-嗯,因为您声明这是“代码异味”。没有意义的方法是更糟糕的代码味道。
gnasher729

抱歉,但是,我不仅在上面列出了几个原因。我编写的许多代码是针对业务系统的,许多类基于角色而仅限于用户。许多公共方法测试用户权限和参数。我到底为什么要回调相同的公共方法来重用其功能并重新测试用户权限?
Mark Graham

我一生中从不需要从私有方法调用公共方法。这似乎对我来说很不对劲。我真的很惊讶,大多数人认为还可以。
陷阱

2

想象相反。您处于私有方法中,而您需要公共方法中的功能如果无法从私有方法中调用该公共方法,该怎么办。你会怎么做?

  • 创建重复的私有方法?没有
  • 为场合创建特殊的公共方法?没有
  • 调用可以调用公共方法的特殊私有方法?没有
  • 某种超级可以做到这一点?没有

显然,答案是,当您想要公共方法中的功能时,您应该能够从此类或其他类的方法中调用该方法。


1

在我的代码中,我经常创建延迟加载获取器,也就是说,对象在第一次被请求时就被初始化,然后重用相同的实例化对象。但是,使用延迟加载实例化的对象意味着不一定必须在任何给定点实例化该对象。与其将我的头放在调用序列周围,以免我知道该对象已被实例化或在另一个方法内重复执行延迟加载的相同代码,我只是在需要该对象时调用延迟加载器。

正如可以聪明地使用公共方法一样,您也可能会错误地使用它们。例如,一个公共方法将在调用另一个私有方法之前处理其参数。仅仅因为您具有相同的参数而随便调用该公共方法将是一个错误。该错误很细微,但它是设计错误,而不是其他任何错误,并且要求您学会使用内部方法的参数而不是公共方法的参数进行管理。

因此,要回答您的问题,如果使用正确,它肯定不是不好的代码。


1

您需要问自己的问题是,为什么您的班级与班级的客户需求相同?通常,一个班级与其客户有非常不同的需求。是的,这表明您有

(a)公开暴露应为私人的东西;要么

(b)班级的行为不够狭窄(请考虑单一责任原则)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.