What's wrong with returning this?
在我工作的公司,有一份文档描述了我们应该在Java中遵循的良好实践。其中之一是避免返回this的方法,例如:
我会有这样一堂课,所以我能写:
1
| properties.add("name","john").add("role","swd"). ... |
我已经多次见过这样的习语,比如在StringBuilder中,并没有发现任何问题。
他们的论证是:
... can be the source of synchronization problems or failed expectations about the states of target objects.
我想不出这可能是真的情况,你们有谁能举个例子吗?
编辑该文档没有指定任何有关可变性的内容,因此我没有看到链接调用和执行以下操作之间的差异:
1 2
| properties.add("name","john");
properties.add("role","swd"); |
我会尝试与发起人联系,但我想用我的枪加载,这就是为什么我发布了这个问题。
解决:我得与其中一位作者交谈,他的初衷显然是为了避免释放尚未准备好的对象,比如在Builder模式中,并解释说如果在调用之间发生上下文切换,则对象可能在无效的状态。我认为这与返回this无关,因为你可能会犯同样的错误购买逐个调用方法,并且更多地与正确地同步构建过程有关。他承认该文件可能更加明确,并将很快修改。胜利是我的/我们的!
-
"同步问题"?我无法想象这会是怎样来的(双关语不是意图,而是容忍)。像其他所有模式一样,它有很好的用途和误用,但我不明白你给出的推理。也许可以要求该文件的作者进行澄清。
-
在stackoverflow.com/questions/1345001/&hellip上还有另一篇关于此的帖子;
-
我也不理解这个论证。
-
如果我希望我的(假设的)下属停止做我不喜欢的事情而不想承认我的理由是95%美学,那么这种论证就是我所使用的那种夸张,空洞的废话。 (另请参阅:支持或反对OTBC / K& R风格的每一个论点。)
-
如果你在两个线程中执行了buff.append("Hello,").append("World
"),其中buff是StringBuffer,你最终会得到"Hello,Hello,World nWorld n"。然而,在StringBuffer中进行所有同步并没有多大意义,它告诉你"良好实践"。 (OTOH,返回this表示该语言存在问题。)
-
对于它的价值,我的观点是,这是一种非常适合可变对象的模式,你也可以在常用时广泛变异。 (例如StringBuilder。)经历一系列不可变内部状态的构建器很棒,但并不是每个类都需要以这种方式使线程安全,并且每个可变类都是"同步问题"的来源,无论它的API是什么很流利。
-
@ TomHawtin-tackline这是我主要反驳"这个线程安全吗?"形式的基础。同步问题是由单个共享状态实例的所有使用的交互引起的,查看单个方法/类(或在这种情况下的单个语句)是近视的。
-
@millimoose当然,它看起来像是一种去除空间 - 防止 - 种族 - 条件的心态。 :)
-
@millimoose美学对于可维护的代码很重要,所以我认为美学是做/不做某事的一个很好的理由。而且,为什么不让方法列出对象,而不是链接Add()方法?
-
@BobHorn美学的问题在于,在某种程度上,你在浪费的争论中浪费精力。根据我的经验,使"真实世界"代码库无法维护的是复杂的架构,太多的实习生,在关键时刻必须修复的错误的解决方法,必须与客户在十年前购买的那个模糊的CMS一起工作随谷歌提供的文档 - 法语翻译...纯粹/大多数美学问题最终都是微不足道的,并且根本不会影响实践中的可维护性。它错过了树林。
-
@BobHorn至于你的后一个建议:可能有几种类型的"可添加"对象,它们的实现是你无法控制的,并且不共享你可以编码的公共抽象接口。
-
@BobHorn以不同的方式表达我对可维护性的看法:如果你真的关心它,你应该进行代码审查和所有其他耗时的事情。作为一个关于代码风格的欺凌者是"可维护性剧院",对于缺陷率和修复它们所需的时间大致相同,因为TSA让人们移除鞋子以防止恐怖袭击。
-
我觉得你有一些好处。我也认为你有一个与我有关的稻草人论点。我不是在争论关于括号去哪里的辩论。我只是认为干净的代码比丑陋的代码更容易维护。无论如何,我们关注的是另一个主题。
我的猜测是他们反对可变状态(通常是正确的)。如果您没有设计返回this的fluent接口,而是返回具有已更改状态的对象的新不可变实例,则可以避免同步问题或没有"failed expectations about the states of target objects"。这可能解释了他们的要求。
-
可以说,这一点应该明确提到。
-
你能解释一下,如何从实例方法中返回这个会影响不变性吗? 返回对不可变对象的引用有什么坏处?
这种做法唯一严肃的基础是避免可变对象;批评它"混乱"并导致"失败的期望"是相当薄弱的。一个人不应该在没有熟悉其语义的情况下使用对象,并且为了满足那些选择不再阅读Javadoc的人而强制执行A??PI的约束并不是一个好习惯—特别是因为,正如您所注意到的,返回this以实现流畅的API设计是Java中的标准方法之一,而且确实非常受欢迎。
我认为有时这种方法非常有用,例如在'builder'模式中。
我可以说,在我的组织中,这种事情是由声纳规则控制的,我们没有这样的规则。
另一个猜测是,项目可能是在现有代码库的基础上构建的,这是一种遗留限制。
所以我在这里建议的唯一一件事就是和写这篇文章的人交谈:)
希望这可以帮助
我认为在某些情况下使用该模式是完全可以接受的。
例如,作为Swing开发人员,我经常使用GridBagLayout来发挥它的优势和灵活性,但是任何曾经使用它的人(在犯罪GridBagConstraints中都是它的伙伴)都知道它可能非常冗长且不易阅读。
我在网上看到的一个常见的解决方法(我使用的是)是GridBagConstraints(GBConstraints)的子类,它为每个不同的属性都有一个setter,每个setter返回它。这允许开发人员根据需要链接不同的属性。
生成的代码大小约为1/4,并且对于可能不熟悉使用GridBagConstaints的临时开发人员来说,可读/可维护性更强。