我该如何避免重复?

时间:2014-08-07 05:02:37

标签: java

我正在用Java做一个教程,我总是读到我必须尽量不要重复,我注意到这是非常重复的;因此,如果有人能给我一些提示,以减少重复性或某种程度上更好,它是非常适合的。谢谢;)(这不是教程的一部分,我只是为了好玩,因为我在学校的科学学习)

  1. Run.java 文件:

    package scientificFormula;
    
    public class Run {
    
        public static void main(String[] args) {
            Formula formula = new Formula();
    
            formula.compound1 = args[0];
            formula.compound2 = args[1];
    
            String theFormula = formula.createFormula();
            System.out.println("Molecule: " + args[0] + " " + args[1] + " = "
                    + theFormula);
        }
    
    }
    
  2. Formula.java 文件:

    package scientificFormula;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class Formula {
        String compound1;
        String compound2;
        static private Map<String, String> map = new HashMap<String, String>();
    
        static private void initiateIons() {
            // 1+
            map.put("Hydrogen", "H^1+");
            map.put("Lithium", "Li^1+");
            map.put("Sodium", "Na^1+");
            map.put("Potassium", "K^1+");
            map.put("Rubidium", "Rb^1+");
            // 2+
            map.put("Magnesium", "Mg^2+");
            map.put("Calcium", "Ca^2+");
            map.put("Strontium", "Sr^2+");
            // 3+
            map.put("Aluminium", "Al^3+");
            // 3-
            map.put("Nitrogem", "N^-3");
            map.put("Phosphorus", "P^-3");
            // 2-
            map.put("Oxygen", "O^-2");
            map.put("Sulfur", "S^-2");
            map.put("Selenium", "Se^-2");
            // 1-
            map.put("Fluorine", "F^-1");
            map.put("Chlorine", "Cl^-1");
            map.put("Bromine", "Br^-1");
            map.put("Iodine", "I^-1");
        }
    
        String createFormula() {
            initiateIons();
    
            // Example1: Input = Calcium Iodine:
            // 2x + -1y = 0
            // x = 1 and y = 2
            // Output = CaI2
            //
            // Example2: Input = Sulfur Iodine
            // Output = Molecule: Sulfur Iodine = SI2
    
            String symbol1 = map.get(compound1);
            String symbol2 = map.get(compound2);
    
            int charge1 = Integer.parseInt(symbol1.replace("+", "").substring(
                    symbol1.length() - 2));
            int charge2 = Integer.parseInt(symbol2.replace("+", "").substring(
                    symbol2.length() - 2));
    
            String letter1 = null;
            String letter2 = null;
    
            if (symbol1.length() == 5) {
                letter1 = symbol1.substring(0, 2);
            } else if (symbol1.length() == 4) {
                letter1 = symbol1.substring(0, 1);
            }
            if (symbol2.length() == 5) {
                letter2 = symbol2.substring(0, 2);
            } else if (symbol2.length() == 4) {
                letter2 = symbol2.substring(0, 1);
            }
    
            int possitive1 = (int) Math.sqrt(charge1 * charge1);
            int possitive2 = (int) Math.sqrt(charge2 * charge2);
    
            if ((possitive1 == 1) & (possitive2 == 1)) {
                return letter1 + letter2;
            } else if (possitive1 == 1) {
                return letter1 + possitive2 + letter2;
            } else if (possitive2 == 1) {
                return letter1 + letter2 + possitive1;
            }
            if (possitive1 == 0) {
                possitive1 = -(charge1);
            }
    
            if (possitive2 == 0) {
                possitive2 = -(charge2);
            }
    
            return letter1 + possitive2 + letter2 + possitive1;
        }
    }
    

5 个答案:

答案 0 :(得分:3)

我强烈建议您阅读主要涉及重构的书clean code

当您开始重构时,复制代码只是一个(重要)问题(也称为 DRY - 不要重复自己)。还有许多其他原则,我将尝试描述一些我认为最重要的原则:

一个重要的经验法则&#34;是 SRP :单一责任原则,它说每个类应该只有一个责任,如果我们将相同的想法应用于方法 - 每个方法应该只做一件事!听起来可能非常严格,但是当您开始应用它时 - 您的代码将变得更清晰,更易于维护。

另一个是使用有意义的名称(类/方法/变量):

return letter1 + possitive2 + letter2; // you probably meant positive with one 's' (typo!)

对你来说可能意味着什么 - 但对另一位读者来说并不意味着什么 - 现在,当然你可以通过添加代码注释来解决它,但是修补问题而不是解决问题。此外,代码注释变得陈旧 - 要么变得无关紧要,要么变得更糟 - 当代码发生变化并且注释没有时,可能会误导读者。

最后(现在),保持明确的执行顺序,让我们采取你发布的一段代码并改进它:

    String symbol1 = map.get(compound1);
    String symbol2 = map.get(compound2);

    int charge1 = Integer.parseInt(symbol1.replace("+", "").substring(
            symbol1.length() - 2));
    int charge2 = Integer.parseInt(symbol2.replace("+", "").substring(
            symbol2.length() - 2));

    String letter1 = null;
    String letter2 = null;

    if (symbol1.length() == 5) {
        letter1 = symbol1.substring(0, 2);
    } else if (symbol1.length() == 4) {
        letter1 = symbol1.substring(0, 1);
    }
    if (symbol2.length() == 5) {
        letter2 = symbol2.substring(0, 2);
    } else if (symbol2.length() == 4) {
        letter2 = symbol2.substring(0, 1);
    }

    int possitive1 = (int) Math.sqrt(charge1 * charge1);
    int possitive2 = (int) Math.sqrt(charge2 * charge2);

我们可以看到:正面取决于取决于依赖于化合物的符号的电荷。与它无关:字母取决于依赖于化合物的符号。

让我们将其拆分为单独的方法:

int getPositive(String compound) { // I have no idea what "positive", "symbol" and compound represent, consider better names please
    String symbol = map.get(compound);
    int charge = Integer.parseInt(symbol.replace("+", "").substring(
                symbol.length() - 2));
    return (int) Math.sqrt(charge2 * charge2);
}

现在我们可以将其应用于getLetter(String compound) {...}等。

答案 1 :(得分:2)

我会把一些解析放到自己的类中,也许你甚至可以在构建更多功能时将更多内容卸载到那里。

public class Symbol {
    final int charge;
    final String letter;
    public Symbol(String str) {
        int sepIndex = str.indexOf('^');
        if(sepIndex != -1) {
            letter = str.substring(0, sepIndex);
            charge = Integer.parseInt(str.substring(sepIndex+1).replace("+", ""));
        } else {
            throw new IllegalArgumentException(str + " isnt a valid Symbol, no ^ found");
        }
    }
}

public class Formula {
    String compound1;
    String compound2;
    static private Map<String, String> map = new HashMap<String, String>();

    // make this a static block so its only called once.
    static {
        // 1+
        map.put("Hydrogen", "H^1+");
        map.put("Lithium", "Li^1+");
        map.put("Sodium", "Na^1+");
        map.put("Potassium", "K^1+");
        map.put("Rubidium", "Rb^1+");
        // 2+
        map.put("Magnesium", "Mg^2+");
        map.put("Calcium", "Ca^2+");
        map.put("Strontium", "Sr^2+");
        // 3+
        map.put("Aluminium", "Al^3+");
        // 3-
        map.put("Nitrogem", "N^-3");
        map.put("Phosphorus", "P^-3");
        // 2-
        map.put("Oxygen", "O^-2");
        map.put("Sulfur", "S^-2");
        map.put("Selenium", "Se^-2");
        // 1-
        map.put("Fluorine", "F^-1");
        map.put("Chlorine", "Cl^-1");
        map.put("Bromine", "Br^-1");
        map.put("Iodine", "I^-1");
    }
    String createFormula() {

        // Example1: Input = Calcium Iodine:
        // 2x + -1y = 0
        // x = 1 and y = 2
        // Output = CaI2
        //
        // Example2: Input = Sulfur Iodine
        // Output = Molecule: Sulfur Iodine = SI2

        Symbol symbol1 = new Symbol(map.get(compound1));
        Symbol symbol2 = new Symbol(map.get(compound2));

        int possitive1 = Math.abs(symbol1.charge); // sqrt(a*a) == abs(a)
        int possitive2 = Math.abs(symbol1.charge);

        if ((possitive1 == 1) & (possitive2 == 1)) {
            return symbol1.letter + symbol1.letter;
        } else if (possitive1 == 1) {
            return symbol1.letter + possitive2 + symbol2.letter;
        } else if (possitive2 == 1) {
            return symbol1.letter + symbol2.letter + possitive1;
        }

        // dead code, if positive1 is 0 then setting it to -0 does nothing
        /*if (possitive1 == 0) {
            possitive1 = -(symbol1.charge);
        }
        if (possitive2 == 0) {
            possitive2 = -(symbol2.charge);
        }*/

        return symbol1.letter + possitive2 + symbol2.letter + possitive1;
    }
}

答案 2 :(得分:1)

第一种方法:

getCharge(String symbol){
       return Integer.parseInt(symbol.replace("+", "").substring(symbol.length() - 2));
}

第二种方法:

getLetter(String symbol){
    if (symbol.length() == 5) {
        return symbol.substring(0, 2);
    } else if (symbol.length() == 4) {
        return symbol.substring(0, 1);
    } 
}

答案 3 :(得分:1)

我相信这相当于您发布的代码 -

private static String checkCompound(String symbol) {
  if (symbol.length() == 5) {
    return symbol.substring(0, 2);
  } else if (symbol.length() == 4) {
    return symbol.substring(0, 1);
  }
  return "";
}

然后

String letter1 = checkCompound(symbol1);
String letter2 = checkCompound(symbol2);

if (charge1 > 0) {
  if (charge2 > 0) {
    return letter1 + letter2;
  }
  return letter1 + charge2 + letter2;
} else if (charge2 > 0) {
  return letter1 + letter2 + charge1;
}

return letter1 + charge2 + letter2 + charge1;

最后,这个

if (possitive1 == 0) {
  possitive1 = -(charge1);
}

已删除,因为它是-0 0

答案 4 :(得分:1)

好吧,首先让我们重新安排您的代码,以便所有的...... 1变量在一起。根据您的命名约定,您使用letter1来计算symbol1,使用symbol1来计算charge1等等......我只关注createFormula(),因为那是你要减小的部分。

String createFormula() {
    initiateIons();

    //Calculate symbol1, charge1, letter1, possitive1
    String symbol1 = map.get(compound1);
    int charge1 = Integer.parseInt(symbol1.replace("+", "").substring(
            symbol1.length() - 2));
    String letter1 = null;
    if (symbol1.length() == 5) {
        letter1 = symbol1.substring(0, 2);
    } else if (symbol1.length() == 4) {
        letter1 = symbol1.substring(0, 1);
    }
    int possitive1 = (int) Math.sqrt(charge1 * charge1);

    //calculate symbol2, charge2, letter2, possitive2
    String symbol2 = map.get(compound2);
    int charge2 = Integer.parseInt(symbol2.replace("+", "").substring(
            symbol2.length() - 2));
    String letter2 = null;
    if (symbol2.length() == 5) {
        letter2 = symbol2.substring(0, 2);
    } else if (symbol2.length() == 4) {
        letter2 = symbol2.substring(0, 1);
    }
    int possitive2 = (int) Math.sqrt(charge2 * charge2);

    //Returns
    if ((possitive1 == 1) & (possitive2 == 1)) {
        return letter1 + letter2;
    } else if (possitive1 == 1) {
        return letter1 + possitive2 + letter2;
    } else if (possitive2 == 1) {
        return letter1 + letter2 + possitive1;
    }
    if (possitive1 == 0) {
        possitive1 = -(charge1);
    }

    if (possitive2 == 0) {
        possitive2 = -(charge2);
    }

    return letter1 + possitive2 + letter2 + possitive1;
}

我同意,计算步骤似乎是多余的。拥有一个计算它们的函数并返回它们的元组会很奇妙,但是(据我所知)Java还没有元组。我们可以做一个字符串数组,然后从字符串中解析出来。这是一个不太冗余的代码修订版。

String[] calculatePieces(String compound){
    String symbol = map.get(compound);
    int charge = Integer.parseInt(symbol.replace("+", "").substring(
            symbol.length() - 2));
    String letter = null;
    if (symbol.length() == 5) {
        letter = symbol1.substring(0, 2);
    } else if (symbol1.length() == 4) {
        letter = symbol1.substring(0, 1);
    }
    int possitive = (int) Math.sqrt(charge * charge);
    pieces = new String[4];
    pieces[0] = symbol;
    pieces[1] = charge + "";
    pieces[2] = letter;
    pieces[3] = possitive + "";
    return pieces;
}

String createFormula() {
    initiateIons();

    String[] pieces1 = calculatePieces(compound1);
    int charge1 = Integer.parseInt(pieces1[1]);
    int possitive1 = Integer.parseInt(pieces1[3]);
    String[] pieces2 = calculatePieces(compound2);
    int charge2 = Integer.parseInt(pieces2[1]);
    int possitive2 = Integer.parseInt(pieces2[3]);

    //Returns
    if ((possitive1 == 1) & (possitive2 == 1)) {
        return pieces1[2] + pieces2[2];
    } else if (possitive1 == 1) {
        return pieces1[2] + possitive2 + pieces2[2];
    } else if (possitive2 == 1) {
        return pieces1[2] + pieces2[2] + possitive1;
    }
    if (possitive1 == 0) {
        possitive1 = -(charge1);
    }

    if (possitive2 == 0) {
        possitive2 = -(charge2);
    }

    return pieces1[2] + possitive2 + pieces2[2] + possitive1;
}

它好一点,但Java对返回单个对象的限制限制了它可以获得的清洁程度。使它变得更干净的方法是创建一个基本上充当(string,int,string,int)元组的包装器对象,但是如果你需要快速的话,那就不可能了。< / p>