首页 > 解决方案 > 我如何在 Java 中对这种气味代码进行重构/提取方法?

问题描述

我在重构这段代码时遇到了问题。我如何提取这个长方法?我不知道这些代码中的气味代码在哪里,你们能帮我弄清楚这些气味代码以及如何重构这些代码吗?

private boolean placingFlag = false;
    protected Scanner scan = new Scanner(System.in);
    public void play() {
        clear();
        print();

        if(placingFlag) {
            System.out.println("currently your command is for placing/unplacing flag. Type 'switch' to start opening squares");
        } else {
            System.out.println("currently your command is for opening square. Type 'switch' to placing flag");
        }

        do {
            System.out.print("Input coordinate to command: ");
            String input = scan.nextLine().trim();
            if(input.equalsIgnoreCase("switch")) {
                placingFlag = !placingFlag;
                break;
            }
            if(input.length() != 2) {
                System.out.println("invalid coordinate");
                continue;
            }

            char c1 = input.charAt(0);
            char c2 = input.charAt(1);
            int x = c1 - 'A';
            int y = c2 - '1';

            if(x < 0 || x >= gameSetting.getWidth()) {
                System.out.println("invalid coordinate");
                continue;
            }
            if(y < 0 || y >= gameSetting.getHeight()) {
                System.out.println("invalid coordinate");
                continue;
            }

            if(!placingFlag) {
                if(board[y][x].flagged){
                    System.out.println("cannot open flagged square");
                    continue;
                }
                if(board[y][x].getType().equalsIgnoreCase("mine")) {
                    this.lose();
                    return;
                }

                open(x, y);

                if(isWin()) {
                    this.win();
                    return;
                }
            } else {
                if(board[y][x].getType().equalsIgnoreCase("number")) {
                    System.out.println("opened squared cannot be flagged");
                    continue;
                }
                board[y][x].flagged = !board[y][x].flagged;
            }
            break;
        }while(true);

        play();
    }

请大家给我这些代码的启发如何提取这些长方法:)

标签: javarefactoringextract-method

解决方案


这还不错。您可以做的一件事 - 根据该输入将阅读输入与播放分开:

private static class GameMove {
  int x;
  int y;
  boolean switchFlagPlacingMode;
}

private GameMove readNextMove() { 
 // read in using the scanner
 // and validate the coordinates
}

另一件事 -while(true)绝对是代码味道,就像你拥有的 , 和语句的数量一样continue-break它们return使代码难以追踪。考虑类似的东西

boolean gameOver = false;

while(!gameOver) {

  boolean isMoveValid = false;
  GameMove nextMove = readNextMove();
  while(!isMoveValid) {
    // validate, set isMoveValid
    // if invalid: nextMove = readNextMove();
  }

  // process the move
  if (isWin()) {
    this.win();
    gameOver = true;
  }
  // similar for loss
}



推荐阅读