Sky Archive

교육/Clean Code

[Clean Code] 클린 코드 'Chapter 3. 함수' 핵심 내용 및 정리

Anchovy ʕ-᷅ᴥ-᷄ʔ 2022. 12. 22. 16:06

도서 목차

Chapter 1. 깨끗한 코드
Chapter 2. 의미 있는 이름

 

Chapter 3. 함수

(p39 ~ 66)

 

Chapter 4. 주석

Chapter 5. 형식 맞추기

Chapter 6. 객체와 자료 구조

Chapter 7. 오류 처리

Chapter 8. 경계

Chapter 9. 단위 테스트

Chapter 10. 클래스

Chapter 11. 시스템

Chapter 12. 창발성

Chapter 13. 동시성

Chapter 14. 점진적인 개선

Chapter 15. JUnit 들여다보기

Chapter 16. SerialDate 리팩터링

Chapter 17. 냄새와 휴리스틱

 

강의 목차

함수를 안전하고 간결하게 작성하기

01 SOLID
02 간결한 함수 작성하기
03 안전한 함수 작성하기
04 함수 리팩터링

 

01 SOLID

SOLID 원칙

• SRP 단일 책임 원칙
• OCP 개방-폐쇄 원칙
• LSP 리스코프 치환 원칙
• ISP 인터페이스 분리 원칙
• DIP 의존성 역전 원칙

 

SRP (단일 책임 원칙)
한 클래스는 하나의 책임만 가져야 한다.

• 클래스는 하나의 기능만 가지며, 어떤 변화에 의해 클래스를 변경해야 하는 이유는 오직 하나만
• SRP 책임이 분명해지기 때문에, 변경에 의한 연쇄작용에서 자유로움
• 가독성 향상과 유지보수 가용이

 

OCP (개방-폐쇄 원칙)

소프트웨어 요소는 확장에는 열려있으나 변경에는 닫혀있어야 한다.

• 변경을 위한 비용은 가능한 줄이고, 확장을 위한 비용은 가능한 극대화 해야 한다.
• 요구사항의 변경이 나 추가사항이 발생하더라도, 기존 구성요소에는 수정이 일어나지 않고, 기존 구성요소를 쉽게 확장해서 재사용한다.
• 객체지향의 추상화와 다형성을 활용한다.

 

LSP (리스코프 치환 원칙)
서브타입은 언제나 기반 타입으로 교체할 수 있어야 한다.

• 서브타입은 기반 타입이 약속한 규약(접근 제한자, 예외 포함)을 지켜야 한다.
• 클래스 상속, 인터페이스 상속을 이용해 확장성을 획득한다.
• 다형성과 확장성을 극대화하기 위해 인터페이스를 사용하는 것이 더 좋다.
• 합성(composition)을 이용할 수도 있다.

 

ISP (인터페이스 분리 원칙)

자신이 사용하지 않는 인터페이스는 구현하지 말아야 한다.

• 가능한 최소한의 인터페이스만 구현한다.
• 만약 어떤 클래스를 이용하는 클라이언트가 여러 개고, 이 클라이언트들이 클래스의 특정 부분만 이용한다면, 여러 인터페이스로 분류하여 클라이언트가 필요한 기능만 전달한다.
• SRP가 클래스의 단일 책임이라면, ISP는 인터페이스의 단일 책임

 

DIP (의존성 역전 원칙)

상위 모델은 하위 모델에 의존하면 안 된다. 둘 다 추상화에 의존해야 한다.
추상화는 세부사항에 의존해서는 안 된다. 세부사항은 추상화에 따라 달라진다.

• 하위 모델의 변경이 상위 모듈의 변경을 요구하는 위계관계를 끊는다.
• 실제 사용관계는 그대로이지만, 추상화를 매개로 메시지를 주고받으면서 관계를 느슨하게 만든다.

 

확장에 유연하지 않음. (새로운 카드사 추가)

 

그렇기에 둘 다 추상화된 인터페이스에 의존하도록 한다.

 

02 간결한 함수 작성하기

함수가 길고, 여러 가지 기능이 섞여있다. // Bad

 

함수를 작게 쪼개고 함수 내 추상화 수준을 동일하게 맞춘다. // Good

 

- 한 가지만 하기 (SRP), 변경에는 닫히게 만들기 (OCP)

 

두 가지 기능이 존재 (계산, Money 생성) // Bad

또한 새로운 직원 타입 추가 시 변경이 어려움.

 

계산과 타입 관리를 분리 // Good

타입에 대한 처리는 최대한 Factory에서만 한다.

 

- 함수 인수
인수의 개수는 0~2개가 적당
3개 이상인 경우에는 인자를 줄이는 형태로 변경한다.

// 객체를 인자로 넘기기
Circle makeCircle(double x, double y, double radius); // Bad
Circle makeCircle(Point center, double radius); // Good

// 가변 인자를 넘기기 -> 특별한 경우
String.format(String format, Object… args);

 

03 안전한 함수 작성하기

부수효과(Side Effect) 없는 함수
(Side Effect : 값을 반환하는 함수가 외부 상태를 변경)

함수와 관계없는 외부 상태를 변경시킨다. // Bad

 

04 함수 리팩터링

기능은 같으나 코드의 가독성 향상, 성능을 개선

함수의 정상적으로 동작한다는 전제하에 리팩터링을 해야 하기 때문에 테스트 코드 또한 중요하다.

 

리팩터링 과정

1. 기능을 구현하는 서툰 함수를 작성한다.
길고, 복잡하고, 중복이 존재한다.

2. 테스트 코드를 작성한다.
함수 내부의 분기와 엣지 값마다 테스트하는 코드를 작성한다.

3. 리팩터링 한다.
코드를 다듬고, 함수를 쪼개고, 이름을 바꾸고, 중복을 제거한다.

 

 

 

 

 

 

 

 

 

 

ref.

SOLID design principles https://medium.com/bgl-tech/what-are-the-solid-design-principles-c61feff33685