避免使用嵌套的if语句

ben*_*456 2 java

我目前有以下代码.我使用嵌套的if语句根据不同的情况返回不同的错误

if(!cipherFileRead.isEmpty() && !freqFileRead.isEmpty() ){

    if(freqChooser.getSelection()!=null){

        if(nearestFreq.isSelected()){
            file.writeToFile(decrypter.nearestFreq(cipherFileRead, freqFileRead), "output.txt");;
        }
        else if (rankingFreq.isSelected()){
            file.writeToFile(decrypter.byRanking(cipherFileRead, freqFileRead), "output.txt");;
        }

        returnMessage = "Succesfully decrypted to output.txt";
    }
    else{
        returnMessage = "Please select decryption type. Decryption unsuccesful";}
}
else{
    returnMessage = "Both files must be loaded and contain text. Decryption unsuccesful.";}

JOptionPane.showMessageDialog(null, returnMessage);
}  
Run Code Online (Sandbox Code Playgroud)

有没有更优雅的方法来实现这一点,没有大量可怕的IF语句?

Zab*_*uza 9

您确实可以显着降低嵌套级别.无论你喜欢与否,我都会把它留给你.

您的代码目前有三个级别的嵌套,这是相对正常的.使用注释可以使代码更具可读性.但是,您可以调整以下一些技巧.


仍未分配

String returnMessage = null;

// Something is empty
if (cipherFileRead.isEmpty() || freqFileRead.isEmpty()) {
    returnMessage = "Both files must be loaded and contain text. Decryption unsuccessful.";
}

// No description type given
if (returnMessage == null && freqChooser.getSelection() == null) {
    returnMessage = "Please select decryption type. Decryption unsuccessful";
}

// Decrypt
if (returnMessage == null) {
    // Select technique
    String decryptedText = null;
    if (nearestFreq.isSelected()) {
        decryptedText = decrypter.nearestFreq(cipherFileRead, freqFileRead);
    } else if (rankingFreq.isSelected()) {
        decryptedText = decrypter.byRanking(cipherFileRead, freqFileRead);
    }

    // Write decrypted text
    file.writeToFile(decryptedText, "output.txt");

    returnMessage = "Successfully decrypted to output.txt";
}

// Show return message
JOptionPane.showMessageDialog(null, returnMessage);
Run Code Online (Sandbox Code Playgroud)

所以诀窍是检查是否returnMessage仍未分配.

缺点这种风格是它减慢程序一点,因为它使得它更难的处理器来猜测正确的条件进行流水线.这称为分支预测,所有处理器都这样做.

但是,如果它增强了可读性,例如通过减少非常深的嵌套,您可以使用它.


从方法返回

但是,如果这是一种方法,我肯定会给出使用这种风格的建议,但之后使用returnlike:

public String decryptFile() {
    // Something is empty
    if (cipherFileRead.isEmpty() || freqFileRead.isEmpty()) {
        return "Both files must be loaded and contain text. Decryption unsuccessful.";
    }

    // No description type given
    if (freqChooser.getSelection() == null) {
        return "Please select decryption type. Decryption unsuccessful";
    }

    // Decrypt
    // Select technique to use
    String decryptedText = null;
    if (nearestFreq.isSelected()) {
        decryptedText = decrypter.nearestFreq(cipherFileRead, freqFileRead);
    } else if (rankingFreq.isSelected()) {
        decryptedText = decrypter.byRanking(cipherFileRead, freqFileRead);
    } else {
        // Out of techniques?
        return "No decryption technique can be applied.";
        // Or if this must not happen due to context, use:
        // throw new AssertionError();
    }

    // Write decrypted text
    file.writeToFile(decryptedText, "output.txt");

    return "Successfully decrypted to output.txt";
}
Run Code Online (Sandbox Code Playgroud)

然后调用者会这样做:

// Show return message
JOptionPane.showMessageDialog(null, decryptFile());
Run Code Online (Sandbox Code Playgroud)

在这种情况下,除了减少嵌套之外,还可以减少在代码本身中花费的时间.

应该把它装在一个方法中.它不应该是解密的决定在何处以及如何显示返回消息.而是返回消息并让调用者决定如何使用它.

请注意,在实践中,您可能希望向方法添加一些参数,依此类推.此外,您可能希望使用异常而不是普通String消息,例如IllegalArgumentException.


Ant*_* Ng 6

我将使用我最喜欢的一本名为“干净代码”的书的原则来回答:

  1. 一个函数应该只做一件事,如果你像这样嵌套的话你的函数肯定会做不止一件事。

  2. 因此,这意味着每个 if/else if/else 块都应该位于其自己的函数中。这解决了嵌套 if 的问题。

  3. 并且应该为提取的函数指定一个描述性名称来说明其功能。这比评论更好,因为评论可能会过时,甚至不相关,从而产生误导。

因此,如果我尝试用上述原则重构你的函数,我可能会想出这样的东西:

public void displayDecryptResult() {
    String decryptResult = decrypt();
    JOptionPane.showMessageDialog(null, decryptResult);
}

private String decrypt() {
    String decryptResult;

    if(!cipherFileRead.isEmpty() && !freqFileRead.isEmpty() ){
        decryptResult = decryptForValidInputFiles();
    } else{
        decryptResult = "Both files must be loaded and contain text. Decryption unsuccesful.";
    }

    return decryptResult;
}

private String decryptForValidInputFiles() {
    if (freqChooser.getSelection() != null){
        message = decryptForValidInputFilesAndDecryptionType();
    } else {
        message = "Please select decryption type. Decryption unsuccesful";}
    }

    return message;
}

private String decryptForValidInputFilesAndDecryptionType() {
    if(nearestFreq.isSelected()){
        file.writeToFile(decrypter.nearestFreq(cipherFileRead, freqFileRead), "output.txt");;
    }
    else if (rankingFreq.isSelected()){
        file.writeToFile(decrypter.byRanking(cipherFileRead, freqFileRead), "output.txt");;
    }

    return "Succesfully decrypted to output.txt";
}
Run Code Online (Sandbox Code Playgroud)

有些人可能会发现函数名称过于具有描述性,以至于变得可笑。但是,在编写代码很长一段时间后,您必须对其进行调试,您会感谢您给出了这些描述性名称,因此您可以轻松地浏览伪代码(如名称)以了解它正在尝试执行的操作。