top | item 46844236

(no title)

xavdid | 29 days ago

I like this pattern a lot, but it's important that the code in the dry path is representative. I've been bitten a few too many times by dry code that just runs `print("would have updated ID: 123")`, but not actually running most of the code in the hot path. Then when I run it for real, some of the prep for the write operation has a bug / error, so my dry run didn't actually reveal much to me.

Put another way: your dry code should do everything up until the point that database writes / API calls / etc actually happen. Don't bail too early

discuss

order

ziml77|28 days ago

This is why I end up creating an interface for the calls that perform modifications. Then I have one implementation that logs and one implementation that does the actual work. I end up with the output being as representative as possible as to what would happen. I also feel a lot more comfortable that a dry run truly won't write anything when the only class that could ever actually write anything is not even instantiated in dry run mode. I don't get that same comfort when there's a ton of branches sprinkled throughout checking for a dry run flag.

marhee|29 days ago

Doesn’t this conflate dry-running with integration testing? ASAIK the purpose of a dry-run is to understand what will happen, not to test what will happen. For the latter we have testing.

madeofpalk|29 days ago

> ASAIK the purpose of a dry-run is to understand what will happen

Right - so the dry-run has to actually do as much of 'what will happen' as possible, except the actual things.

You want to put the check as far down, close to the 'action' as possible. You don't want any additional business logic gated by the dry run check.

friendzis|29 days ago

> ASAIK the purpose of a dry-run is to understand what will happen, not to test what will happen. For the latter we have testing.

Not really. Testing is a way to increase confidence that code does what it is specified to do, because it is cheaper than full-blown formal analysis :)

The problem raised by OP here is granularity. Operation like `update(record, field, value)` is itself a tree of smaller sub-operations that may do some permissions checking, locking, network calls, even checking for presence of record if it has upsert semantics, all of which could fail. A dry run with a plan that is too coarse can succeed while the actual operation fails over things left unchecked.

xavdid|29 days ago

Yes, but it depends on the context.

For little scripts, I'm not writing unit tests- running it is the test. But I want to be able to iterate without side effects, so it's important that the dry mode be as representative as possible for what'll happen when something is run for real.

lanyard-textile|29 days ago

I'd argue the dry run is a form of integration testing: Essentially the writes are mocked, but the reads are still functional.