- 작게 만들어라
- 한 가지만 해라
- 함수당 추상화 수준은 하나로
- Switch 문
- 서술적인 이름을 사용하라
- 함수 Parameter
- Side Effect를 일으키지 마라
- 명령과 조회를 분리하라
- 오류 코드보다 예외를 사용하라
- 반복하지 마라
- 함수를 짜는 방법
- 함수를 작게 만들어라.
- 그리고 함수를 더 작게 만들어라.
if,else,while등에 들어가는 불록은 한 줄이어야한다.
- 함수는 한가지만을 해야 한다. 그 한가지를 잘 해야 한다. 그 한가지만을 해야한다.
- 함수내에서 추상화 수준이 하나인 단계만 수행한다면 그 함수는 한 가지 작업만 한다.
- 함수가 한 가지 작업만 하려면 함수 내 모든 문장의 추상화 수준이 동일해야한다.
- 추상화의 수준이 섞여 있으면 안된다.
- 코드는 위에서 아래로 이야기 처럼 읽혀야 좋다.
- 위에서 아래로 추상화 단계가 한 단계씩 낮아진다.
- 다형성을 이용하여 switch를 저차원 클래스에 숨기고 절대로 반복하지 않는다.
추상화란 무엇인가?
- 함수가 작고 단순할수록 서술적인 이름을 고르기도 쉬워진다.
- 단, 이름을 붙일 때는 일관성이 있어야 한다.
- 이상적인 parameter의 개수는 0개 이다.
- 4개 이상은 특별한 이유가 있어도 사용하면 안된다.
- Parameter에 질문을 던지는 경우
- e.g.
fileExists("Myfile")
- e.g.
- Parameter를 무언가로 변환해 결과를 반환하는 경우
- 이벤트 함수
- 이벤트 함수는 input parameter만 존재한다. ouput은 존재하지 않는다.
- Parameter로 상태를 바꾼다.
- 이벤트라는 사실이 코드에 명확이 드러나야한다.
- 함수와 Parameter가 쌍을 이루어야한다.
- 함수로 bool 값을 넘기는 것은 함수에서 한 가지 일을 처리하는 규칙에 어긋난다.
- 사용을 지양해야한다.
- 자연적 순서가 존재하는 경우 사용한다.
- e.g.
new Point(0,0)
- e.g.
- 불가피한 경우가 존재하겠지만, 단항함수로 바꾸도록 노력해라.
-
Parameter가 2개인 함수보다 이해하기 어렵다.
-
객체를 생성하여 인수를 줄이는 방법도 좋다.
- 객체를 생성함으로써 개념을 표현하게 된다.
❌ makeCircle(x: Double, y: Double, radius: Double); ✅ makeCircle(center: CGPoint, radius: Double);
- Side Effect는 함수에서 한가지 일을 처리하는 규칙에 어긋난다.
- Temporal coupling이나 Order dependency를 초래한다.
Temporal coupling ?
Order dependency ?
- 출력 Parameter의 사용을 지양한다.
❌ func appendFooter(report: String)
✅ report.appendFooter()- 함수에서 상태를 변경해야 한다면 함수가 속한 객체 상태를 변경하는 방식을 택한다.
- 함수는 뭔가를 수행하거나 뭔가에 답하거나 둘 중 하나만 해야 한다.
❌ 명령과 조회가 같이 있는 경우
public boolean set(String attribute, String value);
if (set("username", "unclebob"))... //의미가 명확하지 않다.
✅ 명령과 조회가 분리된 경우
if (attributeExistsC'username")) { //조회
setAttribute("username", "unclebob"); //명령
...
}- 명령/조회 분리 규칙을 미묘하게 위반한다.
- 오류 코드의 사용은 여러 단계로 중첩되는 코드를 야기한다.
try {
deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey());
} catch (Exception e) {
logger.log(e.getMessage());
}- Try/Catch는 정상동작과 오류 처리 동작을 뒤섞는다.
public void delete(Page page) {
try {
deletePageAndAllReferences(page);
} catch (Exception e) {
logError(e);
}
}- 중복되는 코드가 존재하면, 오류 발생 확률이 높아진다.
- 처음부터 함수를 잘 짜낼 수 없다.
- 리펙토링을 통하여 코드를 다듬고, 함수를 만들고, 이름을 바꾸고, 중복을 제거하며 메서드를 줄이고 순서를 바꾼다.