컴파일러, 인터프리터, VM이 이해할 수 있는 코드는 누구나 짤 수 있다. 하지만 사람이 이해할 수 있는 코드는 잘 교육된 SW 엔지니어만 짤 수 있다.
현실은 빠르게 만들어야 해서 TDD, 리팩토링, 코드 리뷰도 안한다. 나중에 한다고 말만 하고 안한다.
대부분의 버그는 버그를 수정하다 나온다. 코드 1줄 수정하면 3줄에서 버그가 발생한다.
프로젝트 완료가 다가올 수록 수정하는 데 자원이 많이 든다. 클린 아키텍처를 이용하면 처음에는 시간이 좀 걸릴지라도 나중에 자원을 아끼게 된다.
내가 구현하려는 것을 대략적으로라도 종이, 화이트보드에 그려봐야 한다.
1. Why Clean Code
- SW는 한번 작성되면 10번 이상 읽힌다. 나뿐만 아니라 다른 사람들도 보기 편하도록 작성해야 한다.
- 인간이 이해할 수 있는 코드는 잘 훈련된 SW 엔지니어만이 작성할 수 있다.
2. Why OOP
- 절차 지향은 데이터를 공유하기 때문에 변경 사항이 생기면 줄줄이 영향을 미친다. 영향을 주지 않기 위해 비슷한 함수를 복붙하게 되면 나중에 변경이 필요할 때 비효율적이다.
- 객체 지향은 기능은 객체에 매핑을 한다. 데이터 변경이 있으면 해당 데이터가 속해 있는 객체에만 영향이 있다. 객체 간 구체적 내용을 알 수 없도록 interface를 사용해야 한다. 데이터, 코드가 encapsulated 된다. 객체간 결합도(coupling)는 낮게, 각 객체의 응집도(cohesion)는 높게.
- 객체 지향이 좋은 방식임에도 절차 지향이 편하고, 객체 지향적으로 생각하는 사람이 별로 없기 때문에 제대로 쓰이지 못한다.
- 절차 지향적으로 더럽게 만들고 refactoring(기능, 동작은 그대로. 구조는 개선)을 통해 객체 지향적으로.
코드 짤 때는 추후 내 코드를 볼 사람이 날 죽일 수 있을 만한 싸이코라고 가정하고 '잘' 짜야 한다.- 한번 쓰이고 유지보수가 필요 없는 것은 절차 지향적으로 해도 된다.
- 절차지향이 처음에는 쉽지만 시간이 지나면 수정하기 어려운 구조다.
3. Object / Role / Responsibility
- 객체/클래스 이름은 어떻게가 아닌 무엇으로 정의해야 한다. RequestParse(O), JsonRequestParser(X). Json이었다가 XML로 바뀐다면 이 객체를 참조한 모든 곳에서 수정이 일어난다.
- 역할은 관련된 책임의 집합
- 객체는 역할을 가짐
4. 객체지향 설계 과정
- 기능을 제공할 객체 후보 선별
- 내부에서 필요한 데이터 선별
- 클래스 다이어그램
- 정적 설계
- 객체 간 메시지 흐름 연결
- 커뮤니케이션 다이어그램
- 시퀀스 다이어그램
- 동적 설계
- 1, 2 반복
ex) 파일 암호화 예
1. 기능을 제공할 객체 후보 선별
2. 객체 간 메시지 흐름 연결
FileReader, Encrypter, FileWriter를 조합해서 FlowController라는 비즈니스 로직을 처리한다.
5. Encapsulation
- 내부적으로 어떻게 구현했는지를 감춰 내부의 변경(데이터, 코드)으로 인해 client가 변경되지 않도록 한다. 코드 변경에 따른 비용 최소화
- 절차 지향 vs 객체 지향
- 절차 지향은 요구사항 변경이 데이터 구조 변경을 유발한다
- 객체 지향은 절차 지향에 비해 변경이 적고 클라이언트에 영향을 안 미친다
- Tell, Don't Ask
- 데이터를 요청해서 변경하고 저장하라고 하지 말고 기능을 실행하라
- Command vs Query
- Command (tell)
- 객체의 내부 상태 변경
- 결과를 반환할 수 있다.
- Query (ask)
- 객체의 내부 상태에 대한 정보 제공
- 객체의 상태를 변경하지 않는다.
- side effects에서 자유롭다.
- 해당 객체의 외부에서 의사결정에 사용하지 않는다면 객체의 상태를 얻을 수 있다.(?)
- 해당 객체의 상태에 기반한 결정은 반드시 객체 내에서 이뤄져야 한다.
- tell, don't ask를 잘 지키게 해준다.
- Command (tell)
6. Polymorphism
- 한 객체가 여러가지 모습/타입을 가질 수 있다
- 상속을 통해 다형성 구현
- 구현 상속
- 수퍼 타입의 구현을 재사용
- 인터페이스 상속(부모 클래스를 상속 받아 거기 있는 메서드를 쓰면 안되나?? 굳이 implement를 해야 하나??가 아니다. 객체 간 결합이 느슨해진다. 컨트롤러가 인터페이스를 통해 인터페이스 구현체와 연결하면 이후 다른 인터페이스 구현체로 변경이나 확장이 용이하다. 즉 인터페이스 구현체가 변경돼도 컨트롤러엔 영향이 없다. 테스트가 쉬워진다. decorator를 활용하기 쉽다.)
- 타입 정의만 상속
- 상속은 객체에게 다형성을 제공
- 구현 상속
출처 https://www.youtube.com/watch?v=60lLSe1phks&list=PLuLb6MC4SOvXCRePHrb4e-EYadjZ9KHyH&index=1
'클린 코드' 카테고리의 다른 글
클린 코드 function structure 2 (0) | 2019.12.10 |
---|---|
클린 코드 function structure (0) | 2019.12.10 |
클린 코드 function 2 (0) | 2019.12.10 |
클린 코드 function (0) | 2019.12.10 |
클린 코드 OOP 2 (0) | 2019.12.10 |