patterncsharpMinor
Extracting pattern and simplifying testing
Viewed 0 times
testingextractingsimplifyingandpattern
Problem
I observe the same pattern in a number of my classes but can't extract/abstract it due the tight coupling inside each particular implementation.
Having the class accepting an optional number of dependencies onto its constructor:
With the single method passing its arguments to the first dependency. Passing result to the second. And so on. Returning result of the last dependency:
(names of the classes, methods and variables are random, just to illustrate the pattern)
Can it be refactored to decouple the flow from the types of dependencies, arguments and return values?
It also will simplify the (unit) testing because currently I make sure that a dependency N passes its result to a dependency N+1:
Having the class accepting an optional number of dependencies onto its constructor:
public Repository(IBuilder, IFormatter, ILoader, ISelector)With the single method passing its arguments to the first dependency. Passing result to the second. And so on. Returning result of the last dependency:
public XElement Do(int i)
{
string q = _builder.Build(i);
string f = _formatter.Format(q);
XDocument d = _loader.Load(f);
XElement r = _selector.Select(d);
return r;
}(names of the classes, methods and variables are random, just to illustrate the pattern)
Can it be refactored to decouple the flow from the types of dependencies, arguments and return values?
It also will simplify the (unit) testing because currently I make sure that a dependency N passes its result to a dependency N+1:
[TestMethod]
public void Do_Should_Pass_Result_Of_Build_To_Format()Solution
One option would be to create a generic method that accepts delegates to the methods:
The implementation would look like this:
The implementation would need to have overloads for different number of delegates.
Also, I'm not completely sure whether this actually improves the situation. Your original code is very straightforward, this code is harder to understand, because it's not immediatelly clear what does
var combined = Combine(_builder.Build, _formatter.Format, _loader.Load, _selector.Select);
return combined(i);The implementation would look like this:
public static Func Combine(
Func f1, Func f2, Func f3, Func f4)
{
return input =>
{
var r1 = f1(input);
var r2 = f2(r1);
var r3 = f3(r2);
var r4 = f4(r3);
return r4;
};
}The implementation would need to have overloads for different number of delegates.
Also, I'm not completely sure whether this actually improves the situation. Your original code is very straightforward, this code is harder to understand, because it's not immediatelly clear what does
Combine() do.Code Snippets
var combined = Combine(_builder.Build, _formatter.Format, _loader.Load, _selector.Select);
return combined(i);public static Func<T1, T5> Combine<T1, T2, T3, T4, T5>(
Func<T1, T2> f1, Func<T2, T3> f2, Func<T3, T4> f3, Func<T4, T5> f4)
{
return input =>
{
var r1 = f1(input);
var r2 = f2(r1);
var r3 = f3(r2);
var r4 = f4(r3);
return r4;
};
}Context
StackExchange Code Review Q#38158, answer score: 3
Revisions (0)
No revisions yet.