Question

Several times now I have come across the situations where you have some kind of settings class that simply contains a mass of data. Often these classes are simply not valid without at least most of the data.

However a constructor like this:

public dataclass (int v1, int v2, int v3, int v4,
      string v5, double v6, string v7, int v8, 
      Internalclass v9, string v10,
      double v11, double v12, int v13, int v14)
{
   this.v1=v1;
   this.v2=v2;
   ...
   this.v14=v14; 
}

feels like it's not good code practice. Now I could try to group some of these variables together but often these variables only make sense in the context of the data class. So what is a good way to design such a data class?

Was it helpful?

Solution

You are looking for the builder pattern.

Essentially it's an object with setters where you can set the parameters for construction and a createResult() method that will create the object you are looking for (or fail if it wouldn't be valid).

You can use it to contain the defaults for the properties and group some of them into a single setter.

DataClassBuilder builder = new DataClassBuilder();

builder.setV1(v1);
builder.setV3(v3);
builder.setV4(v4);
builder.setV5AndV6(v5, v6);
//...

DataClass data = builder.createResult();

OTHER TIPS

Are all those parameters actually required? By "data class" do you mean a Domain Model, View Model or Data Transfer Object? Requiring such a large list of arguments for a simple "data class" starts to feel like a Code Smell telling you either:

  1. This class is doing too much, and much of its work should be delegated to other classes that get passed in as a dependency

  2. Not everything is needed. Optional values in data classes should not be passed in via the constructor

I think the question here is not "How do I handle a large list of constructor arguments" and instead is "How can I refactor my object model so I don't need two dozen parameters to a constructor."

The Builder Pattern will "fix" your problem, but I think it is putting a bandage on a larger problem that requires a different solution.

If your parameters are optional, the Builder pattern could be useful indeed! Though, the builder pattern can be a mess sometimes. If you use the Builder at many places, when you'll add a new parameter you'll need to make sure you don't forget to add it in every places because you won't have compile-time check.

If the parameters are not optional, you would need to verify everything has been set at the moment to call the Build method!

I'd like to propose another solution, the Introduce Parameter Object refactor.

The idea is to group your parameters (if possible) by some logic. Then, you'd have less parameters in this constructor and maybe 3-4 more "parameter classes". You could argue this moves the problem elsewhere, but it gives you more flexibility on how to create these parameter objects.

Maybe one of the "parameter object" can be created via an hardcoded factory, the other could be retrieved from a configuration file etc.

This way you create a better separation of concerns!

Licensed under: CC-BY-SA with attribution
scroll top