steliosbl
steliosbl

Reputation: 8921

Design pattern with methods that return modified parent

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

Answers (2)

Elias Navarro
Elias Navarro

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

Enigmativity
Enigmativity

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

Related Questions