Best practice for passing many arguments to method?
In Effective Java, Chapter 7 (Methods), Item 40 (Design method signatures carefully), Bloch writes:
There are three techniques for shortening overly long parameter lists:
- break the method into multiple methods, each which require only a subset of the parameters
- create helper classes to hold group of parameters (typically static member classes)
- adapt the Builder pattern from object construction to method invocation.
For more details, I encourage you to buy the book, it's really worth it.
Best practice: how to pass many arguments to a function?
I don't think this is really a StackOverflow question, more of a Software Engineering question. For example check out this question.
As far as whether or not this is a good design pattern, this is an excellent way to handle a large number of arguments. You mentioned that this isn't very efficient in terms of memory or speed, but I think you're making an improper micro-optimization.
As far as memory is concerned, the overhead of running the Python interpreter is going to dwarf the couple of extra bytes used by instantiating your class.
Unless you have run a profiler and determined that accessing members of that options class is slowing you down, I wouldn't worry about it. This is especially the case because you're using Python. If speed is a real concern, you should be using something else.
You may not be aware of this, but most of the large scale number crunching libraries for Python aren't actually written in Python, they're just wrappers around C/C++ libraries that are much faster.
I recommend reading this article, it is well established that "Premature optimization is the root of all evil".
Best practice to pass arguments
About the performance, two of them are the same. If you implement your function as
public printUsernameAndGroup(String username, String group){
sout(username);
sout(group);
}
You will access username and group attributes of your object before calling the function. Also when you implement it as
public printUsernameAndGroup(Application application){
sout(application.username);
sout(application.group);
}
You are just passing a copy of the reference of that object, not copying all the 10 fields, and again accessing two attributes of it.
But if you think about the ease of use, the second one will be more user friendly.
When a method has too many parameters?
There is no clear limit, but I am uncomfortable with more than 3-4 parameters. AFAIR Uncle Bob Martin in Clean Code recommends max 3.
There are several refactorings to reduce the number of method parameters (see Working Effectively with Legacy Code, by Michael Feathers for details). These come to my mind:
- encapsulate many related parameters into a single object (e.g. instead of
String surName, String firstName, String streetAddress, String phoneNumber
pass aPerson
object containing these as fields) - pass parameters in the constructor or other method calls prior to the invocation of this method
How many parameters are too many?
When is something considered so obscene as to be something that can be regulated despite the 1st Amendment guarantee to free speech? According to Justice Potter Stewart, "I know it when I see it." The same holds here.
I hate making hard and fast rules like this because the answer changes not only depending on the size and scope of your project, but I think it changes even down to the module level. Depending on what your method is doing, or what the class is supposed to represent, it's quite possible that 2 arguments is too many and is a symptom of too much coupling.
I would suggest that by asking the question in the first place, and qualifying your question as much as you did, that you really know all of this. The best solution here is not to rely on a hard and fast number, but instead look towards design reviews and code reviews among your peers to identify areas where you have low cohesion and tight coupling.
Never be afraid to show your colleagues your work. If you are afraid to, that's probably the bigger sign that something is wrong with your code, and that you already know it.
What are the best practices for passing multiple variables to a function using PHP
Highly depends on the use case.
But here are some solutions to this problem.
Fixed Order
If the order is somewhat fixed and you never have a need to change it, then:
<?php
function fn($a1, $a2, $a3, $a4, $a5, $a6 = null, $a7 = "foo", $a8 = "bar", array $a9 = array()) {}
Pros
- Self documenting
- Type hinting
- Default values
Cons
- Fixed order
Array
If on the other hand the order is somewhat different all the time, use the array thingy.
<?php
function fn($a1, $a2, $a3, $a4, $a5, array $optional = array()) {}
fn("", "", "", "", "", array("arg9" => false));
Pros
- Easy to use
- No fixed order
Cons
- Not self documenting
- Costly to validate
Parameter Object
A parameter object is of course a valid solution as well, but impractical to handle:
<?php
class Args {
public $arg5 = "foo";
public $arg6 = "bar";
public $arg7 = null;
public $arg8 = array();
public $arg9 = true;
}
function fn($arg1, $arg2, $arg3, $arg4, $arg5, \Args $optional = null) {}
// Now comes the impractical part.
$optional = new Args();
$optional->arg9 = false;
fn("", "", "", "", "", $optional);
Pros
- Self documenting
- No fixed order
Cons
- Highly impractical
- Costly to validate
Array to Parameter Object
You could mix the two approaches:
<?php
class Args {
public $arg5 = "foo";
public $arg6 = "bar";
public $arg7 = null;
public $arg8 = array();
public $arg9 = true;
public __construct($args) {
foreach ($args as $property => $value) {
$this->"set{$property}"($value);
}
}
public function setArg5($value) {
if (is_string($value) === false) {
throw new \InvalidArgumentException;
}
$this->arg5 = $value;
}
// and so on ...
}
function fn($arg1, $arg2, $arg3, $arg4, $arg5, array $optional = null) {
if (isset($optional)) {
$optional = new Args($optional);
}
// ...
}
fn("", "", "", "", "", array("arg9" => false));
Pros
- Easy validation
- Separation of concern
- Easy to pass along
- Easy to handle
- Possible to document the API
Cons
- Still not possible to document it as good as the fixed args approach
- Costly to validate
Variadics
There's a new feature in PHP 5.6 that you might find useful, variadics:
<?php
function fn($a1, $a2, $a3, $a4, $a5, ...$optional) {}
Pros
- Very fast
- Allows to build special APIs (e.g. database prepared statement binding)
Cons
- Not easily documented
- Costly to validate
Named Parameters
And we might see named parameters in the future.
Java: Sending Multiple Parameters to Method
The solution depends on the answer to the question - are all the parameters going to be the same type and if so will each be treated the same?
If the parameters are not the same type or more importantly are not going to be treated the same then you should use method overloading:
public class MyClass
{
public void doSomething(int i)
{
...
}
public void doSomething(int i, String s)
{
...
}
public void doSomething(int i, String s, boolean b)
{
...
}
}
If however each parameter is the same type and will be treated in the same way then you can use the variable args feature in Java:
public MyClass
{
public void doSomething(int... integers)
{
for (int i : integers)
{
...
}
}
}
Obviously when using variable args you can access each arg by its index but I would advise against this as in most cases it hints at a problem in your design. Likewise, if you find yourself doing type checks as you iterate over the arguments then your design needs a review.
Best practice for passing multiple function arguments in C++
there are 5 client functions.
You might pass structure instead
template <typename Element>
struct Customization {
std::function<void(Element)> client_code1;
std::function<void(Element)> client_code2;
std::function<void(Element)> client_code3;
std::function<void(Foo)> client_code4;
std::function<void(Bar)> client_code5;
};
or even possibly an interface:
template <typename Element>
struct Customization {
virtual ~Customization() = default;
virtual void client_code1(Element) = 0;
virtual void client_code2(Element) = 0;
virtual void client_code3(Element) = 0;
virtual void client_code4(Foo) = 0;
virtual void client_code5(Bar) = 0;
};
and then
template<class Range, class Element>
void run_generic_algorithm(Range& r, const Customization <Element>& customization);
Most of the time I am not even specifying all the client functions, so I have to put in a lambda function that does nothing.
With previous comment, you might give default values to the member of previous structure.
Else you can add default value to argument or create overloads.
What's the best way to refactor a method that has too many (6+) parameters?
The best way would be to find ways to group the arguments together. This assumes, and really only works if, you would end up with multiple "groupings" of arguments.
For instance, if you are passing the specification for a rectangle, you can pass x, y, width, and height or you could just pass a rectangle object that contains x, y, width, and height.
Look for things like this when refactoring to clean it up somewhat. If the arguments really can't be combined, start looking at whether you have a violation of the Single Responsibility Principle.
best way to pass many arguments to a method in Java
You could make a builder for Obj
, which will give you a more fluent way of constructing the Obj
than using the static method in your question.
public class ObjBuilder {
private String a;
private String b;
private List<KeyValue> keyValues = new ArrayList<>();
private ObjBuilder() {}
public static ObjBuilder obj() {
return new ObjBuilder();
}
public ObjBuilder withA(String a) {
this.a = a;
return this;
}
public ObjBuilder withB(String b) {
this.b = b;
return this;
}
public ObjBuilder withKeyValue(KeyValue keyValue) {
this.keyValues.add(keyValue);
return this;
}
public Obj build() {
// whatever Obj.makeSomeObject does to create the Obj instance
}
}
Then when you need to create an Obj
Obj obj = ObjBuilder.obj()
.withA("some String")
.withB("some String")
.withKeyValue(new KeyValue("A", "B"))
.withKeyValue(new KeyValue("C", "D"))
.build();
Obviously using this over the static varargs method in your question is largely a stylistic choice
Related Topics
How to Rotate Jpeg Images Based on the Orientation Metadata
Spring Cron Expression for Every Day 1:01:Am
Gson and Deserializing an Array of Objects with Arrays in It
Is the in Relation in Cassandra Bad for Queries
How to Emit and Handle Custom Events
How to Intercept a Method Invocation with Standard Java Features (No Aspectj etc)
Correct Idiom for Managing Multiple Chained Resources in Try-With-Resources Block
Auto-Wiring a List Using Util Schema Gives Nosuchbeandefinitionexception
How to Change the Color of Titlebar in Jframe
Advantage of Set and Get Methods VS Public Variable
Efficient Intersection of Two List<String> in Java
Execute Jsp Directly from Java
Javax.Mail.Authenticationfailedexception Is Thrown While Sending Email in Java