Reference
다음을 참고하여 학습했습니다. 감사드립니다. 🙇🏻♂️
🏀 Goal
지속적인 성장을 목표에 그치지 않고 직접 실천해본다.
🤓 How
- 문제 해결을 통해 요구사항들의 의미와 프로그래밍의 정수가 무엇인지 최대한 음미하고 질문에 도전한다.
- 아는 것/ 알게 된 것 / 몰랐던 것을 정의하고 분리한다.
- 점진적으로 다듬어가며 단순화한다.
- 되도록 개념을 16가지 이하로 줄여본다!
💡 변하지 않는 원칙
핵심 : 관심사의 분리
- Lv .1 함수를 작게 분리
- Lv .2 캡슐화 - 객체 단위에 적용 (외부에 영향을 주는 '공', 내부적인 처리만을 담당하는 '사', 공과 사 분리)
- 접근 제어를 통해 사적인 구현과 공적인 역할을 분리 -> 다른 객체에 영향을 주지 않고 독립적인 구현, (반대로 캡슐화가 잘 안 되면 사소한 변화로 다른 객체가 모두 삐걱거리기 때문)
- Lv .3 단일 책임 원칙
- 객체의 관심사를 분리할 때 "변경 이유"를 기준으로 나누기
- Lv .4 인터페이스 분리 원칙
- '클라이언트(사용하는 객체)' 기준으로 분리
- 인터페이스를 별도의 추상 클래스 or 프로토콜로 정의 (의존성 역전)
- 메시지를 보내는 객체 / 처리하는 인터페이스 서로 의존 -> 인터페이스 입장에서 객체의 구체적 내용을 알 필요가 없어 결합도 낮아짐
- Lv. 5 디자인 패턴 (MVC, MVP, MVVM..) - UI와 비즈니스 로직 분리
- GUI와 데이터/로직은 굉장히 다른 특성과 변경 주기를 가진다.
- -> UI(View), 비즈니스 로직(Model)이 분리
- 어떻게 하면 UI와 비즈니스 로직으로 관심사를 잘 나눌까?에서 다양한 형태가 파생됨
- Lv. 6 레포지토리 패턴: 비즈니스 로직과 데이터 접근 분리
- 데이터 접근 : HTTP 요청 전송, 로컬 데이터베이스 쿼리 전송.. 등등 네트워킹 레이어, Persistence 레이어의 각 활동
- 외부에서 데이터를 가져오는 코드 / 내부 로직을 처리하는 코드의 특성과 변경 주기가 다름
- 비즈니스 로직 / 데이터 접근 분리
- Lv 7 레이어 간 의존성 규칭 : 의존성은 한쪽으로만 흐르도록 분리
- 로버트 C. 마틴 : 이 아키텍처가 동작하기 위한 우선적인 규칙은 소스 코드 종속성이 안쪽으로만 가리킬 수 있다는 것, 내부의 어떤 것도 외부의 무언가에 대해 아무것도 알 수 없다.
- 안쪽 레이어는 바깥쪽 레이어에 대해 전혀 몰라야 한다.
- 레이어를 층층이 분리해놓은 다음, 자기 바로 아래 레이어에만 의존하도록 방향을 한쪽으로 통일한다.
- 역할을 명확하게 분리하고, 코드의 결합도를 낮춘다.
반복하기
관심사의 분리를 상속한 원칙들
- 작은 함수(Small Functions) : '20줄 이하의 한 가지 일'을 기준으로 관심사를 분리
- 캡슐화(Encapsulation) : 인터페이스와 구현을 기준으로 관심사를 분리
- 단일 책임 원칙(SRP) : '변경할 이유'를 기준으로 관심사를 분리
- MVC/MVP/MVVM 패턴 : 'UI'와'비즈니스 로직'을 기준으로 관심사를 분리
- 인터페이스 분리 원칙(ISP) : '클라이언트가 사용하는 범위'를 기준으로 관심사를 분리
- 레포지토리 패턴(Repository Pattern) : '비즈니스 로직'과 데이터 접근'으로 관심사를 분리
- 의존성 규칙(Dependency Rule) : '더 안쪽 레이어에만 의존하도록' 관심사를 분리한다.
관심사의 분리가 친화적인 이유
- 인간의 뇌는 한번에 하나씩밖에 처리하지 못한다.
- 인간은 잘 묶여있는 덩어리(Chunk)를 더 잘 기억한다.
- 협업과 의사소통은 비싸다
🗒️ To-do List
- 단순화 되어 있는 문제들의 기능별 변경 가능성(ex - 입출력.. )을 고려하여 정의한다.
- 변경 가능성이 높은 경우 인터페이스를 사용하고, 그 이외에는 불필요한 복잡도 증가를 고려한다.
- 기능을 정의한 인터페이스를 사용하여 프로그래밍 한다.
- 인터페이스는 최초 설계 단계에서 도출하지 않고, 진행과정에서 발견된 새로운 추상 개념을 통해 점진적으로 도출한다.
- 변경의 유연함을 보장하기 위해 변경 가능서이 높은 기능에서 추상화를 시작하는 것에 도전한다.
- 단위 테스트를 왜 사용하는 것인지, 의미를 음미함으로써 필요성을 깨닫는다.
- 구현할 코드에 대한 테스트 작성 -> 작성한 테스트를 통과하는 코드를 점진적으로 완성
- 자연스럽게 아직 완성하기 힘든 구현때문에 테스트 할 수 없는 경우에 도달
- 테스트 할 수 없는 경우를 별도의 인터페이스로 분리하여 진행
- 분리된 인터페이스는 테스트 대상이 되는 클래스와 구분되는 책임을 가지게 됨 -> 새로운 책임을 갖는 객체를 도출
- 새로운 책임을 갖는 객체를 도출
- OOP 속에서 객체는 각각 알맞은 책임을 할당하고 각 객체가 주고받는 메시지를 정의하는 과정이므로 테스트 주도 개발은 OOP 설계 유도에 좋은 방식임을 알 수 있다. OOP 본질 고민하기
- 이름 짓기의 의미를 고민한다.
- 프로그래밍이란 각 객체를 주고받는 함수들의 연산 과정이라고 가정한다.
- 연산이 되풀이 되는 방법을 간추려 이름을 붙이고, 문제를 해결하는 눈높이에 맞춰진 표현 수단을 곧바로 만들어 쓰기 위해 프로그래밍 언어에 함수를 생성하는 기능이 들어있는 것 아닐까..
- 되풀이 되는 연산을 요약하여 정의하는 것에 집중하고, 문제 해결과정의 표현력을 최대한 끌어올린다.
- 간추리고 요약하는 것은 내부적인 해결 방법을 더 명확하고 훤하게 드러낸다는 것을 깨달을 수 있도록 노력한다.
- 또렷이 계산 방법이 드러나고 쓸모있는 것이 분리되도록 함수를 구현한다.
- 프로그램의 의미를 고민한다.
- 프로그래밍의 공통 특징은 다음과 같다.
- 변수엔 이름이 붙을 수 있다.
- 함수의 인자로 쓸 수 있다.
- 함수의 결과로 만들어 질 수 있다.
- 데이터 구조 속에 집어넣을 수 있다..
- 현실 세계의 복잡한 현상을 컴퓨터 계산으로 흉내내어 연산 도구를 만든다.
- 각 도구들을 조립하고 변수와 함수를 요약하여 정의한다.
- 복잡한 현상들의 성질들을 변수로 치환하여 연산하는 과정을 통해 문제 해결에 적용한다.
- 함수 콘덴트(깊이)를 1로 줄이는 방법을 고민해본다.
- 함수가 한가지만 해야 하는 이유, 왜 짧으면서도 한가지만 하기 위해 함수 분리를 많이 해야하는지에 대해 고민한다.
- 추상화 수준을 각 하나로 일치 시키기 위해 (한 함수 내 추상화 수준을 섞으면 특정 표현이 근본 개념인지 아니면 세부사항인지 구분하기 어렵다.)
- 내려가기 규칙 : 한 함수 다음엔 추상화 수준이 한 단계 낮은 함수 -> 위에서 아래로 ㅡ프로그램을 읽으면 함수 추상화 수준이 한 번에 한 단계씩 낮아진다
- 큰 개념을 다음 추상화 수준에서 여러 단계로 나눠 수행하기 위해
- 의미 있는 이름으로 다른 함수를 추출할 수 있다면 그 함수는 여러 작업을 하는 셈이다.
- 일급 컬렉션이 필요한 이유에 대해 고민하기
- Lotto 클래스를 주의깊게 들여다보기
- 이동욱님 블로그 - 클릭하여 학습하기
- tecoble - 일급 컬렉션
- JAVA Enum 필요한 이유에 대해 고민하기
- 객체간 책임의 분리
- 코드레벨에서 많은 것을 검증과 확인이 가능해야 좀 더 유지보수하기가 쉬울 수 있다? -> enum으로 조금이나마 답답함을 해소할 수 있다면?
- 약속의 jojoldu님
- tecoble
- 객체지향 체조원칙에 대해 고민하기
- 좋은 블로그
- 블로그 샤인
- 단위 테스트 사용해보기
- 역시 jojoldu님
- 테스트 하기 좋은 코드 시리즈
- Junit5 학습기 시리즈
- static 사용 시 생기는 문제에 대해 고민해보기
2주차 피어리뷰 내용 : 무조건 적인 static 선언 보다는 이를 인스턴스 변수, 인스턴스 메서드만으로 바꿔보시면 좋을 거 같아요
1. static 사용 시 문제점
- 관심사를 분리 이유에 대해 고민해보기, 특정한 패턴만이 최선인지까지 고민해보기
- 필요한 부분만 쉽게 수정하는 방법 - MVC는 왜 생겨난걸까?
- MVC의 본질
- 관심사의 분리
- 인간의 뇌는 한번에 하나씩밖에 처리하지 못한다.
- 인간은 잘 묶여있는 덩어리(Chunk)를 더 잘 기억한다.
- 협업과 의사소통은 비싸다
- 피자 두 판의 법칙