如何使复杂的条件看起来不错并节省语句的数量?

Posted

技术标签:

【中文标题】如何使复杂的条件看起来不错并节省语句的数量?【英文标题】:How to make complex conditions look nice and save the number of statements? 【发布时间】:2012-12-25 09:14:58 【问题描述】:

在我的 java 应用程序中,我有大量的条件来决定一个动作。我的问题是如何让它看起来不错(我使用 NetBeans,所以我更喜欢不会被其代码格式化功能破坏的解决方案)。我还希望 if/else 语句的数量尽可能少,因为我认为它会使其更快。

我原来的代码很乱,所以做了一个动作图:。 Take a copy 如果你想玩它。请记住,对于 UML 语法,该图并不完美,部分原因是我使用谷歌文档制作的。

这是代码:

if (!config.get("checkForSpecials") || event.isNotSpecial()) 
    if (config.get("filterMode").equals("blacklist")) 
        if (!itemFilter.contains(event.getItem().getName())) 
            item.process();
        
     else if (config.get("filterMode").equals("whitelist")) 
        if (itemFilter.contains(event.getItem().getName())) 
            item.process();
        
     else 
        item.process();
    

有两点我不喜欢它 - 条件不太清楚(尤其是当我展开完整的方法名称和配置字符串时),以及 process 方法调用存在 3 次这一事实。

【问题讨论】:

也许您可以从声明布尔标志开始,这些标志代表条件并具有有意义的名称。 ewernli.com/noif 【参考方案1】:

分解布尔值并缓存方法调用的返回值有助于澄清代码。

此外,将所有结果绘制在逻辑表上会有所帮助。我使用this tool 提供帮助。

使用链接工具:

A: config.get("filterMode").equals("blacklist")
B: config.get("filterMode").equals("whitelist")
C: filterContainsName (see below)

工具大量涌现:

(!A && !B) || (!A && C) || (A && !C)

这导致下面的代码(用(B && C)替换(!A && C)的小调整):

boolean filterContainsName = itemFilter.contains(event.getItem().getName());
boolean useBlacklist       = config.get("filterMode").equals("blacklist");
boolean useWhitelist       = config.get("filterMode").equals("whitelist");

if (!config.get("safeMode") || event.isSafe()) 
    if((!useBlackList && !useWhiteList) ||
       ( useWhiteList &&  filterContainsName) ||
       ( useBlackList && !filterContainsName)) 
        item.process();
    

【讨论】:

我猜这取决于您习惯看到的代码结构。我认为嵌套的 if 表示隐式 AND,这种方法使它们显式......我倾向于更喜欢条件的显式表示,除非以另一种方式这样做有明显的好处(例如,如果评估布尔值是昂贵的并且可以避免取决于早期的评估) 赞成解释性变量名称,它们非常便于阅读。【参考方案2】:

使用地图。映射的键是条件/案例,值是包含该条件逻辑的单个方法类/匿名用户接口。每当您遇到某种情况/情况时,您只需在地图中查找并执行相关功能。通过这种方式,您甚至可以将您的逻辑按条件拆分为单独的类(如果为了代码美观而需要)。作为额外奖励,当条件数 > 10 时,您可能会获得性能奖励。

【讨论】:

你有这方面的例子,或者一个澄清博客文章的链接吗? pastebin.com/5JL51udN 一些示例代码。在此示例中,使用 eventCode 来查找正确的事件处理程序。您可以创建任何类型的“案例标识符”(处理程序映射中的键),前提是您可以在事件到达时对其进行重构。 这很有趣。但是我认为它对我的应用程序来说太复杂了,我也无法完全理解它(我是 Java 和 OOP 的新手)。如果您对此有更深入的文章,我愿意阅读:) 一段时间后回来,我现在明白这是什么意思了。我实际上知道如何在 javascript 或 Lua 中做这样的事情(而且我一直在使用这种简洁的方法,但不知道自己在做什么)。但是我不知道如何在 Java 中使用这个原理。而且我仍然不完全理解 pastebin 示例。感谢您的进一步澄清。【参考方案3】:

对我来说看起来不错。或许您可以将调用item.process() 的有效条件隔离到一个方法中,使其更易于理解。

if (!config.get("safeMode") || event.isSafe()) 
    if (isItemValidForProcess(config, itemFilter, event)) 
        item.process();
    


boolean isItemValidForProcess(config, itemFilter, event) 
    String filterMode = config.get("filterMode");
    if (filterMode.equals("whitelist")) 
        return itemFilter.contains(event.getItem().getName());
    
    if (filterMode.equals("blacklist")) 
        return !itemFilter.contains(event.getItem().getName());
    
    return true;

【讨论】:

【参考方案4】:

信不信由你,这个图表并没有那么复杂:) 没有循环,它是相当线性的。

这是一个实现它的伪代码

void action()

    if <sort out specials>
        if <is it special>
            return;

    if <check for unsafe items>
        if not <safe items list contains item>
            return;

    if <filter status = on>
        if < filter mode = whitelist>
            if not <item is on filter>
                return;
        else // black list
            if not <item is on filter>
                return;

    // finally!            
    [process item]

对于非常复杂的图表,答案是... goto ...

【讨论】:

以上是关于如何使复杂的条件看起来不错并节省语句的数量?的主要内容,如果未能解决你的问题,请参考以下文章

一个复杂的sql语句-分条件查询

一个复杂的sql语句-分条件查询

一个复杂的sql语句-分条件查询

如何使用 xslt 获取与复杂条件匹配的所有 xml 项的计数并在终止语句中使用它?

如何计算C++的复杂度?

需要有关 SQL 中复杂 Join 语句的帮助