forked from enan501/springStudy
-
Notifications
You must be signed in to change notification settings - Fork 0
Session2 DAY 3
Kimgeunwook edited this page Oct 5, 2021
·
5 revisions
모임날짜: 2020-12-12(토)
참여자:강인한, 김근욱, 최승연, 한승엽
주제: 함수 (클린 코드 3장) / API 명세서 작성
1.1 함수
1.2 규칙
목표: 함수를 잘 만드는 방법을 이해하기
1.1 함수
프로그램의 가장 기본적인 단위
- 함수는 의도를 분명히 표현해야 함 → 어떤 속성을 부여해야 처음 보는 사람도 내부를 직관적으로 파악할 수 있을까?
- 큰 개념(함수 이름)을 다음 추상화 수준에서 여러 단계로 나누어 수행하기 위해서
1.2 규칙
- 작게 만들기 : 함수는 하나의 이야기만 표현한다
- 중첩구조가 생길만큼 함수는 커져선 안 됨.
- 블록안에는 1줄이 적당 → 안에서 함수 호출함(호출되는 함수 이름을 잘 지으면 직관적으로 내용파악 가능)
- 들여쓰기는 최대 2단
- 한 가지 일만 하기
- 판단 방법: 의미 있는 이름으로 달느 함수를 추출할 수 있다면 그 함수는 여러 작업을 하는 셈 p.45 참고
- 함수 당 추상화 수준은 하나로!
- 함수가 확실히 한 가지 작업만 하려면 함수 내 모든 문장의 추상화 수준이 동일해야 함
- 내려가기 규칙
- 코드가 위에서 아래로 이야기처럼 읽혀야 좋음 → depth가 깊어질 수록 추상화 수준이 한 단계씩 낮아진다 ex) getHTML(): 추상화 수준 높음 .append("\n") ; 추상화 수준 낮음
- Switch문은 숨겨서
- 본질적으로 N가지 처리 but, 피할 방법은 없음
- 만약 같은 객체를 가지고 다른 함수가 추가될 경우 또 N번의 분기를 가진 함수가 생겨나는 것임 ex. calaulatePay() 말고 isPaday() 함수가 추가될 때 switch-case 문이 또 생김
- 숨기는 방법: 다형성을 이용하여 저차원 클래스에 숨김
- abstract class, interface 를 이용해 다형성 객체 생성
- 본질적으로 N가지 처리 but, 피할 방법은 없음
- 서술적인 이름 사용하기
- 코드를 읽으면서 짐작했던 기능을 각 루틴이 그대로 수행하면 ⇒ 클린코드(by 워드)
- 한 가지만 하는 작은 함수는 이름붙이기가 수월함. 길어도 괜찮음
- 함수 인수
- 최대 2개까지로 제한하기 → 인수는 개념을 이해하기 어렵게 만듦 ⇒ 코드를 읽는 시점에서 중요하지 않는 세부적인 사항까지 알아야 하니까
- 인수가 많으면 테스트도 어려워짐 → n개의 조합을 모두 test해봐야 하니까 [예시]
- 단항 함수
- 인수에 질문을 던지는 경우 ex. boolean fileExists("MyFile")
- 인수를 뭔가로 변환해 결과를 반환하는 경우 ex. InputStream은 인자로 들어온 file을 InputStream으로 변환함
- 이벤트 처리 ex. 입력 인수를 해석해 시스템 상태를 바꿈
- 플래그 인수
- 추 하 다 → 함수가 여러 가지를 처리한다고 공표하는 격임
- 이항 함수
- 자연적인 순서에 의해 2개인건 ㄱㅊ ex. Point클래스(좌표는 점 2개니까)
- assertEquals(expected, actual)은 자연적인 순서가 아니므로 순서를 기억해야한다는 단점이 있음
- 인수 객체
- 인수가 2, 3개 필요하다면 독자적인 클래스 변수로 선언할 가능성을 고려해봐야함 ex. makeCircle(double x, double y, double radius) https://github.com/Kimgeunwook/Spring-Study/wiki/_new → makeCircle(Point center, double radius)
- 동사와 키워드
- 단항 함수: 함수와 인수가 동사/명사 쌍을 이뤄야 함 ex. write(name)은 '이름을 쓴다'라는 뜻 → writeField(name)은 '이름'이란 '필드'를 '쓴다'라는 뜻 //더 명확하고 좋음
- 함수 이름에 키워드(인수 이름)추가 → 인수 순서를 기억할 필요 없음 ⇒ assertEquals → assertExpectedEqualsActual
- 부수 효과를 일으키지 마라
- 함수에서 약속한 기능말고 다른 일을 하지 말 것 ex. 인수나 시스템 전역 변수를 수정함
- 의도하지 않은 채로 시간적 결합은 혼란을 일으킬 수 있음
ex. 비밀번호만 체크하겠다고 해놓고, 세션까지 초기화 해버리는 함수는 잘 못 호출했을 때 문제 생길 수 있음
→ 인수의 값이 함수에서 바껴서 호출한 곳에서 쓰는 경우?!? ⇒ 개별로임
- 명령과 조회를 분리하기
- 함수는 뭔가를 수행하거나 뭔가에 답하거나 둘 중 하나만 해야 함 ex. if(set("username", "ddeung")) //1번: username이 ddeung이라면 //2번: username을 ddeung으로 바꾸는데 성공한다면 혼란을 야기할 수 있음 ⇒ if(attributeExists("username")){ setAttribute("username", "ddeung"))} 이 더 좋은 구조
- 오류코드보다 예외 사용하기
- if문에 명령문이 들어가서 오류코드를 반환할 경우 → 호출한 함수에서 오류 코드에 따른 핸들링을 해야함 ⇒ 함수의 depth가 자연적으로 깊어질 수 밖에 없음 ⇒ 오류코드 반환 부분을 try-catch로 뽑기 // catch 에서 exception으로 처리함 ⇒ try-catch도 사실 추한 구조임 ⇒ 에러 발생 가능성있는 부분을 따로 함수로 만들고, 메인 로직을 처리하는 함수에선 예외 처리 안하도록 만들기
- 즉, 정상 동작과 오류 처리 동작을 분리하여 만들자
- 오류 처리도 한 가지 작업임 → 함수로 따로 빼내서 처리하기(오류만 처리시킴)
- 저자는 오류코드 방식보다 예외처리 방식 추천 → 오류코드는 새로운 코드 추가가 번거로움
- 반복하지 마라
- 한 함수 내에 중복되는 것이 있다면, 하나 고칠경우 수작업으로 다 고쳐야함
- 소프트웨어는 중복을 제거하는 쪽으로 발전해옴 ex. RDB의 정규화, AOP 등등