Closed akamud closed 8 years ago
I would opt for option #3. You can just have the default implementation in ExperimentBuilder perform a simple Equal but allow the user to set a different comparison function. It seems that would match the Ruby API the best.
So I made a thing https://github.com/Haacked/Scientist.net/pull/26
When you setup a test you optionally can pass in a Func<T, T, bool>
or a IEqualityComparer<T>
if neither are passed in the the default rules are applied
Specifically it checks like this:
/// <summary>
/// Checks if two ExperimentResults are equal
/// </summary>
/// <param name="controlResult">Control ExperimentResult</param>
/// <param name="candidateResult">Candidate ExperimentResult</param>
/// <returns>
/// Returns true if:
///
///
/// The values of the observations are equal according to an IEqualityComparer<T> expression, if given
/// The values of the observations are equal according to a comparison function, if given
/// Both observations raised an exception with the same Type and message.
/// The values of the observation are both null
/// The values of the observations are equal according to Ts IEquatable<T> implementation, if implemented
/// The values of the observations are equal (using .Equals())
///
/// Returns false otherwise.
/// </returns>
Thoughts? Comments?
Similar to Ruby's original code.
I'm willing to implement this, but I would like to discuss the preferred implementation. I see a few ways to do this in C#:
1. Use an optional parameter
We could make
Science
have an optional parameterFunc<T, T, bool>
that would be called at the end of the experiment if it is not null.I implemented this in my fork, you can see the changes needed here.
2. Add a property in Scientist class
Very similar to # 1, but instead of passing an optional parameter you would make Scientist generic (
Scientist<T>
), having a propertyFunc<T, T, bool> Comparer
that could be set like anObservationPublisher
.This would change the way the lib is used right now, as a type parameter would have to be passed in
Scientist
class but no parameter would be needed in theScience
method anymore.Old way:
New way
From my point of view this would make the code a little less clean, as the type would have to be used anytime the Scientist object is referenced.
3. Change
Experiment<T>
interfaceRuby's implementation of Comparator is inside the
Experiment
class, doing that in C# would make implementing theCompare
method required, even for straightforward value types' comparison.Maybe we could provide an abstract
Experiment
class that would be easier to implement (defaultCompare
virtual method using default C# comparators?) allowing the user to override when needed?What do you think? Does any of these make sense? Is there a simpler more idiomatic way of doing this in C#?