본문 바로가기
📝 회고/✅ 22년 회고

[일일 회고] 22.02.14~15 - 좋은 코드와 Git

by kukim 2022. 2. 15.

이번 주부터 코드 스쿼드 백엔드 과정이 본격적으로 시작됐다. 프로젝트 공개도 가능하다. 이번주는 간단하게 사다리 게임을 구현한다. 객체지향, 단위 테스트, 리팩토링을 한다. 총 5단계로 이루어져 있으며 하루에 1단계씩 진행한다. 어제오늘 2단계까지 진행했다. (프로젝트 링크 : Step2 Code) 과정 속에서 좋은 코드 조각과 Git에 배울 수 있었다.

 

좋은 코드 조각

작년🧘🏻‍♂️ 유지 보수하기 좋은 코드, 앞으로의 수련 를 통해 생각을 정리했다. 좋은 소프트웨어, 코드를 만드는 개발자가 되고 싶었고 같은 생각을 가지고 있는 동료를 만나고 싶었다. 우연히 '코드 스쿼드'를 알게 되었고 현재 이곳에서 공부하고 있다.

좋은 코드는 무엇일까? 정답은 없다고 생각한다. 주어진 상황에 따라 다를 수 있으며 주관적이다. 하지만 상황에 따른 고민이 쌓일수록 좋은 코드를 작성할 수 있다고 생각한다. 코드 스쿼드를 시작하며 그 조각들을 모으고 있다.

 

✅  생성자 vs 정적 팩토리 메서드

이펙티브 자바 item 1을 공부한 후 연습을 위해 의도적으로 생성자 대신 정적 팩토리 메서드를 사용하고 있다. 과연 이게 옳은 것일까?

public class Ladder {

    private Ladder() {
    }
    
    public static Ladder create(int playerCount, int ladderMaxHeight) {
        Ladder ladder = new Ladder();
        ladder.playerCount = playerCount;
        ladder.ladderMaxHeight = ladderMaxHeight;
        ladder.lines = new int[ladderMaxHeight][playerCount];
        return ladder;
    }

    public static void main(String[] args) {
        Ladder ladder = Ladder.create(playerCount, ladderMaxHeight);
    }
}

🧐 생각

현재 프로젝트에서 Ladder 클래스의 발전 가능성은 적다. 다시 말해 동일한 매개변수로 들어오는 생성자가 더 필요하지 않을 수 있다.

단순히 생성자만으로도 좋을 수 있다. 하지만 정적 팩토리 메서드를 작성했다. 그 이유는 혹시 모를 프로젝트 발전 가능성을 두었다. 아쉬운 점은 팩터리 메서드라고 설명하는 주석(자바독)이 없었다. 메서드 이름도 create() 대신 createWithPlayerAndLadderCount()는 어떨까 생각해본다. 너무 길려나?

 

✅  Utils 관련 class는 static으로 만들어야 할까 의존성 주입을 해야 할까?

사용자 입력을 담당할 InputView, 사용자 출력을 담당할 OutputView가 있었다. Step2 구현 사항은 static으로 만들었다. 그 이유는 코드 작성 시 가독성을 위해서였다. 매번 InputView나 OutputView 객체를 생성하고 사용하기 힘들었다.

🧐 생각

Utils 관련 클래스는 static으로 좋아 보인다. 왜냐하면 자주 사용되기 때문에 메모리 상에서도 이점을 가질 수 있다. 또한 Util 클래스는 상태(정보)가 없기 때문에 static해도 문제가 없다는 것이다.(동료 Ader의 말)

 

✅  박싱 타입과 기본 타입을 적재적소에 사용하자

자바 박싱 타입(Integer, Character, Float...)은 컬렉션의 원소, 키 값이나 제네릭, 리플렉션을 통한 메서드 호출할 때 사용한다.

그 외의 변수나 연산은 기본 타입 int, char, float... 을 사용하는 것이 좋다.

🧐 생각

이 내용은 이펙티브 자바 item 61에도 있는 내용이다. 박싱 타입은 null이 가능하지만 문제가 있다.

박싱 타입의 문제는 메모리 비효율 적이고 기본 타입 + 박싱 타입 혼용 연산 시 박싱 타입의 박싱이 풀린다. 만약 이때 박싱 타입이 null이라면 NullPointException이 발생한다. 정말 자주 일어나는 일 같다.

 

✅  표준 입력을 사용했고 더 이상 사용하지 않는다면 닫아주자

사용자 입력을 위해 표준 입력, Scanner(system.in) 해주었다. 입력이 더 이상 없을 때는 scanner.close()로 닫아주자. 

 

✅  IntelliJ의 메서드 자동 생성 시 접근 제어자 주의

접근 제어자를 항상 조심하자. 나는 보통 메서드나 클래스 생성 시 해당 메서드, 클래스 사용하는 곳에 구현되지 않은 것을 먼저 작성하고 옵션 + 엔터 단축키를 사용해 생성한다. 오늘은 테스트 용도로 main문을 내부에 만들고 메서드를 만들었는데 main문이 클래스 안에 있다 보니 public 되어야 할 메서드가 private로 만들어졌다. 이를 제대로 확인하지 않았다. 항상 주의하자

 

✅  디자인 패턴을 이론보다 몸으로 경험하자

디자인 패턴 틀에 박혀 설계 고민에 빠지는 것보다 어떻게 쪼개고 좋을지 고민하고 코드를 작성해보자. 그렇다 보면 자연스럽게 패턴이 나오지 않을까?

 

✅  복잡한 조건문이나 계산식은 메서드나 변수는 추출하자

너무 복잡한 조건이나 계산식은 추출하여 사용하자

if (lines[col_i] == 1 && lines[col_i + 1] == 1)
// -> 메서드 추출
if (isRadder(col_i, lines[row_i]))
private static boolean isRadder(int col_i, int[] lines) {
	return lines[col_i] == 1 && lines[col_i + 1] == 1;
}


height * 2 - 1
// -> 변수 추출로
line = height * 2 - 1

 

 

Git

환경

upstream (원본) 저장소의 ku-kim 브랜치

upstream을 fork 뜬 origin 저장소의 ku-kim 브랜치

 

상황 : origin 저장소를 clone 받았다. origin의 ku-kim 브랜치에서 step1 브랜치를 생성했다. 많은 것을 작업하고 git push origin ku-kim 했고 upstream으로 PR을 보냈다. PR 리뷰받기 전 step 2 진행을 하고 싶어 step1위에서 step 2 브랜치 생성하여 작업했다. 그러던 중 PR 리뷰가 끝나고 머지가 되었다. 로컬 저장소에서 upstream의 머지 커밋을 업데이트하고 머지 커밋 위에서 이전의 작업 중이던 step 2 내용을 시작하고 싶다. 이때 step2 브랜치를 upstream/ku-kim으로 rebase 했다. 충돌을 해결하여 작업을 진행할 수 있었다.


👍 Keep

- 문제가 발생했을 때 내가 현재 무엇을 모르는지 점검하고 해당 내용을 작고 빠르게 테스트하며 문제를 해결했다.

- 도움이 필요한 동료들에게 설명해주었다.

- 그룹 리뷰 시간에 서로 알고 있는 것을 나누고 토론했다.

 

🔥Problem

- 아침 늦잠

- 온전히 집중한 시간이 적음 (주위 산만)

- 여러 동료들의 질문이 반복된다.

🚒 Try

- 아침에 일어나기 힘드니 일찍 잠들어야겠다.

- 뽀모도로 시계를 활용해서 30분 씩이라도 완전히 집중할 수 있는 시간을 만들자.

- 반복되는 질문이나 이슈가 있을 때 문서화하여 공유해야겠다.

댓글