-
Notifications
You must be signed in to change notification settings - Fork 7
6.10 콤비네이터:가장 뛰어난 소프트웨어 컴포넌트 추상화
chomg edited this page Sep 19, 2016
·
1 revision
기존 코드의 조합으로 새로운 원하는 코드를 작성할 수 있는 컴포넌트 모델이 객체지향 패러다임에서는 성공적으로 지원되지 않았다. 함수형 언어에서는 컬렉션으로부터 시작해서, 순수 고차 함수 등을 이용하여 공통된 연산을 제공한다. 각 연산에서 부수 효과가 안 일어나며, 원래 컬렉션에서 원소를 걸러 내거나, 변환하기 위한 구체적인 작업을 수행할 다른 함수를 인자로 받는다. 이런 고차 함수는 조합수학의 콤비네이터라는 수학적 개념과 관련이 깊다.
콤비네이터 함수를 함께 조합하면 상대적으로 적은 양의 코드를 사용해서 단순하지 않은 동작을 만들어낼 수 있다. 또한 데이터를 특정 문제를 위해 구현해야 할 필요가 있는 동작으로부터 분리할 수 있다. 이는 데이터와 동작을 함께 묶는 일반적인 객체지향 접근방법과는 반대다.
// src/main/scala/progscala2/fp/combinators/payroll.sc
case class Employee (
name: String,
title: String,
annualSalary: Double,
taxRate: Double,
insurancePremiumsPerWeek: Double)
val employees = List(
Employee("Buck Trends", "CEO", 200000, 0.25, 100.0),
Employee("Cindy Banks", "CFO", 170000, 0.22, 120.0),
Employee("Joe Coder", "Developer", 130000, 0.20, 120.0))
// Calculate weekly payroll:
val netPay = employees map { e =>
val net = (1.0 - e.taxRate) * (e.annualSalary / 52.0) -
e.insurancePremiumsPerWeek
(e, net)
}
// "Print" paychecks:
println("** Paychecks:")
netPay foreach {
case (e, net) => println(f" ${e.name+':'}%-16s ${net}%10.2f")
}
// Generate report:
val report = (netPay foldLeft (0.0, 0.0, 0.0)) {
case ((totalSalary, totalNet, totalInsurance), (e, net)) =>
(totalSalary + e.annualSalary/52.0,
totalNet + net,
totalInsurance + e.insurancePremiumsPerWeek)
}
println("\n** Report:")
println(f" Total Salary: ${report._1}%10.2f")
println(f" Total Net: ${report._2}%10.2f")
println(f" Total Insurance: ${report._3}%10.2f")
출력결과
** Paychecks:
Buck Trends: 2784.62
Cindy Banks: 2430.00
Joe Coder: 1880.00
** Report:
Total Salary: 9615.38
Total Net: 7094.62
Total Insurance: 340.00
Employee의 정의
- 튜플이 아닌 case class로 정의하여, 의미가 있는 이름을 사용하였다. (기반 컬렉션 v.s. 전용 타입의 trade-off)
- 거의 기능이 없다 (전통적인 객체 지향 설계에서는 급여계산 등의 논리가 들어갔을 것임) -> 관심사의 분리(separation of concerns)
- 참고: 전용 타입을 사용할 때, 인스턴스를 만들 때의 부가 비용이 들기도 함 -> 18장 빅데이터에서 추가 설명