[Readable Code: 읽기 좋은 코드를 작성하는 사고법 회고 1주차
출처 : Readable Code: 읽기 좋은 코드를 작성하는 사고법 / 박우빈
1. 회고
저자께서 회고 방식에 대한 아티클을 소개해주셨고 KPT로 진행 후 주차별로 다른 회고 방식을 적용해보려고 합니다.
Keep(만족했고 지속할 부분)
단순히 따라치는 수준에 그치더라도 직접 코드 작성
미션 전 수강 내용 훑어보고 진행하기
Problem(부정적 또는 아쉬웠던 부분)
강의 수강 전에 목표 달성 실패
목표 : 코드 분석 및 수강 전 리팩토링한 코드와 수강 후 리팩토링된 코드 비교
실제 : 코드 분석은 했으나 리팩토링까지는 진행하지 못함
Trying(Problem 해결 방식으로 다음에 시도해볼 점)
목표 설정 후 시간제한 두기
시간제한 없이 루즈하게 진행하여 목표 달성도 실패했고, 결과물도 만족스럽지 못함
2. 학습 내용 요약
추상(섹션1~2)
이름짓기
단복수에 의미 부여
줄임말 사용하지 않기
도메인 언어 사용(유행어, 은어, 방언 금지)
좋은 코드 보고 습득
필드 이름은 추상화하지 않음
메서드명은 내부 처리 내용을 추상화
메서드 선언부
메서드 선언부 : 반환타입 + 메서드명 + 파라미터
메서드 시그니처 : 메서드명 + 파라미터
반환타입에 대한 고민 : 반환할만한 값이 있는지? boolean이라면 true/false가 무엇을 의미할지?
파라미터가 날짜 형태라면 String 형태보다는 LocalDate가 적절해보임
전치사 잘 활용하기
메서드 내에서 동일한 추상화 레벨로 묶여야함
매직넘버 / 매직스트링 : 상수로 추출되지 않은 숫자나 문자 -> 리팩토링할 때 실제 의미가 같은 데이터만 변경했는지 확인 필요
논리, 사고의 흐름
Early Return
if(){}
else if(){}
else{}
구조 보다는 개별 if문과 return 사용(if의 조건을 else 까지 기억하기 어려움)
사고의 depth 줄이기
중첩 분기문 / 중첩 반복문
코드 분석이 어렵다면 depth 1로 줄이는 것 고려, 그러나 모든 것을 메서드로 추출하면 오히려 가독성이 떨어질 수 있음
사용할 변수는 가깝게 선언하기
공백 라인을 대하는 자세
비슷한 역할단위로 끊어주기
부정어를 대하는 자세
!isLeft
=> isRight, isNotLeft ( 부정 연산자 !의 가독성이 떨어짐)
해피 케이스와 예외 처리
예외 발생 가능성 낮추기 - 외부와의 접점
의도한 예외와 예상치 못한 예외 구분
return null 자제,
Optional 사용 고려(단, Optional은 비싼 객체이므로 꼭 필요한 경우에만 사용)
Optional을 파라미터로 받는 것은 안티패턴(Optional이 가진 데이터 null, optional null)
Optional 해소 - isPresent().orElseGet(), orElseThrow(), ifPresent(), ifPresentOrElse() 사용
++ orElse(), orElseGet(), orElseThrow() 차이 숙지
객체 지향 패러다임(섹션4)
객체지향 설계
객체와 외부 세계는 공개 메서드로 소통함
책임 분리
1개의 관심사로 명확하게 책임 정의
setter 사용 자제
객체에서 데이터를 꺼내어(getter) 분기처리하는 것이 아니라 공개 메서드에 필요한 정보를 입력하고 true/false 확인
필드 수는 적을 수록 좋음 (totalPrice 같은 것은 성능상 이유가 아니라면 필요할 때마다 계산하여 반환
SOLID
SRP
하나의 클래스는 하나의 변경 이유(책임)만 가져야 한다
OCP
확장에는 열려있고 수정에는 닫혀있다 -> 기존 코드 변경 없이 시스템 기능 확장
LSP
부모 클래스가 자식 클래스를 완전히 대체할 수 있어야한다.
자식 클래스끼리 호환되지 않는 기능은 부모 클래스에서 제외
ISP
사용하지 않는 인터페이스에 의존하면 안됨(3개 중 2개는 쓰는데 1개는 사용하지 않는 경우 인터페이스를 분리해야함)
DIP
의존성의 순방향 : 고수준 모듈이 저수준 모듈 참조
의존성의 역방향 : 고수준(고추상), 저수준(저추상) 모듈 모두 추상화에 의존
구현체에 의존하는 것이 아니라 구현체의 추상(인터페이스)에 의존
++ 참고
DIP(Dependency Inversion Principle)
DI(Dependency Injection) - "3" 제 3자가 의존성 주입
IoC(Inversion of Control)
객체지향 적용하기(섹션5)
상속과 조합
상속보다는 조합
상속은 결합도가 높음
인터페이스 활용
부모의 필드를 직접 참조하지 않는 것이 좋음
Value Object
도메인의 특정 개념을 추상화하여 표현한 객체
불변성(final), 동등성(equals(), hashCode() 등, 내부 값이 같으면 같은 객체 취급), 유효성 검증(객체 생성 시점) 등 보장 필요
++ VS Entity
Entity
단일 필드 식별자
식별자만 같으면 다른 필드 값이 달라도 동등한 객체 취급
VO
전체 필드가 식별자
모든 필드가 같아야 동등한 객체취급
일급 컬렉션
일급시민(ex 함수)
변수로 할당 가능
파라미터로 전달 가능
함수의 결과로 반환 가능
일급 컬렉션
컬렉션만을 유일하게 필드로 가지는 객체
컬렉션을 객체와 동등한 레벨로 다루기 위함
단 하나의 컬렉션 필드만 가짐
가공 로직 및 테스트 작성 가능
반환할 때는 getter로 객체 주소를 반환하는 것이 아니라 새로운 컬렉션을 반환해야함
Enum의 특성과 활용
상수와 상수 관련 로직 집합
도메인 개념과 기능 명시 가능
변경이 잦은 개념은 DB로 관리
다형성 활용하기
OCP
조건을 만족하는가?
만족하면 행위 수행
숨겨져 있는 도메인 개념 도출하기
도메인 지식은 발견하는 것
객체지향은 현실을 흉내내는 것
현실에서 인지하기 어려운 개념도 도출해서 사용할 때가 있음
설계할 때는 최대한 미래를 예측해서 진행하고 틀렸을 때 언제든 돌아올 수 있도록 코드를 만들어야함
댓글을 작성해보세요.