May 17, 2018 6:38 am
Published by Manuel Dewald
Yesterday in a longer refactoring session, we stumbled across some open questions when it comes to member variables vs function parameters.
In a function with a huge number of parameters, we decided to create new class(es) to split this mess up a bit. As the new class first contained only one public function – because we moved one function out of a bigger class – we had to decide which of the parameters to choose for the input of the constructor and the actual function call, respectively.
Without being able to judge whether this is a good recipe currently, we split them up by the following classifications:
Does the variable change between calls of the public method?
If this is the case, in our it should be a function parameter. This was hard to decide for many of the input parameters, as in this state of the refactoring, every instance of the new class would be used only once to call the function.
Is the variable a member, a local variable, or a parameter in the caller?
We found it clean to treat all the parameters and local variables of the calling function that need to be passed to the new one as input parameters of this function. This should also make it easier to change the locally created object into a member of the calling class in future. Most of the member variables of the calling class have been turned into a member of the new class (although not all of them, as some could be decided based on earlier mentioned reasons).
Is the variable a pure input parameter, a complex object or subject of change?
We found it useful in our case to classify the variables we had to pass to the new class in three different types:
Pure input parameters
We created some structs to group the huge number of input parameters thematically, which turned out to be a good idea later in the process as we could find subfunctions and classes taking one of those groups and acting upon it. Also, we thought it would be a good idea to put those input only parameters into the interface of the function instead of the class constructor.
Some of the variables to handle are real objects, receiving messages from the new class. We decided to take them as members of the new class to enhance the object-oriented feeling of objects talking to each of their members.
Subjects of Change
There was at least one variable who changed it’s internal state which would be an input parameter to our new class. (We cannot be 100% sure, because we are coding in ruby, where we don’t have the possibility to const our variables and ask our compile, who might try to change it). As this would increase also the state, being held by the newly created class, we decided to put it as input parameter to the new method.