How to write code that fits the domain model
#code #ruby #summary #boring #write #surprise #leastsurprise
This is a summary for:
https://stanko.io/keep-it-boring-dont-surprise-me-52opnwWR6CBh
Here is the summary in text:
# Code Summary for article
#
# https://stanko.io/keep-it-boring-dont-surprise-me-52opnwWR6CBh
# part 1/4 : Sample code surprising and simple
PurchaseChargerService(
purchase: PurchaseBuilderService.new(line_items: line_items).call,
form: purchase_form,
user: current_user
).call
# Why the code ☝️ is surprising:
# > "Nobody expects things like `PurchaseChargerService` and `PurchaseBuilderService` to exist, yet alone that you have to call those in succession with a form object and the current user to make a purchase."
user.purchase(line_items)
.charge(authorization_code: params[:authorization_code])
# Why the code ☝️ is simple?
# > "While most people working on a web shop expect that a user can just purchase something, and that a purchase can be charged."
# Part 2/4 : Lesson 1: Embrace the domain you are working with
# "Naming something after what it does and putting it next to the thing it works with tells a story that can help people understand what’s going on"
# Rename (location: app/services/purchase_charger_service.rb)
class PurchaseChargerService; end
# To (location: app/models/purchases/charger.rb)
module Purchases
class Charger; end
end
# Part 3/4 : Lesson 2: Write code that mimics how people think about the domain
# "If a `User` can purchase line items, then add a `purchase` method to the User model that accepts line items"
class User
# @return [Purchase]
def purchase(line_items)
end
end
# Part 4/4: Lesson 3: Extract actions into models to tell a story
#
# "Don’t create new classes just to keep things DRY. If your model has many small or a single large method that deal with a single action, extract it into its own model."
class Purchase
# @return [Purchases::Charge]
def charge(authorization_code:)
Purchases::Charger.new.call
end
end