JaeWon's Devlog
article thumbnail
반응형

클린코드(CleanCode)를 읽고 간략하게 정리한 글입니다.

 


1. 14장. 점진적인 개선

1.1. 1. 점진적인 개선의 중요성

  • 지속적 개선
    - 소프트웨어는 한 번에 완벽해질 수 없다.
    - 꾸준한 점진적 개선이 필요하다.
    - 작은 변경을 자주 적용하는 방식이 대규모 변경을 한 번에 적용하는 것보다 효과적이다.
  • 유지보수성 향상
    - 코드는 시간이 지남에 따라 변경되고 개선되어야 유지보수성이 높아진다.
    - 점진적인 개선은 코드를 최신 상태로 유지하는 데 중요하다.

1.2. 2. 개선 방법

1.2.1. 2-1. 리팩토링

  • 정의
    - 리팩토링은 소프트웨어의 기능을 변경하지 않으면서 코드를 재구성하는 것을 의미한다.
  • 목표
    - 코드를 더 읽기 쉽고 이해하기 쉽게 만들며, 중복을 제거하고, 구조를 개선한다.
  • 방법
    - 작은 단위로 점진적으로 리팩토링한다.
    - 하나의 작업을 끝내고 테스트를 통과한 후에 다음 작업으로 넘어간다.

1.2.2. 2-2. 테스트 주도 개발(TDD)

  • 정의
    - 테스트를 먼저 작성하고, 그 테스트를 통과하는 코드를 작성하는 개발 방식
  • 목표
    - 코드가 예상대로 동작하는지 확인하고, 리팩토링을 안전하게 수행
  • 방법
    - 새로운 기능을 추가할 때마다 먼저 테스트를 작성하고, 테스트가 실패하면 코드를 작성하여 통과시킴

1.2.3. 2-3. 작은 단위의 변경

  • 정의
    - 작은 단위로 자주 변경하는 것이 큰 단위로 드물게 변경하는 것보다 낫다.
  • 목표
    - 변경 사항을 쉽게 이해하고, 버그 발생 가능성을 줄이며, 문제 발생 시 원인을 쉽게 찾을 수 있게 한다.
  • 방법
    - 변경할 부분을 작게 나누어, 각 변경 후에 테스트를 수행하여 코드의 안정성을 유지한다.

1.3. 3. 코드 리뷰와 피드백

  • 코드 리뷰
    - 코드 리뷰는 다른 개발자의 피드백을 받아 코드를 개선하는 중요한 과정이다.
    - 코드 리뷰를 통해 코드 품질을 높이고, 잠재적인 문제를 사전에 발견할 수 있다.
  • 피드백 루프
    - 짧은 피드백 루프를 유지하여 빠르게 개선점을 반영한다.
    - 이는 개발 과정에서 지속적으로 학습하고 성장할 수 있게 한다.

1.4. 4. 개선 문화

  • 지속적 개선 문화
    - 팀 전체가 점진적 개선의 중요성을 이해하고, 이를 실천하는 문화를 조성한다.
    - 코드의 품질을 높이기 위해 누구나 개선 제안을 할 수 있는 환경을 만든다.
  • 자동화
    - 빌드, 테스트, 배포 과정을 자동화하여 개발 주기를 단축하고, 반복 작업을 줄여 점진적인 개선을 촉진한다.

1.5. 5. 리팩토링 예제

- 간단한 은행 계좌 클래스를 리팩토링하고 점진적으로 개선하는 과정

1.5.1. 5-1. 초기 코드

- 먼저 기본적인 은행 계좌 클래스와 관련 메소드를 작성한다.

<java />
public class BankAccount { private double balance; public BankAccount(double initialBalance) { this.balance = initialBalance; } public void deposit(double amount) { if (amount > 0) { balance += amount; } } public void withdraw(double amount) { if (amount > 0 && amount <= balance) { balance -= amount; } } public double getBalance() { return balance; } }

1.5.2. 5-2. 테스트 코드

- TDD를 위해 은행 계좌 클래스의 동작을 검증하는 테스트 코드를 작성한다.

<java />
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; public class BankAccountTest { @Test public void testDeposit() { BankAccount account = new BankAccount(100); account.deposit(50); assertEquals(150, account.getBalance()); } @Test public void testWithdraw() { BankAccount account = new BankAccount(100); account.withdraw(50); assertEquals(50, account.getBalance()); } @Test public void testWithdrawMoreThanBalance() { BankAccount account = new BankAccount(100); account.withdraw(150); assertEquals(100, account.getBalance()); } }

1.5.3. 5-3. 리팩토링 1 : 중복 코드 제거

- 입금과 출금 메소드의 검증 로직을 별도의 메소드로 추출하여 중복 코드를 제거한다.

<java />
public class BankAccount { private double balance; public BankAccount(double initialBalance) { this.balance = initialBalance; } public void deposit(double amount) { if (isValidAmount(amount)) { balance += amount; } } public void withdraw(double amount) { if (isValidAmount(amount) && amount <= balance) { balance -= amount; } } public double getBalance() { return balance; } // 중복 코드 메소드로 추출 private boolean isValidAmount(double amount) { return amount > 0; } }

1.5.4. 5-4. 리팩토링 2: 예외 처리 추가

- 입금 또는 출금 시 잘못된 금액에 대한 예외 처리를 추가한다.

<java />
public class BankAccount { private double balance; public BankAccount(double initialBalance) { this.balance = initialBalance; } public void deposit(double amount) { if (!isValidAmount(amount)) { // 예외 처리 추가 throw new IllegalArgumentException("Amount must be greater than zero"); } balance += amount; } public void withdraw(double amount) { if (!isValidAmount(amount)) { throw new IllegalArgumentException("Amount must be greater than zero"); } if (amount > balance) { throw new IllegalArgumentException("Insufficient balance"); } balance -= amount; } public double getBalance() { return balance; } private boolean isValidAmount(double amount) { return amount > 0; } }

1.5.5. 5-5. 예외 처리 테스트 추가

- 새로운 예외 처리 로직에 대한 테스트를 추가하여 TDD 를 유지한다.

<java />
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; public class BankAccountTest { @Test public void testDeposit() { BankAccount account = new BankAccount(100); account.deposit(50); assertEquals(150, account.getBalance()); } @Test public void testWithdraw() { BankAccount account = new BankAccount(100); account.withdraw(50); assertEquals(50, account.getBalance()); } @Test public void testWithdrawMoreThanBalance() { BankAccount account = new BankAccount(100); account.withdraw(150); assertEquals(100, account.getBalance()); } @Test public void testDepositNegativeAmount() { BankAccount account = new BankAccount(100); assertThrows(IllegalArgumentException.class, () -> { account.deposit(-50); }); } @Test public void testWithdrawNegativeAmount() { BankAccount account = new BankAccount(100); assertThrows(IllegalArgumentException.class, () -> { account.withdraw(-50); }); } @Test public void testWithdrawInsufficientBalance() { BankAccount account = new BankAccount(100); assertThrows(IllegalArgumentException.class, () -> { account.withdraw(150); }); } }

1.6. 6. 결론

  • 지속적인 리팩토링
    - 점진적인 개선을 위해 지속적으로 코드를 리팩토링하고, 테스트를 통해 코드의 안정성을 확인한다.
  • 작은 단위로 자주 변경
    - 큰 단위의 변경보다 작은 단위로 자주 변경하는 것이 좋다.
  • 팀 협업과 피드백
    - 코드 리뷰와 피드백을 통해 코드 품질을 높이고, 지속적인 개선 문화를 조성한다.
반응형

'Study > CleanCode' 카테고리의 다른 글

[클린코드] 13장. 동시성  (0) 2024.07.02
[클린코드] 7장. 오류처리  (0) 2024.06.28
[클린코드] 12장. 창발성  (0) 2024.06.27
[클린코드] 11장. 시스템  (0) 2023.11.15
[클린코드] 10장. 클래스  (2) 2023.11.12
profile

JaeWon's Devlog

@Wonol

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!