I have different data modules, which take a couple of parameters from a configuration list. Do you think it's ok to pass a configuration object as a whole module1(config)
and let the module pick what it needs, or should I rather pass the individual parameters module1(config.a, config.c, config.f)
?
The first case doesn't require change interfaces in case I need more configuration parameters, but the second case encapsules more?
4 Answers
The parameter object pattern is widely used in .NET and other object oriented frameworks.
This is essentially what you are describing what talking about passing in a single object and is considered a good practice, so long as the individual parameters have good defaults (so the modules will work even when only some of the parameters are passed in).
If your modules don't have a use for all items in the configuration object I would call this a code smell, however. If they are not needed, why pass them in? The configuration object should match the needs of the module.
-
I'm afraid I have the latter code smell option. The config is some "global" project config and most modules need only a subset. In that case you would advise against it? Does it have a particular explanation (a scenario when this breaks).– GereCommented Jun 14, 2012 at 18:42
-
@Gerenuk - It is difficult to say. If the configuration is immutable you could be OK, but if anyone can change it, then it becomes a shared global resource which can be very difficult to work with.– OdedCommented Jun 14, 2012 at 18:44
So you want to write this method Module1, which depends on some subset of the properties of a Configuration object.
Some reasones you might want Module1 to take the Configuration object as a single parameter:
Future versions of Module1 might use additional properties of the Configuration object. This would require changes to every call site if you use individual parameters. (This might not matter too much if Module1 is only exposed internally to your own project, and you have and IDE with strong refactoring features. It matters a lot if it is part of a publicly published API.)
At the places where you want to call Module1, you have a Configuration object available, and it is more convenient to just pass the whole object than to pass in each relevant property.
You might want Module1 to take the relevant properties as individual parameters if:
- At the places where you want to call Module1, you don't have a Configuration object available, and you can supply values for the relevant properties but not all the properties. (This is a strong reason if you are confident that future versions will not use more properties.)
So really, it depends on how you expect the method might change in the future, and how much of a burden it is to change call sites if the signature changes.
You may want to consider using an interface for your parameter itself. Your configuration object will implement the interface, but the interface should include only the properties that you can use on this method.
We call this using role interfaces, and it is an important part of the Interface Segregation Principle. It means that as your configuration object changes, you can choose which properties this particular method is interested in, and add those properties to the interface. No additional refactoring is required. And you still don't have the code smell of getting passed a lot of information you don't need.
I've found it easier to make Configuration objects static. That way, you don't have to pass them around.
The assumption behind static
is that you have a single configuration for each process. For me, so far, that assumption holds.
-
1That may be true for global configuration, but possibly not for objects that require specific configuration (say
Process
andProcessStartInfo
in .NET)– OdedCommented Jun 14, 2012 at 18:36 -
Even for global configuration, this is a smell once you even need to think about concurrent access and/or testing.– TelastynCommented Jun 14, 2012 at 20:08