Skip to main content

3장 함수

1. 📌 핵심 개념 정리

좋은 함수란 무엇인가?요약하기

    1.
  • 함수를 작게 만들어라!
  • 함수를 만드는 첫 번째 규칙은 '작게' 만드는 것이다. 두 번째 규칙은 '더 작게' 만드는 것이다. 함수는 가능한독성을 위해아야 하며, 일반적으로 20줄 이하로 작성하, 단순if/else, while, for 문 등의 블록은 1줄로 만들어 들여쓰기 수준을 1단 또는 2단을 넘지 않도록 해야 한다.

    • 개선 전
    public class OrderProcessor {
        public void processOrder(Order order) {
            if (order != null) {
                if (order.isPaid()) {
                    if (order.isShipped()) {
                        System.out.println("이미 배송된 주문입니다.");
                    } else {
                        order.ship();
                        System.out.println("주문이 배송되었습니다.");
                    }
                } else {
                    System.out.println("결제되지 않은 주문입니다.");
                }
            } else {
                System.out.println("잘못된 주문입니다.");
            }
        }
    }
    
    • 개선 후
    public class OrderProcessor {
        public void processOrder(Order order) {
            if (order == null) {
                handleInvalidOrder();
                return;
            }
    
            if (!order.isPaid()) {
                handleUnpaidOrder();
                return;
            }
    
            processShipping(order);
        }
    
        private void handleInvalidOrder() {
            System.out.println("잘못된 주문입니다.");
        }
    
        private void handleUnpaidOrder() {
            System.out.println("결제되지 않은 주문입니다.");
        }
    
        private void processShipping(Order order) {
            if (order.isShipped()) {
                System.out.println("이미 배송된 주문입니다.");
                return;
            }
            order.ship();
            System.out.println("주문이 배송되었습니다.");
        }
    }
    

    개선 후 코드는 들여쓰기 제한을 준수하고 if 문 중첩을 최소화하여 가독성을 높였다.

    2. 한 가지 기능하도록해라!

    설계하라

    "함수는 한 가지를 해야 한다. 그 한 가지를 잘 해야 한다. 그 한 가지만을 해야 한다."
    함수는 지정된 이름 아래에서 추상화 수준이 하나 작업단계만 수행해야 하며, 여러의미 작업을있는 이름으로 다른 함수를 추출할 수 없을 때까지 작게 만들어야 한다.

    • 추상화는 필요한 정보만 남기고 불필요한 세부사항을 숨기는 개념이며, "무엇을 할 것인가?"(What)담으면집중하고 "어떻게 처리할 것인가?"(How)는 숨기는 원칙이다.

    3. 함수당 추상화 수준은 하나로!

    함수가 한 가지 일만 하려면 함수 내 모든 문장의 추상화 수준이 동일해야 한다. 코드는 위에서 아래로 책처럼 자연스럽게 읽혀야 한다.

    • 개선 전
    public class OrderProcessor {
        private double getPrice(String item) {
            return switch (item) {
                case "Apple" -> 1.0;
                case "Banana" -> 0.5;
                case "Orange" -> 0.75;
                default -> 0.0;
            };
        }
    
        public void processOrder() {
            System.out.println("Processing order...");
    
            List<String> items = fetchItems();
            System.out.println("Items to pack: " + items);
    
            for (String item : items) {
                System.out.println("Packing: " + item);
            }
    
            System.out.println("Calculating total price...");
            double total = 0;
            for (String item : items) {
                total += getPrice(item);
            }
            System.out.println("Total price: $" + total);
    
            System.out.println("Generating invoice...");
            String invoice = "Invoice: " + items + " | Total: $" + total;
            System.out.println(invoice);
    
            System.out.println("Order processed.");
        }
    
        private List<String> fetchItems() {
            return List.of("Apple", "Banana", "Orange");
        }
    }
    
    • 개선 후
    public class OrderProcessor {
        public void processOrder() {
            printStartMessage();
            List<String> items = fetchItems();
            packItems(items);
            double total = calculateTotalPrice(items);
            generateInvoice(items, total);
            printEndMessage();
        }
    
        private void printStartMessage() {
            System.out.println("Processing order...");
        }
    
        private List<String> fetchItems() {
            return List.of("Apple", "Banana", "Orange");
        }
    
        private void packItems(List<String> items) {
            System.out.println("Items to pack: " + items);
            for (String item : items) {
                System.out.println("Packing: " + item);
            }
        }
    
        private double calculateTotalPrice(List<String> items) {
            System.out.println("Calculating total price...");
            double total = 0;
            for (String item : items) {
                total += getPrice(item);
            }
            System.out.println("Total price: $" + total);
            return total;
        }
    
        private double getPrice(String item) {
            return switch (item) {
                case "Apple" -> 1.0;
                case "Banana" -> 0.5;
                case "Orange" -> 0.75;
                default -> 0.0;
            };
        }
    
        private void generateInvoice(List<String> items, double total) {
            System.out.println("Generating invoice...");
            String invoice = "Invoice: " + items + " | Total: $" + total;
            System.out.println(invoice);
        }
    
        private void printEndMessage() {
            System.out.println("Order processed.");
        }
    }
    

    각 단계를 함수로 분리하여 코드 흐름일관되책처럼 자연스럽읽히도록 개선했다.

    4. Switch 문

    본질적으로 N 가를 처리하는 switch 문을 완전히 피할 수는 없지만, 다형성을 이용하여 각 switch 문을 숨기고 반복하지 않도록 구현할 수 있다. switch 문은 추상 팩토리에 의해 숨겨지고 객체 생성 부분에만 사용해야 한다.

    • 개선 전
    public class Payroll {
        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);
            }
        }
    }
    
    • 개선 후
    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 HourlyEmployee(r);
                case SALARIED:
                    return new SalariedEmployee(r);
                default:
                    throw new InvalidEmployeeType(r.type);
            }
        }
    }
    

    개선 후 switch 문은 추상 팩토리에 의해 숨겨지고 객체를 생성하는 부분에만 사용된다.

    5. 서술적인 이름을 사용하라!

    이름이 길더라도 괜찮다. 길고 서술적인 이름이 짧고 모호 이름보다 좋으며, 서술적인 주석보다도 효과적이다. 함수 내의이름은 함수 기능을 명확히 표현해야 하며, 문장내에서 함수 이름은 같은 추상화문구, 수준(명사, 동사 형태를 일관성 있게 사용해야 한다.

    • 좋은 : 고수준includeSetupAndTeardownPages, 중간수준includeSetupPages, includeSuiteSetupPage

    6.  인수

    함수의 인수는 적을수록 좋다. 이상적인 인수 개수는 0개(무항)이며, 단항, 이항 함수 순으로 좋다. 3개 이상의 인수는 가능한 피하는 것이 좋다.

    • 함수 인수에 boolean 값가져넘기는 것은 피해야 한다.
    • 의도를인수가 분명히많아진다면 드러내는 함수명을 사용하라
      – 의미 있는, 서술독자적인 함수명class 로 묶는 것사용하여 코드의 목적을 쉽게 파악할 수 있게고려해야 한다.
    • Switch문은함수 다형성이름에 인수 이름활용추가 최소화함수 의도를 더 명확
      Switch문과 같은있다. 조건
        분기는
      • assertEquals(expected, actual) 보형성(혹은 추상assertExpectedEqualsActual(expected, 팩토리actual) 패턴)으로 감추어 코드의 개방-폐쇄 원칙(OCP)을 따르도록 한명확하다.
      • 인수
      개수를 최소화하라
      – 이상적인 함수 인수는 0개이며, 인수가 많아지면 가독성과 테스트가 어려워진다.

    7. 오류 코드보다 예외를 사용하라!

    오류 코드를 반환하는 대신 예외를 사용하여 오류 처리는 if-else 분기를 통해 코드와 혼합하기보다는 예외(Exception) 처리로 분리한다.

  • 부수 효과를 피하라
    – 함수가 외부 상태를 예상치 못하게 변경하지 않도록 작성하여, 시간적 결합이나 순서 종속성을 줄인다.
  • 명령과 조회를 분리하
    – 함수는 상태코드변경깔끔 명령(Command) 또는 값을 반환하는 조회(Query) 중 하나만 수행유지해야 한다.
  • try-catch 블록을 사용하여 오류를 처리하고, try-catch 블록은 별도의 함수로 분리하는 것이 좋다.

    public void delete(Page page) {
        try {
            deletePage(page);
        } catch (Exception e) {
            log.error(e);
        }
    }
    

    8. 반복하지 마라

    중복은 소프트웨어의 모든 악의 근원이다. 중복을 제거하
    위해 중복다양한 코드는원칙과 유지보수를기법 어렵게(관계형 하므로데이터베이스 정규화, 공통구조적 기능은프로그래밍, 모듈화(AOP, COP 등)하여 제거한등장했다.

  • 9. 구조적 프로그래밍

    준수하라

    함수는 입구와return 출구가문이 하나여야 하며, return문은루프 안에서 번만breakcontinue 사용하지 않고 goto 문은 절대 사용해서는 안 된다.

    10. 함수를 어떻게 짜죠?

    처음부터 완벽한 함수를 작성하기는 어렵다. 초안은 길고 복잡할 수 있지만, 점진적으로 리팩토링하고 다듬어 나가면서 깨끗한 함수를 만들어야 한다. 단위 테스트를 작성하면서 함수를 개선해 나가는 것이 좋은 방법이다.


2. 🤔 함수이해가 작성어려운 부분

🔍 질문하기

1. 개념 또는 원칙

1.이름: 함수를AOP, 작게 만들어라!

COP
  • 목표어려웠던 부분: AOP, COP란 무엇인가? 중복 제거에 어떻게 활용되는가?
  • 궁금한 점: AOP와 COP의 정확한 개념과 중복 제거와의 연관성

이해한 점:

펼치기/접기

AOP (Aspect-Oriented Programming, 관점 지향 프로그래밍)

AOP는 핵심 비즈니스 로직(Core Logic)과 부가적인 관심사(Cross-cutting Concerns)를 분리하여 코드의 재사용성을 높이고 유지보를 쉽게 만드프로그래밍 패러다임이다.

  • AOP의 주요 개념

    • Aspect(애스펙트): 부적인 기(로깅, 트랜잭션 관리 등)을 모듈화한 작고 단순해야 한다.
    • 원칙Join Point(조인 포인트): 애스펙트가 적용될 수 있는 지점(메서드 실행, 예외 발생 등).
    • Pointcut(포인트컷): 애스펙트를 적용할 특정 조건을 정의.
    • Advice(어드바이스): 애스펙트가 실행될 구체적인 동작(메서드 실행 전/후, 예외 발생 시 등).
    • Weaving(위빙): 핵심 코드와 애스펙트를 결합하는 과정.
  • 장점

    • 들여쓰기중복 수준코드 제거 (로깅, 트랜잭션 관리 같1~2단계부가적인 기능을 분리 가능)
    • 핵심 직과 부가 기능 분리하여 유지한다.
    • 보수
    • 중첩 구조(예: if/else, while 등)는 최소화한다.
    • 각 블록은 한 줄로 작성하도록 한다.용이

2.

COP (Context-Oriented Programming, 문맥 지향 프로그래밍)

COP는 실행되는 문맥(Context)에 따라 동적으로 프로그램의 동작을 변경하는 프로그래밍 기법이다. AOP가 주로 부적인 기능을 모듈화하는 데 집중하는 반면, COP는 동적인 문맥(Context)에 따라 동업만 수행변경도록 하라!

데 초점을 맞춘다.

  • COP의 주요 개념

    • 목표Context(문맥): 애플리케이션의 현재 상태(사용자의 위치, 시간, 디바이스 종류 등).
    • Layer(레이어): 특정 문맥에서 활성화될 동작을 정의.
    • Activation(활성화): 특정 문맥이 충족될 때 적절한 레이어를 활성화하여 동작을 변경.
  • 장점

    • 사용자 환경(시간, 장소, 디바이스 등)에 따라 동적으로 동작 변경 가능
    • 애플리케이션의 유연성을 높이고, 사용자 맞춤형 서비스 구현에 유리

2. 함수 추상화 수준은 하나로!

  • 어려웠던 부분:임만에서 말하는 추상화 수준에 대해 잘 이해지도록 설계한안 갔다.
  • 원칙궁금한 점:
    • 함수 이름 아래에 한 가지 추상화 단계수준이 "높다, 낮다, 중간이다" 라는 의미가 대체 무엇인가?

    이해한 점:

    펼치기/접기

    1. 고수준(High-level) 코드란?

    ✔ 핵심 개념존재보여주는 코드

    • "이 코드가 무엇을 하는지"를 설명하는 큰 그림(전체 흐름) 을 보여줌.
    • 세부 구현을 감추고, 전체 로직을 명확히 이 수 있게 함.
    • 주로 함수 호출이나 비즈니스 로직(업무 흐름) 에 해당함.

    💡 예제

    const placeOrder = ({ order }) => {
        validateAvailability(order);  // 주문 가능 여부 확인 (고수준)
    
        // (여기서 중간 및 저수준 작업 진행)
    
        shipOrder(order);   // 주문 배송 처리 (고수준)
    };
    

    왜 고수준인가?

    • validateAvailability(order) → "주문이 가능지 확인"
    • shipOrder(order) → "주문을 배송한다"
    • 세부 구현이 아닌 "이 코드가 무엇을 하는지"를 표현하는 큰 개념 이다.
    • 의미내부 구현이 감춰져어서, "어떻게 하는지"신경 쓸 필요 없음.

    2. 저수준(Low-level) 코드란?

    ✔ 실제로 동작하는 상세 코드

    • 세부적인 계산, 데터 변환, API 호출 같은 작업을 직접 수행하는 코드
    • "어떻게 작동하는지"를 설명하는 코드
    • 구현 세부사항이 많아서 가독성이 떨어질 수 있음.

    💡 예제

    const total = order.items.reduce(
        (item, totalAcc) =>
            totalAcc + item.unitPrice * item.units,
        0,
    );
    

    왜 저수준인가?

    • reduce()를 사용해 주문 항목의 총 가격을 계산하는 세부적인 연산 코드
    • "어떤 방식으로 가격을 계산하는지"에 집중한 구체적인 구현 코드

    3. 중간수준(Mid-level) 코드란?

    ✔ 고수준과 저수준을 연결하는 코드

    • 고수준 코드와 저수준 코드 사이에서 데이터를 가공하고, 각 단계를 연결하는 역할을 함.
    • 하나의 개념을 실행하는데 필요한 여러 작업을 모아서 처리하는 코드.

    💡 예제

    const invoiceInfo = getInvoiceInfo(order);
    const request = new PaymentService.Request({
        total,
        invoiceInfo,
    });
    const response = PaymentService.pay(request);
    sendInvoice(response.invoice);
    

    왜 중간수준인가?

    • getInvoiceInfo(order) → 주문 정보를 가져옴.
    • PaymentService.Request({ total, invoiceInfo }) → 결제 요청 객체를 생성함.
    • PaymentService.pay(request) → 결제 요청을 보냄.
    • sendInvoice(response.invoice) → 결제 후 인보이스(청구서)를 보냄.

    이들은 개별적으로 보면 특정 기능을 처리하는 코드이지만, 전체 주문 처리 과정에서 보면 중간 과정(연결 역할)을 담당하고 있음!


    정리: 코드의 추상화 수준 이해하기

    수준특징예제
    고수준 (High-level)- "무엇을 하는지" 설명
     - 전체 흐름을 보여줌
     - 세부 구현을 감춤
    validateAvailability(order); 
     shipOrder(order);
    중간수준 (Mid-level)- 고수준과 저수준을 연결함
     - 여러 작업을 모아서 처
    const invoiceInfo = getInvoiceInfo(order); 
     const response = PaymentService.pay(request);
    저수준 (Low-level)- "어떻게 동작하는지" 설명
     - 세부적인 계산 및 구현
    const total = order.items.reduce(...);

    3. 함수에 기능 하나씩

    • 추상화: 함수의 지정된 이름 아래 추상화준이 있다면,하나인 분리해야단계
    • 궁금다. 점: 여기서 추상화란 정확히 무엇을 의미하는가?

    이해한 점:

    펼치기/접기

    추상화 수준이 하나라는 것은 한 함수가 너무 낮은 수준의 작업(세부적인 로직)과 높은 수준의 작업(큰 개념)을 동시에 처리하면 안 된다는 의미이다.

    • 개선 전
    public void processOrder() {
        // 주문 처리 (높은 수준)
        System.out.println("주문을 처리합니다.");
    
        // 데이터베이스에서 주문 정보 가져오기 (낮은 수준)
        Order order = database.getOrderById(1);
    
        // 결제 처리 (낮은 수준)
        PaymentProcessor processor = new PaymentProcessor();
        processor.processPayment(order);
    
        // 이메일 전송 (낮은 수준)
        EmailService emailService = new EmailService();
        emailService.sendOrderConfirmation(order);
    }
    
    • 개선 후
    public void processOrder() {
        System.out.println("주문을 처리합니다.");
    
        Order order = getOrder();
        processPayment(order);
        sendConfirmationEmail(order);
    }
    
    private Order getOrder() {
        return database.getOrderById(1);
    }
    
    private void processPayment(Order order) {
        PaymentProcessor processor = new PaymentProcessor();
        processor.processPayment(order);
    }
    
    private void sendConfirmationEmail(Order order) {
        EmailService emailService = new EmailService();
        emailService.sendOrderConfirmation(order);
    }
    

    3. 함수의 추상화 수준을 일관되게 유지하라!

    • 목표: 함수 내 모든 문장이 같은 추상화 수준을 가져야 한다.
    • 원칙:
      • 상위 함수는 '무엇을' 하는지 설명하고, 하위 함수는 '어떻게' 하는지 세부 구현한다.
      • 내려가기 규칙(Top-Down Reading): 코드는 위에서 아래로 읽을 때, 추상화 단계가 한 단계씩 내려가야 한다.

    4. Switch 문을 피하라!

    • 목표: Switch문은 여러 작업을 한꺼번에 처리하므로 피하거나 감춘다.
    • 원칙:
      • 다형성을 활용해 Switch문을 캡슐화한다.
      • OCP(개방-폐쇄 원칙)를 위반하지 않도록 한다.
    public abstract class Employee {
        public abstract boolean isPayday();
        public abstract Money calculatePay();
        public abstract void deliverPay(Money pay);
    }
    

    5. 서술적인 함수명을 사용하라!

    • 목표: 함수명만 보고도 그 기능을 쉽게 이해할 수 있어야 한다.
    • 원칙:
      • 의미를 충분히 전달하는 긴 이름도 괜찮다.
      • 동사 및 명사를 조합해 일관된 문체로 작성한다.
    // 나쁜 예
    void d(); // 의미 불명확
    
    // 좋은 예
    void deleteUserById(int userId);
    

    6. 함수 인수 개수를 최소화하라!

    • 목표: 인수 개수가 적을수록 함수가 단순해지고 테스트하기 쉽다.
    • 원칙:
      • 이상적인 함수는 인수가 0개(무항)이다.
      • 1개(단항)는 변환이나 상태 확인에 사용한다.
      • 2개(이항)는 비교나 두 값 처리를 위한 최소한의 경우.
      • 3개 이상이면 객체로 묶어 전달하는 방법을 고려한다.
    // 개선 전
    Circle makeCircle(double x, double y, double radius);
    
    // 개선 후
    Circle makeCircle(Point center, double radius);
    

    7. 부수 효과를 일으키지 마라!

    • 목표: 함수가 외부 상태를 예상치 못하게 변경하지 않도록 한다.
    • 원칙:
      • 부수 효과(Side Effect)는 함수가 외부 변수나 시스템 상태를 변경하는 것을 의미한다.
      • 부수 효과로 인해 시간적 결합(Temporal Coupling)이나 순서 종속(Execution Order Dependency)이 발생할 수 있다.
      • 출력 인수(Out Parameter)를 피하고, 결과는 반환값으로 처리한다.

    8. 명령과 조회를 분리하라!

    • 목표: 함수는 한 가지 역할(상태 변경 또는 값 반환)만 수행해야 한다.
    • 원칙:
      • 명령(Command) 함수는 상태를 변경하고, 조회(Query) 함수는 값을 반환해야 한다.
      • 둘을 혼합하면 코드의 예측 가능성이 떨어진다.
    // 명령과 조회를 섞은 나쁜 예
    if (deleteUser(userId)) {
        System.out.println("삭제 성공");
    }
    
    // 개선된 코드
    boolean isDeleted = deleteUser(userId);
    if (isDeleted) {
        System.out.println("삭제 성공");
    }
    

    9. 오류 코드보다 예외를 사용하라!

    • 목표: 오류 처리 코드를 본 로직과 분리하여 가독성을 높인다.
    • 원칙:
      • if-else문으로 오류 코드를 반환하는 방식은 명령-조회 분리 원칙에 어긋난다.
      • 예외(Exception)를 사용해 오류 상황을 처리하면 코드가 더 깔끔해진다.
    // 나쁜 예 - 오류 코드 사용
    int processPayment(Order order) {
        if (order.isPaid()) {
            return -1; // 이미 결제됨
        }
        return 0; // 정상 처리
    }
    
    // 좋은 예 - 예외 사용
    void processPayment(Order order) throws PaymentAlreadyProcessedException {
        if (order.isPaid()) {
            throw new PaymentAlreadyProcessedException("이미 결제되었습니다.");
        }
    }
    

    10. 중복을 제거하라!

    • 목표: 중복된 코드는 유지보수를 어렵게 하므로 제거해야 한다.
    • 원칙:
      • 공통 기능은 모듈화하여 재사용성을 높인다.
      • AOP(관점 지향 프로그래밍) 또는 COP(컴포넌트 지향 프로그래밍)를 활용해 중복을 제거할 수 있다.
    @Aspect
    public class LoggingAspect {
        @Before("execution(* com.example.service.*.*(..))")
        public void logMethodCall(JoinPoint joinPoint) {
            System.out.println("Method called: " + joinPoint.getSignature());
        }
    }
    

    11. 구조적 프로그래밍을 준수하라!

    • 목표: 함수의 입구와 출구를 명확하게 하여 제어 흐름을 단순화한다.
    • 원칙:
      • 함수는 한 번만 return하는 것이 이상적이다.
      • 중첩 if-else문을 줄이고, early return을 사용해 가독성을 높인다.
    // 나쁜 예
    public boolean isValidUser(User user) {
        if (user != null) {
            if (user.isActive()) {
                return true;
            }
        }
        return false;
    }
    
    // 좋은 예
    public boolean isValidUser(User user) {
        if (user == null) return false;
        return user.isActive();
    }
    

    3. 🤔📚 이해가참고 어려운 부분사항

    A.🔍 함수 내 추상화 수준질문하기

      1.
    • 문제: 한 함수 내에서 고수준(What을 설명)과 저수준(How를 구현) 코드가 섞이면 읽기 어려워진다.
    • 정의:
      • 고수준 코드 (High-level):
        – 전체 흐름이나 큰 개념을 설명하는 코드
        – 예: validateAvailability(order);, shipOrder(order);
      • 저수준 코드 (Low-level):
        – 세부적인 연산, 계산, API 호출 등 구체적인 구현을 다루는 코드
        – 예: total = order.items.reduce(...);
      • 중간수준 코드 (Mid-level):
        – 고수준과 저수준 사이의 다리 역할을 하며, 여러 작업을 묶어 처리하는 코드
        – 예: 결제 요청 객체를 생성하고, 결제 서비스를 호출하는 부분
    • 요약: 한 함수는 동일한 추상화 수준의 코드로 구성되어야 하며, 상위 함수는 ‘무엇을 할 것인가’를, 하위 함수는 ‘어떻게 할 것인가’를 담당해야 한다.

    B. 반복하지 마라! – AOP와 COP

    • AOP (Aspect-Oriented Programming, 관점 지향 프로그래밍)
      • 정의:
        – 핵심 기능(Core Concern)과 부가적 관심사(Cross-cutting Concern: 예. 로깅, 보안, 트랜잭션 관리)를 분리하여 모듈화하는 기법
      • 장점:
        – 중복 코드 제거
        – 재사용성과 유지보수성 향상
    • COP (Component-Oriented Programming, 컴포넌트 지향 프로그래밍)
      • 정의:
        – 프로그램을 독립적인 컴포넌트(Component) 단위로 구성하여 각 컴포넌트가 자신의 역할에 집중하도록 하는 방식
        – (일부 문헌에서는 COP를 '문맥 지향 프로그래밍'으로 정의하기도 한다.)
      • 장점:
        – 컴포넌트 간 결합도를 낮추어 유지보수 및 확장이 용이함
    • 요약:
      – AOP와 COP는 공통 기능의 중복을 제거하고 코드의 재사용성을 높이기 위한 기법이다.

    C. 모르는 단어

      1. FitNesse:
        사용자 스토리 기반의 테스트를 지원하는 오픈 소스 웹 애플리케이션
        이다. 애자일 개발 프로세스에서 사용자 및 개발자 협력하여 소프트웨어 요구 사항을 검증하는 데 사용된다.
      2. 출력 인수 (Out Parameter):
        – 함수가프로그램에서 결과를 반환화면, 콘솔, 로그 등으로 출력하는 부분이다. 출력 코드는 프로그램이 사용자나 다른 시스템에 정보를 제공하는 중요한 역할을 한다.

      📢 논의하기

      1. 논의하고 싶은 주제

      • 주제: 추상화 패턴으로 함수를 작성 시 가독성 있는 함수 작성법
      • 설명: 복잡한 비즈니스 로직을 추상화 패턴을 사용하여 작성할 때, 코드를 따라가기 어려운 경우가 있다. 가독성 있는 함수를 작성하기 위해 어떻게 해야 할까? 한 클래스 파일에는 한 가지 기능만 담겨야 하는가?

      2. 논의하고 싶은 주제

      • 주제: switch 문과 if/else 중 어떤 것을 써야 하는가?
      • 설명: 저자는 switch 문보다 단일 블록이나 함수를 수정하는 방식
        – 객체 지향 언어에서는 출력 인수 대신 객체 자신의 상태를 변경하거나, 반환값으로 처리사용하는 것 권장됨선호한다고 한다. 그렇다면 우리는 어떤 것을 써야 할까?

      3.

      4. 📢 논의하고 싶은 주제

      • 주제:

        부수 효과 최소화

      • 설명
        : "시간적인 결합이나 순서 종속성을 초래한다"는 의미가 무엇인가? 함수 외부 상태를 변경함으로써 발생하는 시간적 결합과 순서 종속성 문제를 어떻게 해결할 수 있을까?

      • 플래그 인수를 사용하지 않도록 여러 기능 처리하기
        – 플래그 인수를 사용하면 함수가 여러 작업을 암시하므로, 이를 대체할 수 있는 설계 방법은 무엇일까?

      • 객체지향적인 방식으로 Switch문 리팩토링
        – 다형성을 활용해 조건 분기를 제거하고, 확장성이 높은 설계를 어떻게 구현할 수 있을까?

      • 함수 내 추상화 수준 명확히 구분하기
        – 고수준, 중간수준, 저수준 코드를 어떻게 효과적으로 구분하여 작성할예측 가능한 있을까?

      • 서술적인 함수명 선정
        – 함수명을 통해 함수의 의도결과를 보다 명확히 전달하기 위한 좋은 사례와 방법은 무엇일까?

      • AOP와 COP의 실제 적용 사례 및 단점
        – 두 기법을 실제 프로젝트에 적용할 때의 효과와해야무엇지 논의해보자.

      • 테스트 도구와 함수 설계의 관계
        – FitNesse와 같은 도구 테스트 주도 개발(TDD)이나 함수 설계에 어떤 영향을 미치는지 토론해보자.

        ?

      5.

      📚 참고 사항

      자료

      내려가기

        규칙
      1. 추상화 수준
      2. switch와 if/else 중 어떤 것을 써야 하는가?

      3. 내려가기 규칙