proofit404 / stories

Service objects designed with OOP in mind.
https://proofit404.github.io/stories/
BSD 2-Clause "Simplified" License
297 stars 21 forks source link

Validate early, error lately. #720

Open proofit404 opened 1 year ago

proofit404 commented 1 year ago

Let say we would have nested stories.

class Purchase(Story):
    I.fetch_discount
    when('has_discount') > I.apply_discount

In that case, we have :chicken: and :egg: problem.

  1. fetch discount would set has_discount and discount variables.
  2. apply discount expect discount to be not null domain object
  3. if discount is null, apply discount would not be executed in any case
  4. if discount exists, apply discount would run
  5. What kind of contract we need to write for discount variable?

I could see couple of options here.

  1. Make discount nullable, which would broke apply discount story expectation but would not have state union error
  2. Raise validation error on first attribute access, not on attribute assign. We would need to have different variables for discount for different stories. Apply discount would never executed, so it would never access invalid discount variable, so validation error would not be raised.
  3. Do not assign invalid discount in the first place. We would have if statement inside fetch discount method which would only assign has discount variable in case discount is null.

I suggest we document pattern number 3 from the list above and call it a day.