Short notes from engineering

Micro-posts on programming and patterns as we build Tramline in public. Follow this feed if you find these bits interesting.


2022 / Oct 06 — 12:23
kitallis

When I originally kicked things off, I added a lot of big transactions around various api-call-surrounding-database-ops. This was knowingly a cheap hack to avoid bad state changes and delaying the inevitable: careful and tedious handling of errors and control-flow.

I'm now slowly refactoring things to unpack these big transactions and I realize many of them are actually unnecessary. I'm employing yet another cheap Result object to signify boundary-states,

Result = Struct.new(:ok?, :error, :value, keyword_init: true)

def good_op
  Result.new(ok?: true, value: 1)
end

def bad_op
  Result.new(ok?: false, error: "Did not work")
end

operation.ok?
operation.value
operation.error

This is a little bit silly, because it requires you to ensure that value is only present alongside the ok? and the others are falsey in the error case. But it is very simple and quick to get a refactor busted out.

I have used Github::Result in the past, but recently discovered dry-rb -- many of these look very sensible and immediately useful. Hopefully the next step!