세션 내용 정리 - 함수로 말해요

SIHA·2025년 1월 20일

SPARTA 수준별 수업 챌린지반 Day02

자바에서 함수란? (method, function)
입출력? 동작? 행위? 과정?


대화의 전달력 향상

  • 무엇을 할지 명확히 표현

bad case

public void dataProcess() { ... };

good case

public void calculateTotalCount() { ... }
  • 작은 대화는 더 구체적, 큰 대화는 더 포괄적
// big function
public void order() {
    // small functons
    validateOrder();
    calculateDiscount();
    submitOrder();
}
  • 하고자 하는 말을 정확하게 표현

bad case

public boolean check(int num) {
    return num / 1440 >= 1;
}

good case

public boolean isTimeOverOneDay(int minutes) {
    int minutesOfDay = 1440;
    return minutes % minutesOfDay >= 1;
}
  • 어려운 말을 쉽게 표현

bad case

if (user.isActive() && user.hasValidSubscription() && "PREMIUM".equals(user.getMembership())) {
 ...
}

good case

if (canAccessPremiumMember(user)) {
    ...
}

private boolean canAccessPremiumMember(User user) {
    return user.isActive() && 
           user.hasValidSubscription() &&
           user.getMembership() == Membership.PREMIUM;
}
  • 확장성을 고려한 표현

  • 목적어와 함께 표현

    • 목적과 의도를 명확히 표현할 수 있는 매개변수 이름 명명
    • 매개변수의 이름과 맞는 적절한 데이터 타입 사용
    • 가능하면 매개변수는 3개 이하로 유지하며, 필요에 따라 객체로 전달
    • setter가 아닌 이상, 함수 내에서 매개변수의 참조 값 변경 지양
    • 목적어를 통해 확장성 있는 대화가 가능
// 단일 대화
public void sendWelcomeEmail();

// 확장성 있는 대화
public void sendEmail(EmailType emailType);
  • 상황에 맞는 직관적인 단어 선택

함수명에 정답은 없지만, 함수가 필요한 상황에 따라 단어를 적절히 선택해야함

프로그램 종료

public void terminateProcess()
public void stopProcess()

주문 정보 가져오기

public Order retrieveOrder()
public Order getOrder()

유효성 검사

public boolean validateEmail()
public boolean checkEmail() 
  • 보편적으로 이해되는 단어 선택(유비쿼터스 도메인 언어) (ubiquot... domain language)

  • 대화 전달력의 핵심

SOLID
Single responsibity principle
Open Close principle
Liskov substitution principle
Interface segregration principle
Dependency inversion princicple

함수형 대화 방법

  • 선언적 대화 방법
    선언적 방식을 통해 어떻게(How) 할지를 작성하지 않고, 무엇을(What) 할지를 표현함으로써 대화의 본질과 흐름에 집중한다.

명령형 방식

List<Integer> results = new ArrayList<>();
for (int n : numbers) {
    if (n % 2 == 0) {
        results.add(n *n);
    }
}
int sum = 0;
for (int n : results) {
    sum + n;
}

선언적 방식

int sum = numbers.stream()
    .filter(n -> n % 2 == 0)
    .map(n -> n * n)
    .reduce(0, Integer::sum);
  • 순수 함수 대화 방법
    동일한 입력에는 항상 같은 값을 반환 하는 순수 함수를 사용함으로써 대화의 신뢰도를 높인다.
    - 순수함수는 그 자체가 독립적이기 때문에 side effect가 발생하지 않음
    - 불변성을 유지하기 때문에 코드의 예측 가능성과 안정성을 높여줌 (thread safe 보장)
    - 함수를 호출하면 항상 동일한 결과를 반환하기 때문에, 함수를 디버깅하거나 테스트하기 쉬워짐
    - SRP를 지키기 쉬움
public int add(int a, int b) { return a + b; }
  • 고차 함수 대화 방법

함수를 매개변수로 받거나 함수를 결과값으로 반환하는 고차 함수를 사용함으로써 유연한 대화를 이끌어간다.

List<Integer> customNumbers = numbers
    .filter(n -> n % 2 == 0)
    .map(n -> n * 2)
    .collect();

filter, map 등은 대표적인 고차 함수

  • Stream & Lambda 를 통한 간결한 대화
List<String> reversedAdultCrewNames = crews.stream()
    .filter(crew -> 20 < crew.getAge())
    .sorted(Comparator.comparingInt(Crew::getAge).reversed())
    .map(Crew::getName)
    .collect(Collectors.toList());

생성 → 중간 연산 → 최종 연산 형태로 진행됨

Stream을 반환하는 여러 개의 중간 연산을 연속적으로 연결하며, 지연 평가(Lazy Evaluation)를 활용하여 효율적으로 처리

filter(), map(), sort() 등이 있음

각 고차함수는 lambda 식을 통해 연산 결과를 반환

최종 연산은 한 번만 실행되며, 실행 후에는 Stream이 종료되어 추가적인 연산을 할 수 없음

collect(), forEach(), reduce() 등이 있음


  • Optional 과 결합한 안정적인 대화
boolean existAdultCrew = crews.stream()
    .filter(crew -> 20 < crew.getAge())
    .findFirst()
    .isPresent();

함수형 프로그래밍 방법과 함께 null 안전성을 높이고, 코드의 가독성을 향상시킬 수 있음

  • 간편한 병렬 대화

java

ExecutorService executor = Executors.newFixedThreadPool(4);
List<Future<Integer>> futures = new ArrayList<>();

for (Integer number : numbers) {
    Future<Integer> future = executor.submit(() -> number * 2);
    futures.add(future);
}

for (Future<Integer> future : futures) {
    System.out.println(future.get());
}

executor.shutdown();

java stream

numbers.parallelStream()
    .map(n -> n * 2)
    .forEach(System.out::println);

단점
: 가독성이 무조건 좋지만은 않으며, 코드 중단이 불가하다. 또한 디버깅이 불편하다.

profile
뭐라도 해보자

0개의 댓글