진소희
1. 📌 핵심 개념 정리
✅ 요약하기
- 의도를 분명히 표한하는 함수를 어떻게 구현할 수 있을까?
- 함수에 어떤 속성을 부여해야 처음 읽는 사람이 프로그램 내부를 직관적으로 파악할 수 있을까?
- 작게 만들어라!
함수를 만드는 첫째 규칙은 '작게!' 이다. 함수를 만드는 둘째 규칙은 '더 작게!'이다.- 얼마나 짧아야 좋을까?
- 블록과 들여쓰기: if문, else문, while문 등에 들어가는 블록은 한 줄이어야 한다는 의미다.
- 이 말은 중첩 구조가 생길 만큼 함수가 커져서는 안 된다는 뜻이다.
- 한 가지만 해라!
힘수는 한 가지를 해야 한다. 그 한 가지를 잘 해야 한다. 그 한 가지만을 해야 한다.- 지정된 함수 이름 아래에서 추상화 수준이 하나인 단계만 수행한다면 그 함수는 한 가지 작업만 한다.
TO RenderPageWithSetupsAndTeardowns, 페이지가 테스트 페이지인지 확인한 후 테스트 페이지라면 설정 페이지와 해제 페이지를 넣는다. 테스트 페이지든 아니든 페이지를 HTML로 렌더링한다.
- 우리가 함수를 만드는 이유는 큰 개념을 다음 추상화 수준에서 여러 단계로 나눠 수행하기 위해서이기 때문이다.
- 단순히 다른 표현이 아니라, 의미 있는 이름으로 다른 함수를 추출할 수 있다면 그 함수는 여러 작업을 하는 셈이다.
- 지정된 함수 이름 아래에서 추상화 수준이 하나인 단계만 수행한다면 그 함수는 한 가지 작업만 한다.
- 함수당 추상화 수준은 하나로!
함수가 확실히 한가지 작업만 하려면 함수 내 모든 문장의 추상화 수준이 동일해야 한다.- 한 함수 내에 추상화 수준을 섞으면 코드를 읽는 사람이 헷갈린다.
- 특정 표현이 근본 개념인지 아니면 세부사항인지 구분하기 어려운 탓이다.
- 위에서 아래로 코드 읽기: 내려가기 규칙
- 코드는 위에서 아래로 이야기처럼 읽혀야 좋다.
- 한 함수 다음에는 추상화 수준이 한 단계 낮은 함수가 온다.
- 즉 위에서 아래로 프로그램을 읽으면 함수 추상화 수준이 한 번에 한 단계씩 낮아진다. 이것이 내려가기 규칙.
- 한 함수 내에 추상화 수준을 섞으면 코드를 읽는 사람이 헷갈린다.
-
Switch 문
본질적으로 switch문은 N가지를 처리한다. 불행하게도 switch문을 완전히 피할 방법은 없다. 하지만 각 switch문을 저차원 클래스에 숨기고 절대로 반복하지 않는 방법은 있다. 물론 다형성을 이용한다.public Money calculatePay (Employee e) throws InvalidEmployeeType { switch (e.type) { case COMMISSIONED: return calculateCommissionedPay(e) ; case HOURLY: return calculateHourlyPay(e); case SALARIED: return calculateSalariedPay (e); default: throw new InvalidEmployeeType(e.type) ; } }
- 함수가 길고, 한가지 작업만 수행하지 않고, SRP 위반, OCP 위반 코드이다.
public abstract class Employee { public abstract boolean isPayday(); public abstract Money calculatePay (); public abstract void deliverPay (Money pay); } --- public interface EmployeeFactory { public Employee makeEmployee (EmployeeRecord r) throws InvalidEmployeeType; } --- public class EmployeeFactoryImpl implements EmployeeFactory { public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType { switch (r. type) { case COMMISSIONED: return new CommissionedEmployee(r) ; case HOURLY: return new Hour lyEmployee(r); case SALARIED: return new SalariedEmployee (r) ; default: throw new InvalidEmployeeType(r.type); } } }
- 서술적인 이름을 사용하자
- 이름이 길어도 괜찮다. 길고 서술적인 이름이 짧고 어려운 이름보다 좋다. 길고 서술적인 이름이 길고 서술적인 주석보다 좋다.
- 서술적인 이름을 사용하면 개발자 머리속에서도 설계가 뚜렷해지므로 코드를 개선하기 쉬워진다.
- 이름을 붙일 때는 일관성이 있어야 한다.
- 문체가 비슷하면 이야기를 순차적으로 풒어가기도 쉬워진다.
- 함수 인수
함수에서 이상적인 인수 개수는 0개(무항)이다. 다음은 1개(단항)고, 다음은 2개다(이향)
- 테스트 관점에서 보면 인수는 어렵다. 갖가지 인수 조합으로 함수를 검증하는 테스트 케이스를 작성한다고 가정했을 때, 인수가 없다면 간단하지만, 인수가 많을수록 복잡해진다.
- 많이 쓰는 단향 형식
- 함수에 인수 1개를 넘기는 이유로 가장 흔한 경우 2가지
- 인수에 질문을 던지는 경우
- 인수를 뭔가로 변환해 결과를 반환하는 경우
- 함수에 인수 1개를 넘기는 이유로 가장 흔한 경우 2가지
- 플래그 인수: 추하다. 함수가 한꺼번에 여러 가지를 처리한다고 공표하는 셈이다.
- 이항함수: 인수가 2개인 함수는 1개인 함수보다 이해하기 어렵다.
- 이항함수가 무조건 나쁘다는 뜻은 아니다. 프로그램을 짜다보면 불가피하게 써야 하는 순간이 있는데, 그만큼 위험이 따른다는 것을 이해하고 가능하면 단일 함수로 바꾸도록 해야 한다.
- 삼항함수: 인수가 3개인 함수는 2개인 함수보다 훨씬 더 이해하기 힘들다.
- 인수 객체: 인수가 2-3개 필요하다면 일부를 독자적인 클래스 변수로 선언할 가능성을 짚어본다.
- 인수 목록: 때로는 인수 개수가 가변적인 함수도 필요하다. 예시)
String.format("%s worked %.2f hours." name, hours);
좋은 예시이다.
- 부수 효과를 일으키지 마라
- 시간적인 결합이나 순서 종속성을 초래한다.
- 출력 인수
- 일반적으로 출력 인수는 피해야 한다. 함수에서 상태를 변경해야 한다면 함수가 속한 객체 상태를 변경하는 방식을 택한다
- 명령과 조회를 분리하라!
- 함수는 뭔가를 수행하거나 뭔가에 답하거나 둘 중 하나만 해야 한다. 둘 다 하면 안 된다. 객체 상태를 변경하거나 아니면 객체 정보를 반환하시거나 둘중 하나다.
- 오류코드보다 예외를 사용하라!
- 명령 함수에서 오류 코드를 반환하는 뱡식은 명, 조회 분리 규칙을 미묘하게 위반다. 자칫하면 if문에서 명령을 추현식으로 사용하기 쉬운 탓이다.
- 하지만 오류 코드 대신 예외를 사용하면 오류 처리 코드가 원래 코드에서 분리되므로 코드가 깔끔해진다.
- try-catch
- 반복하지 마라!
- 중복은 문제다. 코드 길이가 늘어날 뿐만 아니라 알고리즘이 변하면 네 곳이나 손봐야 하기 때문이다.
- 구조적 프로그래밍
- 데이크스트라는 모든 함수와 함수 내 모든 블록해 입과와 출구가 하나만 존재한다고 말했다.
2. 🤔 이해가 어려운 부분
🔍 질문하기
모르는 단어
-
FitNesse
- 사용자 스토리 기반의 테스트를 지원하는 오픈 소스 웹 애플리케이션입니다. 이 도구는 애자일 개발 프로세스에서 자주 사용되며, 사용자와 개발자가 협력하여 소프트웨어 요구 사항을 검증하는 데 도움을 줍니다.
-
출력 인수
- 프로그램에서 결과를 화면이나 콘솔, 로그 등으로 출력하는 부분을 의미
- 출력 코드는 프로그램이 사용자나 다른 시스템에 정보를 제공하는 중요한 역할을 하므로, 이를 어떻게 작성하느냐가 코드의 품질에 큰 영향을 미친다.
public class Main { // 두 수의 합을 반환하는 메서드 public static int add(int a, int b) { return a + b; // 출력 인수 (반환값) } public static void main(String[] args) { int result = add(4, 7); // 결과 저장 System.out.println("결과: " + result); // 결과: 11 } }
3. 📚 참고 사항
📢 논의하기
- 논의하고 싶은 주제
- 부수 효과 최소화
- 시간적인 결합이나 순서 종속성을 초래한다는 의미가 무엇인가
- 설명
- 함수는 외부 상태를 변경하지 않도록 하여, 예측 가능한 결과를 보장해야 한다는 뜻
- 부수 효과 최소화