In a C++ book, the author says we no longer need a function with a long parameter list because most of the parameters can be refactored into state variables in a class. On the other hand, a functional programming book says state variables are evil because it causes side-effects which cause bug-prone and hard to parallelize code. I'm getting puzzled. Should the code avoid relying on state variables as much as possible by moving its state variable into the function parameter list?
3 Answers
Depends if you are programming in a procedural
or functional
paradigm. Mutable state is required for the former and crippling for the later. This is apples and oranges. They are both correct in their on bailiwicks!
You can apply single assignment and other functional techniques to imperative procedural languages, immutable state makes concurrent programming more deterministic, but making every object immutable in a language like Java or C++ is almost impossible because their memory models don't easily support this paradigm.
-
:Thanks! The book <<97 things every programmer should know>> says we should apply functional programming principles such as avoid side-effect. Can't we apply functional programming principles in an imperative code context?– TomCapsSep 19, 2011 at 1:35
-
State is not required for procedural programming. It is common, but not required. That it is common is due more to habits than anything else. Though I'll admit that there are certainly situations where keeping a (state) variable around is easier than the alternatives (e.g. asynchronous processing). Sep 19, 2011 at 6:16
-
@Marjan anything that has immutable variables is state– user7519Sep 19, 2011 at 15:43
-
@Jarrod: Now you got me confused. Reading your answer again I see I missed the "Mutable" in "Mutable state is required". But your comment seems to say that having immutable variables is state. Don't get it. Could be because I am not used to throwing around and thinking about mutable and immutable in these terms. Any reference(s) for me to read? Sep 19, 2011 at 18:16
-
@MarjanVenema: Yes, having immutable variables is state. The difference in handling state between procedural and functional programming is not that proc.prog. has state, and functional does not - rather, the difference is that proc. prog. has mutable state, whereas state is always immutable in (pure) functional programming. See e.g. en.wikipedia.org/wiki/Purely_functional , which explains that purely functional languages avoid updates.– sleskeSep 20, 2011 at 9:01
If I understand your question right, you are questioning what conditions qualify either the use of a parameter or class variable/member/field/etc? I'm assuming you're referring to a method, and not a function. If this is about C++ specifically, I suggest moving your question to stack overflow.
A long parameter list may be a sign that you might need to refactor your method into a set of more granular ones. Generally, using parameters will make your code more loosely coupled. I'm not sure if this is true for most modern OO languages anymore, but object creation can be expensive, especially if there are many class variables involved; so, if your class variables were objects and were referenced frequently in a program, then they may be justified as being class variables.
Also:
- Could other methods make use of the class variables? If yes, then consider going with class variables.
- Is your method public? If public, use parameters.
- Can your parameter list appropriately be represented as a hash/map/array/collection/list/etc? If so, consider it an option.
- Is your method static? If yes, use parameters.
No, state variables per se do not cause side effects.
Calling a setter method (on a data structure that is visible elsewhere) is a side effect.
You can have data structures to hide long parameter lists ansd yet avoid side effects if you construct them accordingly. Here is a small example (in Java, untested):
class ManyParams {
final String theName = null;
final int theAge = 0:
ManyParams() {}
ManyParams(String a, int b) { theName=a; theAge = b; }
public withName(String n) {
return new ManyParams(n, this.theAge);
}
public withAge(int i) {
return new ManyParams(theName, i);
}
}
/// to be used like this
foo(new ManyParams.withName("John").withAge(42));
Of course, the constructor of ManyParams will still have a long parameter list this way. But its hidden.