Experimentation, dotnet style
Safe (ish!) experimentation and continuous improvements are key to healthy codebases. We discussed https://github.com/scientistproject/Scientist.net yesterday, so I thought I'd get Cursor using GPT-5 to knock up a swift dotnet8 example.
A few birds with one stone as it were. AI, latest model and cursor version trial, and a dotnet library that I wasn't familiar with. Win win.
Set up the experiment within the GET method.
app.MapGet("/api/data/randomdata", () =>
{
var result = Scientist.Science<string>("random-data-experiment", experiment =>
{
In this case, I chose to return a static json response as my control:
experiment.Use(() =>
{
var data = new
{
Id = Random.Shared.Next(1, 1000),
Name = $"Item{Random.Shared.Next(1, 100)}",
Timestamp = DateTime.UtcNow
};
return JsonSerializer.Serialize(data);
});
});and return some json read from a file as the experiment:
experiment.Try(() =>
{
var filePath = Path.Combine(app.Environment.ContentRootPath, "Data", "sample.json");
return System.IO.File.ReadAllText(filePath);
});Here's the console outputter from earlier.
using System;
using System.Threading.Tasks;
using GitHub;
namespace ScientistDemo.Infrastructure
{
public class ConsoleResultPublisher : IResultPublisher
{
public Task Publish<T, TClean>(Result<T, TClean> result)
{
Console.WriteLine($"[Scientist] Experiment: {result.ExperimentName}");
Console.WriteLine($"[Scientist] Matched: {result.Matched}");
Console.WriteLine($"[Scientist] Control: value={Format(result.Control.Value)}, duration={result.Control.Duration}, exception={(result.Control.Exception == null ? "none" : result.Control.Exception.GetType().Name)}");
foreach (var candidate in result.Candidates)
{
Console.WriteLine($"[Scientist] Candidate '{candidate.Name}': value={Format(candidate.Value)}, duration={candidate.Duration}, exception={(candidate.Exception == null ? "none" : candidate.Exception.GetType().Name)}");
}
if (!result.Matched)
{
Console.WriteLine("[Scientist] Mismatch detected!");
}
return Task.CompletedTask;
}
private static string? Format(object? value)
{
return value?.ToString();
}
}
}By adding the following, we can actually get the output logged somewhere we can read it:
// Configure Scientist to publish results to console
Scientist.ResultPublisher = new ConsoleResultPublisher();Here's the console output.
[Scientist] Experiment: random-data-experiment
[Scientist] Matched: False
[Scientist] Control: value={"Id":754,"Name":"Item50","Timestamp":"2025-09-04T10:59:44.315161Z"}, duration=00:00:00.0074269, exception=none
[Scientist] Candidate 'candidate': value={
"Id": 1,
"Name": "SampleItem",
"Timestamp": "2025-09-04T10:44:17Z"
}
, duration=00:00:00.0008843, exception=none
[Scientist] Mismatch detected!Full code here: https://github.com/adrenalinehit/dotnet-scientest/tree/main
There's plenty more scientist.net can do. Do check out its documentation on github.
Thanks for reading.
Comments