[rust] 러스트 코드의 리팩터링 패턴
러스트는 안전하고 병렬 처리가 쉬운 언어이지만, 러스트로 작성된 코드도 계속해서 유지보수되고 리팩터링되어야 합니다. 이러한 과정에서 리팩터링 패턴을 활용하여 코드를 더 깔끔하게 만들 수 있습니다. 이번 블로그에서는 러스트 코드의 리팩터링 패턴 몇 가지를 살펴보겠습니다.
1. Extract Function
기능이 긴 함수를 작게 분해하는 Extract Function 패턴은 코드를 읽기 쉽고 이해하기 쉽게 만들어줍니다. 이 패턴을 활용하면 함수의 목적을 더 명확하게 드러낼 수 있습니다. 또한, 테스트하기도 쉬워지며, 코드를 재사용하기도 용이해집니다.
예시:
fn calculate_total_price(products: Vec<Product>) -> f64 {
let mut total_price = 0.0;
for product in products.iter() {
total_price += product.price;
}
return total_price;
}
fn calculate_total_price_refactored(products: Vec<Product>) -> f64 {
products.iter().map(|product| product.price).sum()
}
2. Replace Iteration with Higher-Order Functions
반복문을 고차 함수로 대체하는 패턴은 코드를 보다 간결하고 함수형 프로그래밍 스타일로 변환할 수 있습니다. 특히 러스트의 반복문 대신 map
, filter
, fold
등의 고차 함수를 활용하면 코드를 더 간결하게 만들 수 있습니다.
예시:
fn find_even_numbers(numbers: Vec<i32>) -> Vec<i32> {
let mut even_numbers = vec![];
for number in numbers.iter() {
if number % 2 == 0 {
even_numbers.push(*number);
}
}
return even_numbers;
}
fn find_even_numbers_refactored(numbers: Vec<i32>) -> Vec<i32> {
numbers.iter().filter(|&number| number % 2 == 0).cloned().collect()
}
3. Introduce Parameter Object
파라미터가 많은 함수의 경우, Introduce Parameter Object 패턴을 활용하여 파라미터를 하나의 객체로 묶을 수 있습니다. 이를 통해 함수의 시그니처를 간결하게 만들고, 관련된 데이터를 논리적으로 묶을 수 있습니다.
예시:
fn calculate_order_total(price: f64, quantity: i32, tax_rate: f64) -> f64 {
price * quantity as f64 * (1.0 + tax_rate)
}
struct Order {
price: f64,
quantity: i32,
tax_rate: f64,
}
fn calculate_order_total_refactored(order: Order) -> f64 {
order.price * order.quantity as f64 * (1.0 + order.tax_rate)
}
이처럼, Extract Function, Replace Iteration with Higher-Order Functions, Introduce Parameter Object 등의 리팩터링 패턴을 적절히 활용하여 러스트 코드를 더 깔끔하고 유지보수 가능하게 만들 수 있습니다.