- 묻지 말고 시켜라 (tell don`t Ask)
- 메서드 인자로 넘어온 값을 변경하지 마라
- 커맨드와 쿼리를 분리하라
- PR 단위는 하루를 넘어가지 않도록 한다.
- One Goal One Method (하나의 메서드는 하나의 관심사만 가져야 한다)
- import가 제대로 되어 있는가
- How가 아닌 What이 드러나는가
- 물어보지 않고 시키는가(tell don’t ask)
- 캡슐화가 깨지지 않았는가
- CQS가 지켜지는가
- 추상화 수준이 적절한가
- 주석이 적절하게 작성되어 있는가
- 변경의 범위가 너무 크지 않은가
- 커밋은 15개를 넘기지 않는가
- 변경된 파일의 라인이 150줄을 넘지 않는가
- 메소드 인자로 넘어온 값이 변경되지 않는가
- 하나의 메소드가 한가지의 관심사만을 가지고 있는가
- 코드에 중복이 있는가
- import된 패키지의 의존성에 어색한 부분이 없는지 확인.
- 네이밍이 이상하지 않은가
- 추상화 수준이 적절한가
- Command와 Query가 잘 분리되어 있는가
- 조회-액션-저장 구조로 동작하는가
- 설계 의도 파악하기
- Rename - 변수나 메서드의 이름을 명확하게 변경하여 코드의 가독성을 높입니다.
- Comment - 중요한 부분이나 복잡한 로직에 주석을 추가하여 이해를 돕습니다.
- final 추가 - 변경되지 않는 변수나 메서드에 final 키워드를 추가하여 불변성을 보장합니다.
- Slide Statement - 관련 있는 코드를 가까이 배치하여 코드의 흐름을 개선합니다.
- Reorder - 메서드나 클래스를 논리적인 순서로 재배치하여 가독성을 높입니다
- Introduce Parameter Object - 관련된 여러개의 파라미터를 하나의 객체로 묶어 코드의 복잡성을 줄입니다
- Extract Method - 중복되거나 긴 코드를 별도의 메서드로 분리하여 재사용성을 높입니다.
- Extract Delegate - 특정 기능을 별도의 클래스나 모듈로 분리하여 책임을 분산시킵니다.
- 읽기 어려운 코드에 대해 왜 이해하기 어려운지, 이유를 설명하는것보다 코드를 바꾸는 편이 났다.
- 커뮤니케이션이 최우선 가치. 단순성은 독자에따라 복잡해보일 수 있다. 때로는 단순성을 포기하더라도 커뮤니케이션을 선택해야한다.
- 유연성은 비효율적인 코딩이나 설계를 정당화해주는 가치이다. 유연성이 있으면서 당장 이득을 얻을 수 있는 패턴을 사용하라. 당장 비용이 들지만 앞으로 이득을 얻을 수 있을지 확실하지 않은 경우에는 일단 자제하라. 정말 필요할떄 적용(YAGNI). 유연성은 복잡도를 증가시킨다.
- 가능성이지 꼭 그렇다는 건 아님. 언제나 예외는 존재.
- 애플리케이션 서비스의 역할은 의존성 간의 오케스트레이션 담당, 도메인 로직이 애플리케이션 서비스에서 여러 번 호출된다면 캡슐화가 깨지지 않았는지 의심해봐야 한다.
- DB 테이블에 nullable한 컬럼을 계속 추가하는 것과 같을 수도 있음.
- nullable한 컬럼은 코어 테이블과 곁가지 테이블로 분리해야 한다는 신호일지도.
- Test List(Todo List)를 만들어 놓고 TDD 사이클을 진행해야 의도한대로 개발할 수 있다.
- 그렇지 않으면 되는 대로 개발할 가능성이 높아진다.
- fail fast와도 결이 같다. -> 코드를 작성하지 않아도 Test List를 작성하면서 러프하게 분석이 진행될 수 있음
- 출력 기반 테스트를 하기 위해서는 상태를 변경하지 않고 값을 반환하는 방식으로 함수형 스타일로 코드를 작성해야 한다.
- 비즈니스 로직을 처리하는 코드와 부작용을 일으키는 코드를 분리하는 것(Functional Core)이 함수형 프로그래밍의 목표다.
- 어떻게? 부작용을 비즈니스 연산 끝으로 몰아 비즈니스 로직을 부작용과 분리한다(빵 - 속 - 빵)
- 다만 은총알은 없기에 함수형 방식의 순수성에 많은 비용이 든다면 따르지 말라.
- 항상 출력 기반 테스트에만 의존할 수는 없는 법.
- 목표는 모든 테스트를 출력 기반으로 만드는 것이 아닌 가능한 많은 테스트를 전환하는 것이다.
- 절차적 프로그래밍 -> cohesion(응집도) 확인 후 슬라이드 스테이트먼트(Slide Statement) -> 리오더(Reorder, 읽기 좋은 순으로) -> Extract Method
- 레거시 쿼리 중 일부 컬럼을 애플리케이션 로직으로 전활할 때는 해당 쿼리를 크게 변경하거나 지우는 것보다 -9와 같은 상수값을 반환하도록 대체한 뒤 애플리케이션에서 계산한 값으로 덮어씌운다.
- ex) 운영: 기준을 4000에서 4100으로 변경 배포 부탁드립니다.
- 이런 경우 DB에서 관리할 경우 매번 배포하지 않아도 됨.
- 컴포넌트의 퍼블릭 메소드가 옵셔널이라면 클래스를 분리해야 할 징조일까? 책임이 너무 많은가?
- 클래스의 퍼블릭메서드 a에서 a 필드만 쓰이고 b 메서드에서 b만 쓰인다면 클래스를 분리해야할 징조?
before
Order {
orderCustomerName
orderCustomerEmail
orderCustomerPhone
}
after
Order {
orderCustomer
}
OrderCustomer {
name
email
phone
}
- 책임이 너무 크거나 혹은 역할 분담이 제대로 안 되어 있을 수도 있지 않을까 의심을?
- 마찬가지로 퍼블릭 메서드 하나에 private 메소드가 5개가 넘어가면 ..?
- 지금 요구사항은 0과 1만 있을수 있지만 2,3이 언제든 추가될 수 있다. 하지만 boolean으로 고정해놓으면 대응하기 어렵다.
- DB에 enum이 그대로 입력되어있으면 DB와 도메인 모델의 결합도가 높아진다.
- 더 좋은 이름이 생각나서 enum을 리팩터링하고 싶어도 DB에 결합되어 있어서 리팩터링이 어려워진다.
- 1, 2, 3안에 대해서 제안하고 트레이드오프를 고려해서 적용하면 당장 도입을 못하더라도 도입하기 쉬운 구조로 만들 수 있다. 때가 되면 바로 도입할 수 있다.
- 무엇을 하기 전에 사용량과 효용을 생각해보자
- ex) 유료 서비스로 욕설 필터링을 추가함.
- 그전에 해야 할 것은 현재 욕설이 얼마나 쓰이고 있는지를 파악.
- 욕설이 쓰이지 않는데 욕설필터링을 돈주고 사용해야 하는 것은 맞지 않음.
- 빈도를 체크하기 전에 로깅이 선행되어야 함.(비중을 알기 위해)
- 기대 효과가 있어야 설득력이 있음. 무언가 하기 전에 빈도를 체크하는건 중요하다.
- 예시) 백엔드에서만 어떻게든 해결하려고 함.
- 깊게 파고들어서 원인을 파악하고 매우 어려운 방법으로 문제를 해결해냄 (스스로 우물에 들어간다)
- 우물의 물을 마시기 위해 어떻게 내려가야 할지, 내려가서 어떻게 해야 할지, 어떻게 올라와야 할지 등등.
- 시니어는 다른 방법을 찾아서 더 쉽게 해결한다. 시야가 넓다.
- 예시) 프론트에서 더 쉽게 해결하거나 인프라 수준에서 더 쉽게 해결할 수 있는지 혹은 운영으로 풀 수 있는지 다각도에서 검토.
- 우물에 물이 있는지, 마실 수 있는지를 확인. 직접 내려가지 않고 도구를 이용.
- 신호일 수는 있지만 꼭 하는것이 좋은것만은 아닐수도 있다.
- 작게 여러 개로 쪼갠 문제를 맥락을 이해할 수 있게 만들어야 한다.
- 작아도 맥락을 충분히 이해할 수 있도록 하기 위해서는 Outside-In이 좋을지도.