개발자 99% 커뮤니티에서 수다 떨어요!
오늘 TIL 3줄 요약
함수는 작게 한가지만 해야한다.
내가 원하는 함수를 짤 때도 한번에 잘 짜려고 하기 보다, 이야기를 짓듯이 정리하고 다듬으면서 이 장의 규칙을 따라해볼것.
TIL (Today I Learned) 날짜
2022.4.26- 4.27
오늘 읽은 범위
3장 함수
책에서 기억하고 싶은 내용을 써보세요.
작게 만들어라
함수가 이야기 하나를 표현하는것.
if/else/while 문 등에 들어가는 블록은 한줄이어야 한다. 즉 중첩구조가 생길 만큼 함수가 커져서는 안된다. 들여쓰기 수준이 1단이나 2단을 넘어서지 말것.
한 가지만 해라
함수는 한가지를 해야 한다. 그 한가지를 잘 해야 한다. 그 한가지만을 해야 한다.
한가지 작업만 하는 함수는 자연스럽게 섹션으로 나누기 어렵다
함수 당 추상화 수준은 하나로
함수가 확실히 한가지 작업만 하려면 함수 내 모든 문장의 추상화 수준이 동일해야 한다.
코드는 위에서 아래로 이야기 처럼 읽혀야 좋다. 위에서 아래로 프로그램을 읽으면 함수 추상화 수준이 한 번에 한 단계씩 낮아진다.
Switch문
switch문은 작게 만들기 어렵다. 한 가지 작업만 하는 switch문도 만들기 어렵다. 불행히도 완전히 피할 방법은 없다. 하지만 각 switch 문을 저차원 클래스에 숨기고 절대로 반복하지 않는 방법은 있다. 물론 다형성을 이용한다. 예를 들어, switch문을 추상팩토리에 숨기고, 팩토리는 switch문을 사용해 적절한 파생 클래스의 인스턴스를 생성한다.
서술적인 이름을 사용하라
이름이 길어도 괜찮다. 길고 서술적인 이름이 짧고 어려운 이름보다 좋다. 길고 서술적인 이름이 길고 서술적인 주석보다 좋다.
함수 이름을 정할 때는 여러 단어가 쉽게 읽히는 명명법을 사용한다. 그런 다음, 여러 단어를 사용해 함수 기능을 잘 표현하는 이름을 선택한다.
이름을 붙일 때는 일관성이 있어야 한다. 모듈 내에서 함수 이름은 같은 문구, 명사, 동사를 사용한다.
함수 인수
함수에서 이상적인 인수 개수는 0개(무항)다. 다음은 1개(단항)고, 다음은 2개(이항)다. 3개(삼항)는 가능한 피하는 편이 좋다.
함수에 인수 1개를 넘기는 이유로 가장 흔한 경우는 2가지다. 하나는 인수에 질문을 던지는 경우, 다른 하나는 인수를 뭔가로 변환해 결과를 반환하는 경우다.
boolean fileExists("MyFile");// 인수에 질문을 던지는 경우
InputStream fileOpen("MyFile");//인수를 뭔가로 변환해 결과를 반환하는 경우
void includeSetupPageInto(StringBuffer PageText) // 변환 함수에서 출력 인수를 사용하면 혼란을 일으킨다.
StringBuffer transform(StringBuffer in) //위의 예시보다 나은 경우
함수로 부울 값을 넘기는 관례는 한꺼번에 여러 가지를 처리한다고 대놓고 공표하는 셈이다.
이항 함수와 삼항 함수는 간으한 단항 함수로 바꾸도록 애써야 한다. 인수가 2-3개가 필요하다면 일부를 독자적인 클래스 변수로 선언하여 사용해 본다.
Circle makeCircle(double x, double y, double radius);
Circle makeCircle(Point center, double radius);
함수의 의도나 인수의 순서와 의도를 제대로 표현하려면 좋은 함수 이름이 필수다. 단항 함수는 함수와 인수가 동사/명사 쌍을 이루어야 한다.
명령과 조회를 분리하라
함수는 뭔가를 수행하거나 뭔가에 답하거나 둘 중 하나만 해야 한다. 객체 상태를 변경하거나 아니면 객체 정보를 반환하거나 둘 중 하나다.
오류 코드보다 예외를 사용하라
try/catch 블록은 별도 함수로 뽑아내는 편이 좋다.
오류 처리도 한 가지 작업만 해야 한다. 함수에 try가 있다면 함수는 try문으로 시작해 catch/finally 문으로 끝나야 한다.
오류코드도 어디선가 오류코드를 정의한다는 뜻이다. Error enum 클래스를 만들어서, import 하여 사용했을 경우, Error eum이 변한다면 사용하는 클래스 전부를 다시 컴파일하고 다시 배치해야 한다. 그래서 새 오류 코드를 추가하는 대신 기존 오류코드를 재사용 한다. 오류코드 대신 예외를 사용하면 새 예외는 Exception 클래스에서 파생된다. 따라서 재컴파일/재배치 없이도 새 예외 클래스를 추가할 수 있다.
반복하지 마라
중복은 코드 길이가 늘어날 뿐 아니라 알고리즘이 변하면 네 곳이나 손봐야 한다. 어느 한곳이라도 빠뜨리는 바람에 오류가 발생할 확률도 네 배나 높다.
구조적 프로그래밍
모든 함수와 함수 내 모든 블록에 입구와 출구가 하나만 존재해야 한다고 말한다. return 문이 하나여야 하며 루프 안에서 break나 continue를 사용해선 안되며 goto는 절대 안된다는
하지만 함수를 작게 만든다면 위의 규칙은 별 이익을 제공하지 못한다. 함수가 클 때만 이익을 제공한다. 작은 함수에서는 return, brak, continue를 여러차례 사용해도 괜찮다.
함수를 어떻게 짜죠?
소프트웨어를 짜는 행위는 여느 글짓기와 비슷하다. 생각을 기록한 후 읽기 좋게 다듬는다. 초안은 대게 서투르고 어수선하므로 원하는 대로 읽힐 때까지 말을 다듬고 문장을 고치고 문단을 정리한다.
내가 원하는 함수를 짤 때도 마찬가지다. 처음에는 길고 복잡하다. 중복도 많고 인수 목록도 길고, 이름은 즉흥적이고 코드는 중복된다. 그런 다음 코드를 다듬고, 함수를 만들고, 이름을 바꾸고, 중복을 제거한다. 메서드를 줄이고 순서를 바꾼다. 때로는 전체 클래스를 쪼개기도 한다.
최종적으로는 이 장에서 설명한 규칙을 따르는 함수가 얻어진다. 처음부터 그게 가능한 사람은 없으리라.
오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요
프론트엔드 개발자라면 제일 많이 고민했을 부분이 이번 내용인것 같다. 어떻게 하면 함수를 잘 짤수 있을까 고민하면서도 검색해보면서도 정리가 잘 안된 부분이었는데, 많이 도움을 받은 것 같다. 리액트의 경우 함수형 프로그래밍 방식이 기본인데, 위의 규칙을 따르는게 제일 좋은 방법일까? 싶은 생각.
궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요.
책과 별개로 개발하면서 함수를 잘 짜게 된 환경이나, 책의 내용과는 조금 다른 경험을 하신 개발자분들의 생각이 궁금합니다!
오늘 읽은 다른사람의 TIL