Clean Code
안녕하세요ㅎㅎ
다시 클린 코드로 찾아뵙게 되었습니다~!
짝짝짝
소개글은 한번씩들 정독하셨나요?
요약하자면, Clean Code는 Code Style의 결정체이자 개발 문화라고 생각합니다!
오늘은 함수에 관한 이야기를 할까해요
함수 = 메서드
프로그래머라면 코딩을 할 때 절대로 빼먹을 수 없는 요소죠!
main함수 안에 멍청하게 모든 것을 넣는 바보는 없겠죠.?
클린 코드 서적에서는 함수에 대해 어떻게 설명할까요?
시작해봅시다!!
함수는 한가지 일만
함수가 한가지 일만 한다는게 무슨 의미일까요?
내가 작성한 함수는 잘 돌아가는데..
아무런 잘못이 없는데?
내가 왜 고쳐야해?
같은 생각이 드시는 분들도 많을 것 같아요
함수는 최대한 작게 쪼개야 합니다
딱 한가지 일만 수행하게 하는 것이죠
Why??
앞선 게시글에도 있지만, 우리가 작성한 코드는 절대로 그 상태로 끝나지 않아요
소비자들의 요구 혹은 설계의 변화에 있어서 다시 수정해야될 시기가 반드시 옵니다
근데 한가지 함수에 너무 많은 일이 담겨져 있으면 어떻게 될까요?
내가 원하는 부분을 고치기가 힘들어집니다..
한마디로 전부 뜯어고쳐야 된다는 거에요
한번 예시를 봐볼게요~!
package cleancode.method;
import com.google.common.base.Strings;
public class Smartphone {
private static long REBOOT_TIME = 1_000L;
private String name;
private double version;
private boolean powerOff;
public Smartphone(final String name) {
this.name = Strings.nullToEmpty(name);
this.version = 1.0;
this.powerOff = true;
}
public void versionUpdate(final double version) {
if (powerOff) {
throw new IllegalStateException("핸드폰 전원이 꺼져있습니다.");
}
powerOff = true;
try {
Thread.sleep(REBOOT_TIME);
} catch (InterruptedException e) {
System.err.println(e.getMessage());
}
powerOff = false;
this.version = version;
}
}
스마트폰을 update하는 메서드가 있다고 가정해볼까요?
- 스마트폰 전원이 꺼져 있으면 업데이트가 불가능하므로 예외를 던집니다
- 전원을 껏다가
- 다시 켜서
- 버전을 업그레이드 하고 받은 패키지들을 설치합니다
라는 과정으로 되어 있습니다!
하지만 저 함수는 분명 문제가 있습니다
무슨 문제일까요?
너무 많은 일을 하고 있습니다
만약 스마트폰을 업데이트 하는데,
더 이상 재부팅 과정이 필요하지 않다면 어떻게 될까요?
다른 개발자가 직접 찾아서 수정해야 되는 귀찮음을 감수해야겠네요
그래서 리팩토링합시다
package cleancode.method;
import com.google.common.base.Strings;
public class Smartphone {
private static long REBOOT_TIME = 1_000L;
private String name;
private double version;
private boolean powerOff;
public Smartphone(final String name) {
this.name = Strings.nullToEmpty(name);
this.version = 1.0;
this.powerOff = true;
}
public void versionUpdate(final double version) {
if (powerOff) {
throw new IllegalStateException("핸드폰 전원이 꺼져있습니다.");
}
reboot();
this.version = version;
}
private void reboot() {
powerOff = true;
try {
Thread.sleep(REBOOT_TIME);
} catch (InterruptedException e) {
System.err.println(e.getMessage());
}
powerOff = false;
}
}
이렇게 리팩토링을 하고 나니 함수에 대한 책임이 확실해졌네요~!
나중에 versionUpdate 메서드를 수정해야 될 시기가 올 때, 조금 더 매끄럽게 수정할 수 있을 것 같아요!!
Switch 문
클린 코드에서 부터 나와있듯이
Switch Case 문은 최대한 지양해야 됩니다
왜 그럴까요?
바로 예시를 들어볼게요!
public String convertNumberToName(final int number) {
switch (number) {
case 1:
return "one";
case 2:
return "two";
case 3:
return "three";
default:
throw new IllegalArgumentException("해당하는 숫자는 없습니다");
}
}
이런 이런........
정말 단점이 많은 코드에요
이 코드의 문제점은
OCP를 위반하는 문제가 있습니다
기능이 추가될 때마다 case Code 한줄씩 추가해야하는 번거로움이 있기 때문입니다.
객체지향적인 언어는
다형성이라는 아주 아주 큰 특성을 지니고 있어요
switch로 분류하는 것보단 다형성을 이용해 보는 것은 어떨까요?
네이밍 & 인자
보통 알고리즘 문제 풀때 어떻게 네이밍을 하시나요?
public int go() {
/*
.
.
.
*/
return 1;
}
보통은 이런식으로 많이 작성하지 않나요?
실제로 현업에서
이러한 네이밍의 함수를 다른 사람이 본다고 생각해볼까요?
아무리 봐도 정말 이해가 안될거에요
함수의 이름은 길어도 좋아요
다만 직관적으로 작성할 필요가 있어요!
ex) parseHTML , convertNumberToName
함수 인자에 대해서 이야기 해볼까요?
다음과 같은 함수가 있다고 생각해볼게요
public int sum(final int number1, final int number2, final int number3, final int number4) {
return number1 + number2 + number3 + number4;
}
위 함수의 문제점은 무엇일까요?
너무나도 인자에 의존적이고, 만약 5개 합을 구하고 싶을땐 IDE의 가로줄을 초과해버리겠네요..
동료가 불쌍하지 않나요?ㅠㅠ
다시 리팩토링을 하면~!
public int sum(final List<Integer> numbers) {
return numbers.stream()
.mapToInt(Integer::intValue)
.sum();
}
요런식으로 인자를 최대한 줄이고, 가독성을 높이는게 포인트입니다!
정리
그 외에도
- 부수효과를 일으키지 마라
- 명령과 조회는 분리하라
- 반복하지 마라
와 같은 원칙들도 있는데, 한번 직접 구매하셔서 정리해보시는 걸 추천할게요 ^-^
다음에 또 정리글로 돌아올게요~!
'Developer > 개발서적' 카테고리의 다른 글
오브젝트(조영호) 책 후기 - 객체지향설계의 끝은 어디인가 (1) | 2020.01.07 |
---|---|
Clean Code(클린코드) - 우리가 코드를 깨끗하게 작성해야 하는 이유 : (2) 테스트 코드도 코드다 (0) | 2019.12.17 |
Clean Code(클린코드) - 우리가 코드를 깨끗하게 작성해야 하는 이유 : 소개글 (0) | 2019.12.07 |
개발서적 - 객체지향의 사실과 오해 (0) | 2019.05.17 |