then을 활용한 가독성 높은 코드 작성
기존의 Ruby 코드에서 여러 단계를 거치는 연산은 다음과 같이 구현될 수 있습니다.
1. 전통적인 방식 (operation_1)
ruby
def operation_1(a)
a_int = (a.to_i)
sum = a_int + 1
cube = sum ** 3
return cube
end
puts "operation_1 is: #{operation_1("3")}" # => operation_1 is: 64
이 방식은 각 단계가 명확하지만, 코드가 길어지고 중간 변수가 많아집니다.
2. 간결하지만 밀집된 방식 (operation_2_dense)
ruby
def operation_2_dense(a)
(a.to_i + 1) ** 3
end
puts "operation_2_dense is: #{operation_2_dense("3")}" # => operation_1 is: 64
이 방식은 간결하지만, 한 줄에 여러 연산이 밀집되어 있어 한눈에 이해하기 어려울 수 있습니다.
3. then을 활용한 커링(Currying) 방식 (curry)
then 메서드를 사용하면 각 연산을 별도의 블록으로 분리하여 파이프라인 형태로 연결할 수 있습니다. 이는 마치 함수형 프로그래밍의 커링과 유사한 효과를 줍니다.
ruby
def curry(a)
a.then { |i| i.to_i }
.then { |i| i + 1 }
.then { |i| i ** 3 }
end
puts "curry is #{curry("3")}" # => curry is 64
이 방식은 각 연산 단계를 시각적으로 분리하여 코드의 흐름을 직관적으로 파악할 수 있게 합니다.
4. then과 헬퍼 메서드 활용 (curry_2)
각 연산 단계를 별도의 헬퍼 메서드로 분리하면 코드의 재사용성과 모듈성이 더욱 향상됩니다.
ruby
def add_one(i)
i + 1
end
def cube(i)
i ** 3
end
def curry_2(a)
a.then { |i| i.to_i }
.then { |i| add_one(i) }
.then { |i| cube(i) }
end
puts "curry_2 is #{curry_2("3")}" # => curry_2 is 64
이 접근 방식은 각 단계의 구현 세부 사항을 숨기고, 코드의 의도를 명확하게 표현할 수 있도록 돕습니다.
tap과의 비교 및 yield_self와의 관계
then은 tap과 유사해 보이지만 목적이 다릅니다. tap은 블록 내에서 작업을 수행한 후 원래 객체를 반환하는 반면, then은 블록의 반환값을 다음 체인으로 전달합니다. 예를 들어, User.create! 후 DemoContent.create_manual을 호출하는 상황에서 tap 대신 then을 사용하여 더 간결하게 표현할 수 있습니다.
```ruby # tap 사용 예시 (원문) User.create!(user_params.merge(role: :administrator)) .tap do |user| DemoContent.create_manual(user) end
then 사용 예시 (개선 제안)
User.create_admin(user_params).then do |user| DemoContent.create_manual(user) end ```
또한, then은 Ruby의 yield_self 메서드와 기능적으로 완전히 동일합니다. 따라서 두 메서드 중 어느 것을 사용할지는 개발자의 선호도에 따라 달라질 수 있습니다.