davezych / shience

A .NET port(ish) of Github's Scientist library. (https://github.com/github/scientist)
MIT License
9 stars 1 forks source link

Implement candidate run percentage #3

Closed davezych closed 8 years ago

davezych commented 8 years ago

Shience will always run the candidate and control every time. Implement functionality to allow control to always run, and candidate to be run X% of the time.

Allow specifying a global percentage, and allow overwriting that percentage per test.

MovGP0 commented 8 years ago

I think by convention, a value of 1.0d (100%) should mean that the test runs every time, while a value of 0.0d (0%) means it doesn't run. Values > 1.0d and < 0.0d should throw an ArgumentOutOfRangeException.

MovGP0 commented 8 years ago

An alternative way would be to provide overrides with an unsigned integer (ie. int, long) which means run the control method every n-th execution. A value of <= 0 should throw an ArgumentOutOfRangeException.

davezych commented 8 years ago

Currently I'm implementing it as an int, but a double might make more sense.

The nth execution is an interesting idea, but how would that really differ from specifying a percentage?

MovGP0 commented 8 years ago

the difference is mostly psychological...

davezych commented 8 years ago

The only issue I see with it is that we'll need some way of tracking the number of executions for each experiment throughout the lifetime of the application, which may or may not be difficult. Did you have an idea in mind of how to track that?

MovGP0 commented 8 years ago

I have multiple ideas what we could do:

Probabilistic

Handle the percentage as a probability. There is a fast pseudo-random number generator (ie. Random class) that puts out doubles between 0.0d and 1.0d. If the value from the RND is bigger than the percentage/probability, the code gets executed.

While this idea has the advantage of beeing handeled locally, many developers might want to have more control over it.

The user handles it

The user provides his own logic in the .When(() => ...) clause.

Singleton Dictionary

The Science object could get registered in a singleton Dictionary<string, Tuple<int, int>> (aka. hash table). The tuple represents a current "count" and a maximum "number" (Note: a properly named entity class results in cleaner code).

If the count exceeds the number, the code gets executed and the number gets set to 0.

Important: The access to the dictionary has to be thread save. So we might need to violate the Command-Query separation (CQS) principle here:

ScienceCounter.Register(scienceName, n); // initial setup (gets called every time; n may change at runtime)
bool scienceShouldExecute = ScienceCounter.IncreaseCountAndReturnTrueIfScienceShouldExecute(scienceName); 
davezych commented 8 years ago

I like the middle idea, especially since it's basically already implemented with #4:

science.Where(() => new Random().Next() % 10 == 0); //run 10% of the time
science.Where(() => counter == 5); //or something dumb like this

Where also allows us to do anything we want:

science.Where(() => DateTime.Now.Day == 1); //run only on first of month
science.Where(() => DateTime.Now.Hour == 11 && DateTime.Now.Minute == 59); //run only at 11:59 
//etc

I say we close this in favor of using Where everywhere.