목록읽을거리/리팩터링 (13)
구어체로 설명하는 다이어리

단계 쪼개기 const orderData = orderString.split(/\s+/);const productPrice = priceList[orderData[0].split('-')[1]];const orderPrice = parseInt(orderData[1]) * productPrice; ▼ const orderRecord = parseOrder(order);const orderPrice = price(orderRecord, priceList);function parseOrder(aString) { const values = aString.split(/\s+/); return { productID: values[0].split("-")[1], quantity: parseInt(v..

여러 함수를 변환 함수로 묶기 function base(aReading) { ...}function taxableCharge(aReading) { ...} ▼ function enrichReading(argReading) { const aReading = _.clonedeep(argReading); aReading.baseCharge = base(aReading); aReading.taxableCharge = taxableCharge(aReading); return aReading;} 배경소프트웨어는 데이터를 입력받아서 여러 가지 정보를 도출하곤 한다. 이렇게 도출된 정보는 여러 곳에서 사용될 수 있는데, 그러다 보면 이 정보가 사용되는 곳마다 같은 도출 로직이 반복되기도 한다. 나는 ..

여러 함수를 클래스로 묶기 function base(aReading) { ...}function taxableCharge(aReading) { ...}function calculateBaseCharge(aReading) { ...} ▼ class Reading { base() { ... } taxableCharge() { ... } calculateBaseCharge() { ... }} 배경클래스는 대다수의 최신 프로그래밍 언어가 제공하는 기본적인 빌딩 블록이다. 클래스는 데이터와 함수를 하나의 공유 환경으로 묶은 후, 다른 프로그램 요소와 어우러질 수 있도록 그중 일부를 외부에 제공한다. 클래스는 객체 지향 언어의 기본인 동시에 다른 패러다임 언어에도 유용하다. ..

매개변수 객체 만들기 function amountInvoiced(startDate, endDate) {...}function amountReceived(startDate, endDate) {...}function amountOverdue(startDate, endDate) {...} ▼ function amountInvoiced(aDateRange) {...}function amountReceived(aDateRange) {...}function amountOverdue(aDateRange) {...} 배경데이터 항목 여러 개가 이 함수에서 저 함수로 함께 몰려다니는 경우를 자주 본다. 나는 이런 데이터 무리를 발견하면 데이터 구조 하나로 모아주곤 한다. 데이터 뭉치를 데이터 구조로 묶으면 데이터..

변수 이름 바꾸기 let a = height * width; ▼ let area = height * witdh; 배경명확한 프로그래밍의 핵심은 이름짓기다. 변수는 프로그래머가 하려는 일에 관해 많은 것을 설명해준다. 단, 이름을 잘 지었을 때만 그렇다. 사실 나는 이름을 잘못 지을 때가 많다. 고민을 충분히 하지 않아서거나, 개발을 더 하다 보니 문제에 대한 이해도가 높아지거나, 혹은 사용자의 요구가 달라져서 프로그램의 목적이 변해 그럴 때도 있다. 특히 이름의 중요성은 그 사용 범위에 영향을 많이 받는다. 한 줄짜리 람다식lambda expression에서 사용하는 변수는 대체로 쉽게 파악할 수 있다. 맥락으로부터 변수의 목적을 명확히 알 수 있어서 한 글자로 된 이름을 짓기도 한다. 마찬가지로..

변수 캡슐화하기 let defaultOwner = { firstName: '마틴', lastName: '파울러' }; ▼ let defaultOwnerData = { firstName: '마틴', lastName: '파울러' };export function defaultOwner() { return defaultOwnerData;}export function setDefaultOwner(arg) { defaultOwnerData = arg;} 배경리팩터링은 결국 프로그램의 요소를 조작하는 일이다. 함수는 데이터보다 다루기가 수월하다. 함수를 사용한다는 건 대체로 호출한다는 뜻이고, 함수의 이름을 바꾸거나 다른 모듈로 옮기기는 어렵지 않다. 여차하면 기존 함수를 그대로 둔 채 전달forward ..

함수 선언 바꾸기 function circum(radius) { ...} ▼ function circumference(radius) { ...} 배경함수는 프로그램을 작은 부분으로 나누는 주된 수단이다. 함수 선언은 각 부분이 서로 맞물리는 방식을 표현하며, 실질적으로 소프트웨어 시스템의 구성 요소를 조립하는 연결부 역할을 한다. 건축과 마찬가지로 소프트웨어도 이러한 연결부에 상당히 의존한다. 연결부를 잘 정의하면 시스템에 새로운 부분을 추가하기가 쉬워지는 반면, 잘못 정의하면 지속적인 방해 요인으로 작용하여 소프트웨어 동작을 파악하기 어려워지고 요구사항이 바뀔 때 적절히 수정하기 어렵게 한다. 다행히 소프트웨어는 소프트하기 때문에 연결부를 수정할 수 있다. 단 주의해서 해야 한다. 이러한 연..

변수 인라인하기 let basePrice = anOrder.basePrice;return basePrice > 1000; ▼ return anOrder.basePrice > 1000; 배경변수는 함수 안에서 표현식을 가리키는 이름으로 쓰이며, 대체로 긍정적인 효과를 준다. 하지만 그 이름이 표현식과 다를 바 없을 때도 있다. 또 변수가 주변 코드를 리팩터링하는 데 방해가 되기도 한다. 이럴 때는 그 변수를 인라인하는 것이 좋다. 절차대입문의 우변(표현식)에서 부작용이 생기지는 않는지 확인한다.변수가 불변으로 선언되지 않았다면 불변으로 만든 후 테스트한다.이렇게 하면 변수에 값이 단 한 번만 대입되는지 확인할 수 있다.이 변수를 가장 처음 사용하는 코드를 찾아서 대입문 우변의 코드로 바꾼다.테스트한..

변수 추출하기 return order.quantity * order.itemPrice - Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 + Math.min(order.quantity * order.itemPrice * 0.1, 100); ▼ const basePrice = order.quantity * order.itemPrice;const quantityDiscount = Math.math(0, order.quantity - 500) * order.itemPrice * 0.05;const shipping = Math.min(basePrice * 0.1, 100);return basePrice = quantityDiscount + shi..

함수 인라인하기 function getRating(driver) { return moreThanFiveLateDeliveries(driver) ? 2 : 1;}function moreThanFiveLateDeliveries(driver) { return driver.numberOfLateDeliveries > 5;} ▼ function getRating(driver) { return (driver.numberOfLateDeliveries > 5) ? 2 : 1;} 배경이 책은 목적이 분명히 드러나는 이름의 짤막한 함수를 이용하기를 권한다. 그래야 코드가 명료해지고 이해하기 쉬워지기 때문이다. 하지만 때로는 함수 본문이 이름만큼 명확한 경우도 있다. 또는 함수 본문 코드를 이름만큼 깔끔하게 리팩..