I could create private properties and setters methods for the
optionals params and remove them from the method signature.
It would be a very bad idea to do this if the reason is that you want them to get out of the way.
What is a parameter and what is a property are decisions making up the design of the class, so swapping one for the other should be made only after looking at the big picture (as any other design decision). Don't make this kind of change because you don't like how one specific call site for one specific method reads.
We can't tell if it makes sense for the parameter to be a property instead, so for the remainder I 'm going to assume that it does not. What are the options in this case?
Option #1: Refactor
- Does it make sense to have two optional parameters on this method?
- Do you usually leave out one (or both) of them when calling it?
If the answer to these questions is "yes", that could be an indication that the method operates in different modes depending on the arguments. In this case it can make sense to break out the modal behavior into separate methods that have simplified signatures.
Option #2: Bundle of properties
- Does this method have a lot of parameters with sensible defaults?
- Do you usually provide only a few (or none) of these on a typical call?
If the answer to these questions is "yes", then you can make the method accept an array as its last argument and use that as a container of "misc options".
This approach has the (big!) drawback that these options are not being advertised through the method signature anymore, but it can make sense if there are sensible defaults that you won't be touching 90% of the time.
Option #3: Fluent interface
If there are a lot of options that could be specified then creating a fluent interface can make sense, but this is a big change and one that should not be made unless there are additional arguments going for it (e.g. if composability is desired). You could view a fluent interface as the better-engineered version of turning arguments into properties.
Writing a fluent interface involves a new class that encapsulates all the arguments that could possibly go into a function call; the class has one method for each argument and one or more methods that use these arguments to do work. A fluent interface call site would look like
$foo->bar()->color('red')->type('widget')->execute();
Here $foo->bar()
returns an instance of the encapsulating class, color
and type
are methods on that class that set properties and execute
reads these properties and performs the actual work.