I have a tic-tac-toe game and there is a class in it that describes the game from beginning to end. I think it is too big, but I do not like I can not decide what to take from there, for which I will not undertake and there is a reason why it should be here.
// ΠΎΠΏΠΈΡΡΠ²Π°Π΅Ρ ΠΏΠ°ΡΡΠΈΡ public class Game implements Play { // ΠΎΠ±ΡΠ΅ΠΊΡ ΡΡΠΈΠ»ΠΈΡΠ½ΠΎΠ³ΠΎ ΠΊΠ»Π°ΡΡΠ° Π² ΠΊΠΎΡΠΎΡΡΠΉ Π²ΡΠ½Π΅ΡΠ΅Π½Π° ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° Π½Π°Π»ΠΈΡΠΈΡ ΠΏΠΎΠ±Π΅Π΄ΠΈΡΠ΅Π»Ρ private Validation validation = new ValidationWinnerUtil(); // ΠΈΠ³ΡΠΎΠΊΠΈ private Subject[] gamers = new Subject[2]; // Π²Π²ΠΎΠ΄ Ρ ΠΊΠΎΠ½ΡΠΎΠ»ΠΈ private Input input; // ΠΏΠΎΠ±Π΅Π»ΠΈΡΠ΅Π»Ρ Π΄Π°Π½Π½ΠΎΠΉ ΠΏΠ°ΡΡΠΈΠΈ private Subject win; // Π΄ΠΎΡΠΊΠ° Π΄Π»Ρ ΠΈΠ³ΡΡ private Desk board; public Game(Input input) { this.input = input; } // ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅Ρ ΡΠ°Π·ΠΌΠ΅Ρ Π΄ΠΎΡΠΊΠΈ private void initBoard() { System.out.println("Π₯ΠΎΡΠΈΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΠΉ ΡΠ°Π·ΠΌΠ΅Ρ Π΄ΠΎΡΠΊΠΈ 3Ρ
3 (y/n)?"); String answer = this.input.getString(); if (answer.equals("n")) { System.out.println("ΠΠ²Π΅Π΄ΠΈΡΠ΅ ΡΠ°Π·ΠΌΠ΅Ρ Π΄ΠΎΡΠΊΠΈ :"); this.board = new Board(this.input.getNumber()); } else if (answer.equals("y")) { this.board = new Board(3); } else { initBoard(); } } // for test Subject[] getGamers() { return gamers; } // for test Desk getBoard() { return board; } // ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·ΠΈΡΡΠ΅Ρ ΠΌΠ°ΡΡΠΈΠ² Ρ ΠΈΠ³ΡΠΎΠΊΠ°ΠΌΠΈ. ΠΏΠΎΡΡΠ΄ΠΎΠΊ ΠΌΠ΅Π½ΡΠ΅ΡΡΡ Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ ΡΠΎΠ³ΠΎ ΠΊΡΠΎ // Ρ
ΠΎΠ΄ΠΈΡ ΠΏΠ΅ΡΠ²ΡΠΌ. ΠΊΡΠΎ ΠΏΠ΅ΡΠ²ΡΠΉ ΡΠΎΡ ΠΈΠ³ΡΠ°Π΅Ρ ΠΊΡΠ΅ΡΡΠΈΠΊΠ°ΠΌΠΈ. @Override public void choiceSide() { System.out.println("ΠΡΠΎ Ρ
ΠΎΠ΄ΠΈΡ ΠΏΠ΅ΡΠ²ΡΠΉ: (Bot / I) :"); String answer = this.input.getString().toLowerCase(); if (answer.equals("i")) { this.gamers[0] = new User(Cell.X, "user"); this.gamers[1] = new User(Cell.O, "bot"); } else if (answer.equals("bot")){ this.gamers[0] = new User(Cell.X, "bot"); this.gamers[1] = new User(Cell.O, "user"); } else { choiceSide(); } } // Π·Π°ΡΠΈΠΊΠ»ΠΈΠ²Π°Π΅Ρ ΠΎΡΠ΅ΡΠ΅Π΄Π½ΠΎΡΡΡ Ρ
ΠΎΠ΄ΠΎΠ² ΠΈΠ³ΡΠΎΠΊΠΎΠ² @Override public void loopMove() { this.initBoard(); PrinterBoard.printDesc(board.getBoard()); while (validation.gameCanGoOn(board.getBoard())) { for (Subject subject : this.gamers) { try { if (validation.gameCanGoOn(board.getBoard()) ) { board.move(subject.getColor(), getNewPosition(subject)); PrinterBoard.printDesc(board.getBoard()); this.win = subject; } } catch (IllegalMove illegalMove) { illegalMove.printStackTrace(); } } } } // Π΄Π°Π΅Ρ Π½ΠΎΠ²ΡΡ ΠΏΠΎΠ·ΠΈΡΠΈΡ Π΄Π»Ρ Ρ
ΠΎΠ΄Π° Π΅ΡΠ»ΠΈ Π±ΠΎΡ ΡΠΎ Π³Π΅Π½Π΅ΡΠΈΡΡΠ΅Ρ Π² ΠΊΠ»Π°ΡΡΠ΅ AutomaticMove // Π΅ΡΠ»ΠΈ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ ΡΠΎ Ρ ΠΊΠΎΠ½ΡΠΎΠ»ΠΈ ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅Ρ private Position getNewPosition(Subject subject) { if (subject.getName().equals("user")) { System.out.println("ΠΠΎ Π²Π΅ΡΡΠΈΠΊΠ°Π»ΠΈ:"); int y = this.input.getNumber(); System.out.println("ΠΠΎ Π³ΠΎΡΠΈΠ·ΠΎΠ½ΡΠ°Π»ΠΈ:"); return new Position(this.input.getNumber(), y); } else { return new AutomaticMove().generateMove(this.board); } } // Π² ΠΌΠΎΠΌΠ΅Π½Ρ ΠΊΠΎΠ³Π΄Π° ΠΈΠ³ΡΠ° ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠ°ΡΡΡΡ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ ΡΠΌΠΎΡΡΠΈΡ Π΅ΡΡΡ Π»ΠΈ ΠΏΠΎΠ±Π΅Π΄ΠΈΡΠ΅Π»Ρ Π΅ΡΠ»ΠΈ Π΄Π° ΡΠΎ Π·Π°ΠΏΠΈΡΡΠ²Π°Π΅Ρ Π΅Π³ΠΎ Π² ΠΏΠΎΠ»Π΅ win @Override public Subject initWinner() { if (!this.validation.emptyCellExist(board.getBoard()) && !this.validation.winnerDetermines(board.getBoard())) { System.out.println("ΠΠΈΡΡΡ"); return new User(Cell.EMPTY, "nobody"); } else { System.out.println(format("ΠΠΎΠ±Π΅Π΄ΠΈΡΠ΅Π»Ρ: %s", this.win.getColor())); return this.win; } } } ΠΠΎΡ ΡΠ΅ΡΡΡ ΠΊ Π½Π΅ΠΌΡ: @Test public void whenUserMoveFirstThenUserAddInArrGamersFirst() { StubInput input = new StubInput(); input.setAnswersStr(new String[] {"i"}); input.setAnswersNum(new int[]{3}); Game game = new Game(input); game.choiceSide(); assertThat(game.getGamers()[0].getName(), is("user")); assertThat(game.getGamers()[1].getName(), is("bot")); } @Test public void whenBotMoveFirstThenUserAddInArrFirst() { StubInput input = new StubInput(); input.setAnswersStr(new String[] {"bot"}); input.setAnswersNum(new int[] {3}); Game game = new Game(input); game.choiceSide(); assertThat(game.getGamers()[0].getName(), is("bot")); assertThat(game.getGamers()[1].getName(), is("user")); } @Test public void whenBotMoveFirstAndWinByHorizontalThen() { StubInput input = new StubInput(); input.setAnswersStr(new String[] {"bot", "y"}); input.setAnswersNum(new int[] {2, 0, 2, 1}); Game game = new Game(input); game.choiceSide(); game.loopMove(); Subject subject = game.initWinner(); assertThat(subject.getName(), is("bot")); assertThat(subject.getColor(), is(Cell.X)); } @Test public void whenManMoveFirstAndWinByHorizontalThen() { StubInput input = new StubInput(); input.setAnswersStr(new String[] {"I", "y"}); input.setAnswersNum(new int[] {0, 1, 1, 1, 2, 1}); Game game = new Game(input); game.choiceSide(); game.loopMove(); Subject subject = game.initWinner(); assertThat(subject.getName(), is("user")); assertThat(subject.getColor(), is(Cell.X)); } @Test public void whenManMoveFirstAndWinByVerticalThen() { StubInput input = new StubInput(); input.setAnswersStr(new String[] {"I", "y"}); input.setAnswersNum(new int[] {0, 0, 1, 0, 2, 0}); Game game = new Game(input); game.choiceSide(); game.loopMove(); Subject subject = game.initWinner(); assertThat(subject.getName(), is("user")); assertThat(subject.getColor(), is(Cell.X)); } @Test public void whenBotMoveSecondAndWinByVerticalThen() { StubInput input = new StubInput(); input.setAnswersStr(new String[] {"I", "y"}); input.setAnswersNum(new int[] {0, 1, 0, 2, 1, 1, 2, 2}); Game game = new Game(input); game.choiceSide(); game.loopMove(); Subject subject = game.initWinner(); assertThat(subject.getName(), is("bot")); assertThat(subject.getColor(), is(Cell.O)); } @Test public void whenManMoveFirstAndWinByDiagonalLeftUpToRightDownThen() { StubInput input = new StubInput(); input.setAnswersStr(new String[] {"I", "y"}); input.setAnswersNum(new int[] {0, 0, 1, 1, 2, 2}); Game game = new Game(input); game.choiceSide(); game.loopMove(); Subject subject = game.initWinner(); assertThat(subject.getName(), is("user")); assertThat(subject.getColor(), is(Cell.X)); } @Test public void whenManMoveSecondAndWinByDiagonalRightUpToLeftDownThen() { StubInput input = new StubInput(); input.setAnswersStr(new String[] {"bot", "y"}); input.setAnswersNum(new int[] {0, 2, 1, 1, 2, 0}); Game game = new Game(input); game.choiceSide(); game.loopMove(); Subject subject = game.initWinner(); assertThat(subject.getName(), is("user")); assertThat(subject.getColor(), is(Cell.O)); } @Test public void whenUseNonstandardSizeDescThenSizeItIsChoiceUser() { StubInput input = new StubInput(); input.setAnswersStr(new String[] {"bot", "n"}); input.setAnswersNum(new int[] {4, 0, 1, 1, 1, 2, 1, 3, 1}); Game game = new Game(input); game.choiceSide(); game.loopMove(); assertThat(game.getBoard().getBoard().length, is(4)); } At first glance, it seems to me that I need to make a definition of the size of the board, but if I initBoard() then several classes will depend on my Input (and not just the Game ), and problems with testing will begin. The same problem with getNewPosition(Subject subject) also needs input from the console. Well, such methods as initWinner() - determining the winner, loopMove() - looping the moves to a certain end of the game, or choiceSide() - choosing who goes first I do not consider taking away from this class, they clearly belong to the game. After all, the party in this is what: chose who for whom, spent the moves themselves, determined the winner.
In general, such a dilemma. Tell me how to be?
The problem is that I need only 1 class to depend on input from the console, but at the same time other methods that do not fit into the general theme of this class fall into my class.
possible example:
In the class of the game for example method:
private Dialogs dialogs = new Dialogs(); private void initBoard() { String answer = this.dialogs.ask("Π₯ΠΎΡΠΈΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΠΉ ΡΠ°Π·ΠΌΠ΅Ρ Π΄ΠΎΡΠΊΠΈ 3Ρ
3 (y/n)?"); if (answer.equals("n")) { System.out.println("ΠΠ²Π΅Π΄ΠΈΡΠ΅ ΡΠ°Π·ΠΌΠ΅Ρ Π΄ΠΎΡΠΊΠΈ :"); this.board = new Board(this.input.getNumber()); } else if (answer.equals("y")) { this.board = new Board(3); } else { initBoard(); } } And the class that encapsulates the input:
public class Dialogs { private Input input = new ConsoleInput(); public void setInput(Input input) { this.input = input; } public String ask(String question) { System.out.println(question); return this.input.getString(); } public int askPosition(String question) { System.out.println(question); return this.input.getNumber(); }
initBoardand everything else. Because you will not need to "ask questions" in the course of initialization - Sublihim