클린 코드(Clean Code)

Y_Sevin·2023년 4월 23일
0

클린 코드: 자바 프로그래밍을 위한 실천적 가이드

소프트웨어 개발에서 '클린 코드(Clean Code)'는 코드의 가독성, 유지보수성, 확장성을 높이기 위한 방법론을 의미합니다. 클린 코드를 작성하는 것은 단순히 기능을 구현하는 것 이상으로, 코드의 품질과 팀 협업의 효율성을 높일 수 있습니다.

1. 의미 있는 변수 및 함수 이름 사용

변수와 함수의 이름은 코드의 가독성에 큰 영향을 미칩니다. 이름은 코드의 의도를 명확하게 전달해야 하며, 이름만으로도 해당 변수나 함수의 역할을 알 수 있어야 합니다. 뿐만아니라 독특한 어휘를 사용하지 않고 일관성있는 어휘를 사용하여 그 의미를 알 수 있도록 합니다.

// 나쁜 예시
int day; // 날짜를 의미하지만 명확하지 않음

// 좋은 예시
int daysSinceLastUpdate; // 날짜를 명확하게 표현

함수 이름 역시 마찬가지로, 함수가 수행하는 작업을 명확히 설명해야 합니다.

// 나쁜 예시
public void getData() {
    // 데이터베이스에서 데이터를 가져옴
}

// 좋은 예시
public void fetchCustomerData() {
    // 데이터베이스에서 고객 데이터를 가져옴
}

2. 함수는 하나의 작업만 수행

함수는 단일 책임 원칙(Single Responsibility Principle, SRP)을 따라 하나의 작업만 수행해야 합니다. 함수가 여러 작업을 수행하면 코드의 가독성과 유지보수성이 떨어집니다.

// 나쁜 예시
public void saveAndPrintCustomerData(Customer customer) {
    saveCustomerData(customer);
    printCustomerData(customer);
}

// 좋은 예시
public void saveCustomerData(Customer customer) {
    // 고객 데이터를 저장
}

public void printCustomerData(Customer customer) {
    // 고객 데이터를 출력
}

3. 작은 함수와 클래스 사용

작은 함수와 클래스를 사용하면 코드의 가독성과 재사용성이 높아집니다. 큰 함수나 클래스는 이해하기 어렵고, 재사용하기도 어렵습니다.

// 나쁜 예시
public class CustomerService {
    public void handleCustomerData() {
        // 고객 데이터 처리
    }
}

// 좋은 예시
public class CustomerDataSaver {
    public void save(Customer customer) {
        // 고객 데이터 저장
    }
}

public class CustomerDataPrinter {
    public void print(Customer customer) {
        // 고객 데이터 출력
    }
}

4. 주석을 최소화하고 코드로 의도를 표현

주석은 코드의 가독성을 높이는 데 도움이 될 수 있지만, 불필요한 주석은 오히려 방해가 될 수 있습니다. 따라서 주석은 코드 자체로 충분히 이해되지 않는 부분에만 사용합니다. 좋은 주석을 다는 방법은 다음과 같습니다.

  • 왜 그 코드가 존재하는지 설명: 코드를 작성한 이유나 목적을 설명합니다.
  • 복잡한 로직 설명: 복잡한 알고리즘이나 로직의 흐름을 설명합니다.
  • 중요한 결정의 근거 설명: 특정 방법을 선택한 이유나, 다른 방법을 배제한 이유를 설명합니다.
  • 의미 있는 정보를 제공: 코드의 맥락이나 중요 정보를 제공합니다.
// 나쁜 예시
int i = 0; // 변수 i를 0으로 초기화

// 좋은 예시
// 고객 목록을 반복하여 각각의 주문을 처리
for (Customer customer : customers) {
    processOrder(customer.getOrder());
}

// 특정 할인 규칙을 적용해야 하는 이유 설명
public double calculateDiscount(double totalPrice) {
    // 정액 할인 규칙 적용: 고객이 VIP 회원일 경우 10% 할인
    if (isVIPCustomer()) {
        return totalPrice * 0.9;
    }
    return totalPrice;
}

// 복잡한 로직에 대한 설명
// 이 메서드는 고객의 주문 내역을 분석하여 추천 상품을 반환합니다.
// 분석 과정에서 머신러닝 모델을 사용하며, 성능 최적화를 위해 배치 처리 방식을 채택했습니다.
public List<Product> recommendProducts(Customer customer) {
    // 추천 로직 구현
}

5. 공통 처리는 공통된 곳에서

중복 코드는 유지보수를 어렵게 만들기 때문에, 공통된 로직은 별도의 메서드나 클래스로 분리하여 재사용할 수 있도록 합니다.

// 나쁜 예시
public void sendWelcomeEmail(Customer customer) {
    String email = customer.getEmail();
    // 이메일 전송 로직
}

public void sendPasswordResetEmail(Customer customer) {
    String email = customer.getEmail();
    // 이메일 전송 로직
}

// 좋은 예시
public void sendEmail(String email, String message) {
    // 이메일 전송 로직
}

public void sendWelcomeEmail(Customer customer) {
    sendEmail(customer.getEmail(), "Welcome!");
}

public void sendPasswordResetEmail(Customer customer) {
    sendEmail(customer.getEmail(), "Reset your password");
}

6. 객체 지향 원칙을 따르기

객체 지향 프로그래밍의 원칙을 따르는 것도 클린 코드를 작성하는 데 중요합니다. 특히 단일 책임 원칙(Single Responsibility Principle, SRP)을 준수하여 각 클래스가 하나의 책임만 가지도록 설계해야 합니다.

// 나쁜 예시
public class OrderProcessor {
    public void processOrder(Order order) {
        if (isValidOrder(order)) {
            calculateTotal(order);
            saveOrder(order);
            sendConfirmationEmail(order);
        }
    }

    private boolean isValidOrder(Order order) {
        // 유효성 검사 로직
        return true;
    }

    private void calculateTotal(Order order) {
        // 총액 계산 로직
    }

    private void saveOrder(Order order) {
        // 주문 저장 로직
    }

    private void sendConfirmationEmail(Order order) {
        // 확인 이메일 발송 로직
    }
}

// 좋은 예시
public class OrderProcessor {
    private OrderValidator validator;
    private OrderCalculator calculator;
    private OrderRepository repository;
    private EmailService emailService;

    public OrderProcessor(OrderValidator validator, OrderCalculator calculator, OrderRepository repository, EmailService emailService) {
        this.validator = validator;
        this.calculator = calculator;
        this.repository = repository;
        this.emailService = emailService;
    }

    public void processOrder(Order order) {
        if (validator.isValid(order)) {
            calculator.calculate(order);
            repository.save(order);
            emailService.sendConfirmation(order);
        }
    }
}

7. 테스트 코드 작성

테스트 코드는 코드의 정확성을 보장하고, 리팩토링 시 코드의 기능이 유지되는지 확인하는 데 중요합니다. 자바에서는 JUnit과 같은 테스트 프레임워크를 사용해 테스트 코드를 작성할 수 있습니다.

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class CustomerServiceTest {

    @Test
    public void testSaveCustomerData() {
        CustomerService service = new CustomerService();
        Customer customer = new Customer("John", "Doe");
        
        service.saveCustomerData(customer);
        
        // 데이터베이스에 고객 데이터가 저장되었는지 확인
        assertNotNull(service.findCustomerById(customer.getId()));
    }
}

8. 일관된 코드 스타일

코드 스타일을 일관되게 유지하는 것은 팀 내 협업을 원활하게 하고, 코드를 읽고 이해하는 시간을 줄이는 데 도움이 됩니다. 코드 스타일 가이드를 정하고, 이를 준수하도록 합니다.

// 나쁜 예시
public class CustomerService {
public void saveCustomerData(Customer customer) {
DatabaseConnection connection = new DatabaseConnection();
connection.save(customer);
}
}

// 좋은 예시
public class CustomerService {
    public void saveCustomerData(Customer customer) {
        DatabaseConnection connection = new DatabaseConnection();
        connection.save(customer);
    }
}

9. 예외 처리를 통해 오류를 관리

적절한 예외 처리는 코드의 안정성을 높이고, 오류가 발생했을 때의 대처 방안을 명확히 합니다. 자바에서는 try-catch 블록을 사용해 예외를 처리할 수 있습니다.

// 나쁜 예시
public void saveCustomerData(Customer customer) {
    DatabaseConnection connection = new DatabaseConnection();
    connection.save(customer);
}

// 좋은 예시
public void saveCustomerData(Customer customer) {
    try {
        DatabaseConnection connection = new DatabaseConnection();
        connection.save(customer);
    } catch (DatabaseException e) {
        // 로그 기록 및 사용자에게 오류 메시지 전달
        System.err.println("Error saving customer data: " + e.getMessage());
    }
}
profile
매일은 아니더라도 꾸준히 올리자는 마음으로 시작하는 개발블로그😎

0개의 댓글