추상화
가독성 좋은 코드를 작성하는 첫번째 원리 추상과 구체를 이해하자
추상화는 최소 정보의 단위를 묶어서 어떻게 부를 것이냐에 관점이며, 컴퓨터 과학은 이러한 추상화 과정이 조화롭게 겹겹이 쌓여서 만들어진다
예를 들어보자면 1bit를 1byte, 1word 등 0과 1로만 이루어진 단위를 우리는 훨씬 더 큰 단위로 묶어서 부를 수 있고 그 단위로 인해 어플리케이션에서 제어할 수 있는 부분의 범위를 넓힌다.
추상화 된 내용으로부터 구체적인 정보를 해석하지 못하는 경우
추상화 과정에서 중요한 정보를 부각 시키지는 못했을 때
상대적으로 덜 중요한 정보를 남기고 중요한 정보는 제거함
해석자가 동일하게 공유하는 문맥이 없을 때
중요한 정보의 기준이 다를 수 있음
도메인 영역 별 추상화 기준이 다를 수 있다는 걸 인지 해야함
잘못된 추상화가 야기하는 사이드 이펙트는 생각보다 정말로 크다.
적절한 추상화는 해당 도메인의 문맥 안에서 정말 중요한 핵심 개념만 남겨서 표현 하는 것
📝 추상화의 가장 대표적인 행위
🗒️ 이름을 짓는다
👉 가장 단순하면서도 아주 중요한, 고도의 추상적 사고 행위
단수와 복수를 구분하기
끝에 -(e)s 를 붙여 어떤 데이터가 단수인지, 복수인지 나타내는 것이 읽는이에게 중요한 정보를 전달 할 수 있음
이름 줄이지 않기
축약 할 때 효율성을 얻을 수 있으나 얻는 것에 비해 잃는 것이 큰 경우임
자제하는 것이 좋긴 하나 관용어처럼 많은 사람들이 자주 사용하는 줄임말 정도는 허용함
은어/방어 사용하지 않기
농담에서 파생된 용어나 일부 팀원, 현재 의 우리팀만 아는 용어 금지
새로운 사람이 팀에 합류 했을 때 이 용어를 단번에 이해 할 수 없는 단어는 사용 하지 말아야 함
도메인 용어 사용하기
도메인 용어를 먼저 정의 하는 과정이 필요할 수 있음
예시) 매장 정보 → shop? store?
좋은 코드를 보고 습득하기
비슷한 상황에서 자주 사용하는 단어, 개념 습득하기
예시) pool, candidate, threshold, etc
Example use case:
👎 BAD!
int row = Character.getNumericValue(r) - 1; if (input2.equals("2")) { board[row][col] = "⚑"; boolean open = true; for (int i = 0; i < 8; i++) { for (int j = 0; j < 10; j++) { if (board[i][j].equals("□")) { open = false; } } } }
👍 GOOD!
int selectedRowIndex = Character.getNumericValue(cellInputRow) - 1; if (userActionInput.equals("2")) { board[selectedRowIndex][selectedColIndex] = "⚑"; boolean isAllOpend = true; for (int row = 0; row < 8; row++) { for (int col = 0; col < 10; col++) { if (board[row][col].equals("□")) { isAllOpend = false; } } } }
🙋♂️ 한 메서드의 주제는 반드시 하나다
🧰 메서드 선언(추출)
Example use case:
👎 BAD!
boolean isAllOpend = true; for (int row = 0; row < 8; row++) { for (int col = 0; col < 10; col++) { if (board[row][col].equals("□")) { isAllOpend = false; } } } if (isAllOpend) { gameStatus = 1; }
👍 GOOD!
private static void checkIfGameIsOver() { boolean isAllOpened = isAllCellOpened(); if (isAllOpened) { gameStatus = 1; } } private static boolean isAllCellOpened() { boolean isAllOpened = true; for (int row = 0; row < 8; row++) { for (int col = 0; col < 10; col++) { if (board[row][col].equals("□")) { isAllOpened = false; } } } return isAllOpened; }
💫 같은 패키지 내에서 추상화 레벨 맞추기
Example use case:
👎 BAD!
public static void main(String[] args) { showGameStartComments(); initializeGame(); showBoard(); ... if (gameStatus == 1) { // <- 추상화 레벨이 다른 구문 System.out.println("게임 클리어"); break; } }
👍 GOOD!
public static void main(String[] args) { showGameStartComments(); initializeGame(); showBoard(); ... if (doesUserWinTheGame()) { System.out.println("게임 클리어"); break; } }
🌇 매직 넘버, 매직 스트링을 상수로 추출하기
Example use case:
👎 BAD!
private static String[][] board = new String[8][10]; private static Integer[][] landMineCounts = new Integer[8][10]; private static boolean[][] landMines = new boolean[8][10]; private static int gameStatus = 0;
👍 GOOD!
public static final int BOARD_ROW_SIZE = 8; public static final int BOARD_COL_SIZE = 10; private static final String[][] BOARD = new String[BOARD_ROW_SIZE][BOARD_COL_SIZE]; private static final Integer[][] NEARBY_LAND_MINE_COUNTS = new Integer[BOARD_ROW_SIZE][BOARD_COL_SIZE]; private static final boolean[][] LAND_MINES = new boolean[BOARD_ROW_SIZE][BOARD_COL_SIZE]; public static final int LAND_MINE_COUNT = 10; public static final String FLAG_SIGN = "⚑"; public static final String LAND_MINE_SIGN = "☼"; public static final String CLOSED_CELL_SIGN = "□"; public static final String OPENED_CELL_SIGN = "■";
👉 예시처럼 자주 사용 되거나 의미를 갖고 있는 숫자나 문자를 뜻 함
Last updated