我认为下面的代码很难理解。我也觉得它滥用了Java的三元运算符。
String name = ((this.getAllNamesAsDelimitedString().contains(incomingName) ?
incomingName:
(CollectionsUtils.isEmptyCollection(this.getEntityOperationMap()) ?
null :
this.getEntityOperationMap.get(incomingName))));
在
getAllNamesAsDelimitedString
上方将返回一个以逗号分隔的,
(<43 /> 79q)。如果看起来更干净,更容易理解。在SVN中解决合并问题也很容易。NB:在我刚刚接手的代码中,甚至还有更多的嵌套三元条件。 >是否有一般性建议建议应允许三元运算符的级别数?换句话说,是否有任何建议建议何时中断三元运算符以提高代码可读性?
#1 楼
是的,那是滥用。一般来说,我在您的代码中看到两点,您可以根据基础数据结构来推断含义,如果要更改的话,这些含义也需要更改。
另外,这些类型的调用(
getAllNamesAsDelimitedString().contains(incomingName)
和(CollectionsUtils.isEmptyCollection(this.getEntityOperationMap())
通常最终会被使用很多次,从而导致DRY。另外,
(this.getAllNamesAsDelimitedString().contains(incomingName)
违反了demeter法则(它有两个点),并在没有充分理由的情况下将我假设的实体作为字符串公开。因此,首先,我将
(this.getAllNamesAsDelimitedString().contains(incomingName)
修改为this.containsName(incomingName)
< br哪个声明:
String name = ((containsName(incomingName)) ? incomingName:
(CollectionsUtils.isEmptyCollection(this.getEntityOperationMap()) ?
null :
this.getEntityOperationMap.get(incomingName))));
好一点。
我将相同的重构应用于下一个三元,通过引入
hasOperations
方法: private boolean hasOperations()
{
return !CollectionUtils.isEmptyCollection(this.getEntityOperationMap())
}
现在发表以下声明:
String name = ((containsName(incomingName)) ? incomingName:
hasOperations() ? this.getEntityOperationMap.get(incomingName)) : null;
再说一遍更好,但仍然令人不快。
最后,我将其换成真正的q4312079 q
private String getName(String incomingName)
{
if (containsName(incomingName))
return incomingName;
else
return hasOperations() ? getOperation(incomingName) : null;
}
评论
\ $ \ begingroup \ $
好人之一,非常好,您提到了“得墨meter耳法则” :)
\ $ \ endgroup \ $
–mprabhat
2011年12月5日7:03
\ $ \ begingroup \ $
摆脱最后的三元操作的一种可能是,当没有操作时,getOperation返回null。还是太不透明?
\ $ \ endgroup \ $
–RoToRa
2011-12-5 12:04
\ $ \ begingroup \ $
@RoToRa这取决于您认为getOperation()的约定应该是什么,以及是否没有操作是否返回null或引发异常是否有效。如果可以返回null,则-是-将三元数移到那里似乎是有效的。
\ $ \ endgroup \ $
–马蒂·皮特(Marty Pitt)
2011年12月6日下午0:01
\ $ \ begingroup \ $
考虑到如果没有操作,让getName返回null会很奇怪,但是如果其中的操作和传入名称不是一个(前者是后者的特例),则抛出异常将会已经返回null(尤其是因为它将替换this.getEntityOperationMap.get,而后者确实做到了)。实际上,考虑到它,原始代码首先检查映射是否为空是有点奇怪的,因为这是不必要的。
\ $ \ endgroup \ $
–RoToRa
2011年12月6日上午8:28
\ $ \ begingroup \ $
还有一件事:自从使用Scala以来,在这种情况下我将使用Option类型/单子,因此明确声明它可以返回“ nothing”。
\ $ \ endgroup \ $
–RoToRa
2011年12月6日上午8:29
#2 楼
我认为必须注意,可以将嵌套的三进制运算符设置为看起来不错的格式:方法调用,但是我认为将条件保持简短和有意义会更好。
评论
\ $ \ begingroup \ $
我完全同意。实际上,我认为嵌套三元运算符是存在的一些最易读的结构!
\ $ \ endgroup \ $
–托德·雷曼(Todd Lehman)
2012年1月22日7:52
#3 楼
在我看来,与使用神秘的三元运算相比,我希望代码更加清晰。如果三元运算符的语句乍一看变得难以理解,那么if.else将是理想的选择。而且,我不知道使用三元运算符在应用程序中有任何性能差异。在您的代码示例中:花一些时间弄清楚三元运算符的情况,即使缩进正确,代码也不会像if ... else那样明显。
也许您可以从这里的相关讨论中受益。
#4 楼
我完全同意用户@seand-格式改变了世界。我认为您的示例完全不是滥用行为,但我认为对它进行一些小的更改会更容易...首先,删除不必要的括号:
String name = this.getAllNamesAsDelimitedString().contains(incomingName) ?
incomingName:
CollectionsUtils.isEmptyCollection(this.getEntityOperationMap() ?
null :
this.getEntityOperationMap.get(incomingName);
接下来,按照@seand的建议重新格式化三元表达式树:和
?
紧接其前一个字符之后-中间没有空格-好像它们是英文标点符号: String name = this.getAllNamesAsDelimitedString().contains(incomingName) ? incomingName
: CollectionsUtils.isEmptyCollection(this.getEntityOperationMap() ? null
: this.getEntityOperationMap.get(incomingName);
但是在这种情况下,我可能会这样写:
String name = isConditionA? "first":
isConditionB? "second":
isConditionC? "third":
"fourth";
评论
\ $ \ begingroup \ $
很好。如何获得Eclipse的格式化程序以这种方式格式化代码?
\ $ \ endgroup \ $
–马丁·施罗德(MartinSchröder)
2012年2月21日23:13
\ $ \ begingroup \ $
@MartinSchröder:参见stackoverflow.com/q/8044946/821436
\ $ \ endgroup \ $
–马丁·施罗德(MartinSchröder)
2012年2月22日10:00
评论
顺便说一句,与三元运算符没有直接关系,如果地图为空,则Map.get将返回null,因此CollectionsUtils.isEmptyCollection分支完全没有必要。@PeterTaylor这可能是检查映射是否为空或为空。但是,考虑将空映射与空映射相同并不是最好的主意。
@Sulthan,用新鲜的眼睛看着它,我认为你是对的。但是,如果将它与null进行实际比较,它将具有更多的自我证明,因为这是唯一的真实目的。
@PeterTaylor同意。
在这种情况下,删除它会有所帮助