TechWorkRamblings

by Mike Kalvas

202205121023 Use values as the boundary

Using values as the boundaries of your classes/objects/functions/services or w/e is important in testing because it gives you isolation for free.

This is a fairly functional approach. The idea is that there's not this class that has dependencies on a different thing that it calls inside of it. There is simply a passing of values in and out of the thing that does work on it.

For testing, we want a functional core with many decisions/paths, with none or few dependencies. These are easy to isolate and unit test. Then we want a shell that brings the dependencies together, but has very few decisions/paths. These are then the candidates for integration tests.

Values become messages. If values are messages, you get concurrency for free because you have a message passing system. Values afford shifting boundaries.

E.g. via the actor model

actor Sweeper
  User.all.each { |user| ExpiredUsers.push(user) }
  die
end

actor ExpiredUsers
  user = pop
  late = user.active? && user.paid_at < 1.month.ago
  BillingProblemNotification.push(user) if late
end

actor BillingProblemNotification
  UserMailer.billing_problem(pop)
end