Reputation: 8921
Lets say I have a class that looks like this:
class Data
{
public Data()
{
// Stuff
}
public void Process1()
{
// Stuff
}
public void Process2()
{
// Stuff
}
}
I have several options for how to use it. The most common one is the following:
var data = new Data();
data.Process1();
data.Process2();
One alternative that I like to use requires me to modify the class:
class Data
{
public Data()
{
// Stuff
}
public Data Process1()
{
// Stuff
return this;
}
public Data Process2()
{
// Stuff
return this;
}
}
Then I can use it like so:
var data = new Data().Process1().Process2();
To which design pattern, if any, does this style of writing classes belong?
Upvotes: 2
Views: 696
Reputation: 97
Take a look at the builder pattern here, it is used in .net core startup class to create the app´s configuration via ConfigurationBuilder object, and they use the chained calls:
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json",
optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json",
optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
Upvotes: 0
Reputation: 117124
A method on a fluent interface should, in my opinion, return a new instance of the source object with the state updated by that method. Otherwise it's easy to write misleading code.
Take this code for example:
public class Data
{
public double Value { get; private set; }
public Data(double value) { this.Value = value; }
public Data Times2Add1()
{
this.Value = this.Value * 2.0 + 1.0;
return this;
}
public Data Divide3()
{
this.Value = this.Value / 3.0;
return this;
}
}
If I run this:
var x = new Data(5);
var y = x.Times2Add1();
var z = x.Divide3();
Console.WriteLine(x.Value);
Console.WriteLine(y.Value);
Console.WriteLine(z.Value);
I get:
3.66666666666667 3.66666666666667 3.66666666666667
However, if I write it like this:
public class Data
{
public double Value { get; private set; }
public Data(double value) { this.Value = value; }
public Data Times2Add1()
{
return new Data(this.Value * 2.0 + 1.0);
}
public Data Divide3()
{
return new Data(this.Value / 3.0);
}
}
The results are
5 11 1.66666666666667
And of course I can write var w = x.Times2Add1().Divide3();
which gives me the 3.66666666666667
I got above, but this time it makes more sense to me. It becomes testable robust code.
LINQ does it properly - calling .Where
, for example, on an enumerable doesn't alter the enumerable but instead returns a new one. That's the best way to write a fluent interface.
When you see return this;
, even though that's a fluent interface, I would consider it code smell.
Upvotes: 4