๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿ’ป/Java CleanCode Study

๐Ÿชœ์‚ฌ๋‹ค๋ฆฌ ๊ฒŒ์ž„ # 2022.04.18~2022.05.02

๐ŸŽˆ ๊ตฌํ˜„ ๊ธฐ๋Šฅ ๋ชฉ๋ก

  • ์ž…๋ ฅ
    • ์ฐธ์—ฌ์ž ์ด๋ฆ„
    • ์‹คํ–‰ ๊ฒฐ๊ณผ
    • ์ตœ๋Œ€ ์‚ฌ๋‹ค๋ฆฌ ๋†’์ด
    • ๊ฒฐ๊ณผ ๋ณด๊ณ ์‹ถ์€ ์‚ฌ๋žŒ ์ด๋ฆ„ (๊ฐœ์ธ or all)
  • ์ถœ๋ ฅ
    • ์‚ฌ๋‹ค๋ฆฌ ๊ฒฐ๊ณผ
      • ํ•˜๋‚˜์˜ ๊ฐ€๋กœ ๋ผ์ธ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” Line Class
      • ํ•˜๋‚˜์˜ ์„ธ๋กœ ๋ผ์ธ์— ๋นˆ ๊ฐ’์ด ์—†๋„๋ก ๊ฐ€๋กœ ๋ผ์ธ์„ ์ƒ์„ฑํ•˜๋Š” ๋กœ์ง ์ถ”๊ฐ€
      • ์ตœ๋Œ€ ์‚ฌ๋‹ค๋ฆฌ ๋†’์ด๋งŒํผ Line์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” Ladder Class
    • ์‹คํ–‰ ๊ฒฐ๊ณผ (๊ฐœ์ธ or all)
      • ๋ผ์ธ์„ ๋”ฐ๋ผ player์˜ ์œ„์น˜๋ฅผ ์ด๋™ ์‹œ์ผœ ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋กœ์ง ์ถ”๊ฐ€

๐Ÿš€ ๊ธฐ๋Šฅ ์š”๊ตฌ ์‚ฌํ•ญ

  • ์‚ฌ๋‹ค๋ฆฌ ๊ฒŒ์ž„์— ์ฐธ์—ฌํ•˜๋Š” ์‚ฌ๋žŒ์— ์ด๋ฆ„์„ ์ตœ๋Œ€5๊ธ€์ž๊นŒ์ง€ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์‚ฌ๋‹ค๋ฆฌ๋ฅผ ์ถœ๋ ฅํ•  ๋•Œ ์‚ฌ๋žŒ ์ด๋ฆ„๋„ ๊ฐ™์ด ์ถœ๋ ฅํ•œ๋‹ค.
  • ์‚ฌ๋žŒ ์ด๋ฆ„์€ ์‰ผํ‘œ(,)๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๊ตฌ๋ถ„ํ•œ๋‹ค.
  • ์‚ฌ๋žŒ ์ด๋ฆ„์„ 5์ž ๊ธฐ์ค€์œผ๋กœ ์ถœ๋ ฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ๋‹ค๋ฆฌ ํญ๋„ ๋„“์–ด์ ธ์•ผ ํ•œ๋‹ค.
  • ์‚ฌ๋‹ค๋ฆฌ ํƒ€๊ธฐ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋ ค๋ฉด ๋ผ์ธ์ด ๊ฒน์น˜์ง€ ์•Š๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค.
    • |-----|-----| ๋ชจ์–‘๊ณผ ๊ฐ™์ด ๊ฐ€๋กœ ๋ผ์ธ์ด ๊ฒน์น˜๋Š” ๊ฒฝ์šฐ ์–ด๋Š ๋ฐฉํ–ฅ์œผ๋กœ ์ด๋™ํ• ์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์—†๋‹ค.
  • ์‚ฌ๋‹ค๋ฆฌ ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•ด์•ผ ํ•œ๋‹ค.
  • ๊ฐœ์ธ๋ณ„ ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜๋ฉด ๊ฐœ์ธ๋ณ„ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•˜๊ณ , "all"์„ ์ž…๋ ฅํ•˜๋ฉด ์ „์ฒด ์ฐธ์—ฌ์ž์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

๐Ÿš€ ๊ตฌํ˜„ํ•ด์•ผ ํ•  ๊ธฐ๋Šฅ

  • ์œ„ ์š”๊ตฌ์‚ฌํ•ญ์— ๋”ฐ๋ผ 4๋ช…์˜ ์‚ฌ๋žŒ์„ ์œ„ํ•œ 5๊ฐœ ๋†’์ด ์‚ฌ๋‹ค๋ฆฌ๋ฅผ ๋งŒ๋“ค ๊ฒฝ์šฐ, ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•œ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
์ฐธ์—ฌํ•  ์‚ฌ๋žŒ ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š”. (์ด๋ฆ„์€ ์‰ผํ‘œ(,)๋กœ ๊ตฌ๋ถ„ํ•˜์„ธ์š”)
dowon, halim, geinee, dowon2

์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”. (๊ฒฐ๊ณผ๋Š” ์‰ผํ‘œ(,)๋กœ ๊ตฌ๋ถ„ํ•˜์„ธ์š”)
๊ฝ,5000,๊ฝ,3000

์ตœ๋Œ€ ์‚ฌ๋‹ค๋ฆฌ ๋†’์ด๋Š” ๋ช‡ ๊ฐœ์ธ๊ฐ€์š”?
5

์‚ฌ๋‹ค๋ฆฌ ๊ฒฐ๊ณผ

dowon  halim  geinee dowon2
    |-----|     |-----|
    |     |-----|     |
    |-----|     |     |
    |     |-----|     |
    |-----|     |-----|
    ๊ฝ    5000  ๊ฝ    3000

๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ  ์‹ถ์€ ์‚ฌ๋žŒ์€?
dowon

์‹คํ–‰ ๊ฒฐ๊ณผ
๊ฝ

๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ  ์‹ถ์€ ์‚ฌ๋žŒ์€?
all

์‹คํ–‰ ๊ฒฐ๊ณผ
dowon : ๊ฝ
halim : 3000
geinee : ๊ฝ
dowon2 : 5000

 

###

- ๋ฉ”์„œ๋“œ ์„ ์–ธ ๊ทœ์น™

1.

์ƒ์„ฑ์ž
static ๋ฉ”์„œ๋“œ
public ๋ฉ”์„œ๋“œ
private ๋ฉ”์„œ๋“œ
getter ๋ฉ”์„œ๋“œ

2.

์ƒ์„ฑ์ž
static ๋ฉ”์„œ๋“œ
public ๋ฉ”์„œ๋“œ
์œ„ public๋ฉ”์„œ๋“œ์—์„œ ํ˜ธ์ถœํ•˜๋Š” private ๋ฉ”์„œ๋“œ๋“ค
public ๋ฉ”์„œ๋“œ
์œ„ public๋ฉ”์„œ๋“œ์—์„œ ํ˜ธ์ถœํ•˜๋Š” private ๋ฉ”์„œ๋“œ๋“ค
๋ฐ˜๋ณต..
getter ๋ฉ”์„œ๋“œ

 

- Random ๊ฐ์ฒด nextBoolean() 

- ๋ฐฐ์—ด๋ณด๋‹ค๋Š” java Collection(List, Map, Set) ์‚ฌ์šฉ

- ์ˆซ์ž ์ƒ์ˆ˜ ์„ ์–ธ

- stream ์‚ฌ์šฉ

before
after

- ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€ ํ™œ์šฉ

- for, if๋ฌธ ๋“ฑ ํ•œ์ค„ ์ค‘๊ด„ํ˜ธ ์ƒ๋žต x 

 

main controller 

public class LadderGame {
    public static final String ALL = "all";

    public void play() {
        Players players = createPlayers();
        int playerCount = players.getPlayerCount();
        Prizes prizes = createPrizes(playerCount);
        int height = inputHeight();

        Ladder ladder = new Ladder(playerCount, height);

        printLadder(players, ladder, prizes);
        GameResult gameResult = createGameResult(players, ladder, prizes);
        printGameResult(gameResult);
    }

    private Players createPlayers() {
        String[] names;
        Players players;

        do {
            names = inputPlayersNames();
            players = new Players(names);
        } while (!players.isValidNameLength(names) || !players.isValidPlayerCount(names));

        return players;
    }

    private String[] inputPlayersNames() {
        String names = InputView.inputPlayersNames();
        return Convert.splitNames(names);
    }

    private Prizes createPrizes(int playerCount) {
        String[] prize;
        Prizes prizes;

        do {
            prize = inputPrizes();
            prizes = new Prizes(prize);
        } while (!prizes.isValidPrizeCount(prize, playerCount));

        return prizes;
    }

    private String[] inputPrizes() {
        String prizes = InputView.inputPrizes();
        return Convert.splitNames(prizes);
    }

    private int inputHeight() {
        return InputView.inputHeight();
    }

    private void printLadder(Players players, Ladder ladder, Prizes prizes) {
        OutputView.printPlayersNames(players.getPlayers());

        for (Line line : ladder.getLadder()) {
            OutputView.printLine(line.getLine());
        }

        OutputView.printPrizes(prizes.getPrizes());
    }

    private GameResult createGameResult(Players players, Ladder ladder, Prizes prizes) {
        GameResultCreator gameResultCreator = new GameResultCreator(players.getPlayers(), ladder.getLadder(), prizes.getPrizes());
        return new GameResult(gameResultCreator.getGameResult());
    }

    private void printGameResult(GameResult gameResult) {
        do {
            String name = InputView.inputPeopleResultRequest();
            if (name.equals(ALL)) {
                break;
            }

            printPlayerResult(gameResult, name);
        } while (true);

        OutputView.printAllGameResult(gameResult.getGameResult());
    }

    private void printPlayerResult(GameResult gameResult, String name) {
        Map<String, String> results = gameResult.getGameResult();

        if (results.get(name) == null) {
            System.out.println("ํ•ด๋‹น ํ”Œ๋ ˆ์ด์–ด๋Š” ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. \n๋‹ค์‹œ ์ž…๋ ฅ ํ•ด ์ฃผ์„ธ์š”.");
            return;
        }

        OutputView.printOnePeopleGameResult(gameResult.getGameResult(), name);
    }
}

model.GameResultCreator

public class GameResultCreator {
    private final Map<String, String> gameResult;

    public GameResultCreator(List<String> players, List<Line> lines, List<String> prizes) {
        this.gameResult = createGameResult(players, lines, prizes);
    }

    private Map<String, String> createGameResult(List<String> players, List<Line> lines, List<String> prizes) {
        Map<String, String> gameResult = new HashMap<>();

        for (int i = 0; i < players.size(); i++) {
            int finalPlayerLocationIdx = findFinalPlayerLocationIdx(lines, i);

            String playerName = players.get(i);
            String prize = prizes.get(finalPlayerLocationIdx);
            gameResult.put(playerName, prize);
        }

        return gameResult;
    }

    private int findFinalPlayerLocationIdx(List<Line> lines, int playerStartIdx) {
        int location = playerStartIdx;
        int height = 0;

        while (height < lines.size()) {
            Line line = lines.get(height);
            location = updateLocation(line, location);
            height++;
        }

        return location;
    }

    private int updateLocation(Line line, int location) {
        int lastIdx = line.getLine().size();

        if (location == 0) {
            location = updateRightDirection(line.getLine(), location);
            return location;
        }

        if (location == lastIdx) {
            location = updateLeftDirection(line.getLine(), location);
            return location;
        }

        int newLocation = updateRightDirection(line.getLine(), location);

        return newLocation != location ? newLocation : updateLeftDirection(line.getLine(), location);
    }

    private int updateRightDirection(List<Boolean> points, int location) {
        boolean rightPoint = points.get(location);
        return rightPoint ? location + 1 : location;
    }

    private int updateLeftDirection(List<Boolean> points, int location) {
        boolean leftPoint = points.get(location - 1);
        return leftPoint ? location - 1 : location;
    }

    public Map<String, String> getGameResult() {
        return this.gameResult;
    }
}

model.Line

public class Line {
    private final List<Boolean> line;

    public Line(int width) {
        this.line = createLine(width);
    }

    private List<Boolean> createLine(int width) {
        Random random = new Random();
        List<Boolean> points = new ArrayList<>();

        for (int i = 0; i < width; i++) {
            points.add(random.nextBoolean());
        }

        return createValidLine(points);
    }

    private List<Boolean> createValidLine(List<Boolean> points) {
        int width = points.size();

        for (int i = 0; i < width; i++) {
            modifyPoint(points, i);
        }

        return points;
    }

    private void modifyPoint(List<Boolean> points, int pointIdx) {
        int width = points.size();
        int lastIdx = width - 1;

        if (pointIdx != lastIdx && isValidPoints(points, pointIdx)) {
            points.set(pointIdx + 1, false);
        }
    }

    private boolean isValidPoints(List<Boolean> points, int index) {
        return points.get(index) && points.get(index + 1);
    }

    public List<Boolean> getLine() {
        return this.line;
    }
}

model.Lines

public class Lines {
    private final List<Line> lines;

    public Lines(int width, int height) {
        this.lines = createValidLines(width, height);
    }

    private List<Line> createValidLines(int width, int height) {
        List<Line> lines;
        boolean replay;

        do {
            lines = createRandomLines(width, height);
            List<Integer> count = calculateBridgesCounts(lines, width, height);

            replay = count.stream()
                    .anyMatch(bridgeCount -> bridgeCount == 0);
        } while (replay);

        return lines;
    }

    private List<Line> createRandomLines(int width, int height) {
        List<Line> lines = new ArrayList<>();

        for (int i = 0; i < height; i++)
            lines.add(new Line(width));

        return lines;
    }

    private List<Integer> calculateBridgesCounts(List<Line> lines, int width, int height) {
        List<Integer> bridgesCounts = new ArrayList<>();

        for (int i = 0; i < width; i++) {
            int bridgeCount = getBridgeCount(lines, i, height);
            bridgesCounts.add(bridgeCount);
        }

        return bridgesCounts;
    }

    private int getBridgeCount(List<Line> lines, int index, int height) {
        int count = 0;

        for (int i = 0; i < height; i++) {
            Line line = lines.get(i);
            List<Boolean> points = line.getLine();
            count = updateBridgeCount(points.get(index), count);
        }

        return count;
    }

    private int updateBridgeCount(boolean point, int count) {
        return point ? count + 1 : count;
    }

    public List<Line> getLines() {
        return this.lines;
    }

}