-
Notifications
You must be signed in to change notification settings - Fork 95
Basic usage
Josh Hiles edited this page Dec 23, 2023
·
1 revision
Let's pretend you're changing the way you handle permissions in a large web app. Tests can help guide your refactoring, but you really want to compare the current and refactored behaviors under load.
using GitHub;
...
public bool CanAccess(IUser user)
{
return Scientist.Science<bool>("widget-permissions", experiment =>
{
experiment.Use(() => IsCollaborator(user)); // old way
experiment.Try(() => HasAccess(user)); // new way
}); // returns the control value
}
Wrap a Use
block around the code's original behavior, and wrap Try
around the new behavior. Invoking Scientist.Science<T>
will always return whatever the Use
block returns, but it does a bunch of stuff behind the scenes:
- It decides whether or not to run the
Try
block, - Randomizes the order in which
Use
andTry
blocks are run, - Measures the durations of all behaviors,
- Compares the result of
Try
to the result ofUse
, - Swallows (but records) any exceptions raised in the
Try
block, and - Publishes all this information.
The Use
block is called the control. The Try
block is called the candidate.
If you don't declare any Try
blocks, none of the Scientist machinery is invoked and the control value is always returned.
- Publishing results
- Controlling comparison
- Adding context
- Expensive setup
- Keeping it clean
- Ignoring mismatches
- Enabling or disabling experiments
- Ramping up experiments
- Running candidates in parallel (asynchronous)
- Testing
- Handling errors
- Designing an experiment
- Finishing an experiment
Sometimes scientists just gotta do weird stuff. We understand.