Passing whole object vs passing object's property

JavaPerformanceOop

Java Problem Overview


I'm thinking about the solution for my application. Here's the situation: I have a class with a method that takes ObjectA as an input parameter and calls several small methods. Each one of these methods needs some parts of the ObjectA (they don't overlap, i.e. method1() needs ObjectA.field1 and ObjectA.field2, method2() needs ObjectA.field3 and so on...)

Given the general good code practices and performance, is it better to pass ObjectA to each one of these methods so they can extract the value they need on their own or is it better just pass them values? I mean:

method1(ObjectA);
method2(ObjectA);

or

method1(Object1.getField1(), ObjectA.getField2());
method2(ObjectA.getField3());

Java Solutions


Solution 1 - Java

Keep in mind, with your code, you're not actually passing ObjectA. Namely, you're passing the reference type to ObjectA, so on a performance note the difference between passing a String object reference and a ObjectA object reference would be negligible.

The way I would write it

I would pass the whole object, if the method is pertinent to the class. My reasoning for this is to split up class knowledge as much as possible. What I mean by this is the following.

public void doSomethingRelatedToTheClass(String param)
{
    // Do something with param.
}

My first criticism here is that this method assumes that the input is the correct field. My second, is that now, the class calling this code needs to know a little bit more about this method, because it has to call it like this:

doSomethingRelatedToTheClass(myObject.getValue());

And what this means is, if you find that another member of ObjectA works better inside this method, or you want to access other members of ObjectA, and you change doSomething() to reflect this change, you also need to change the method call, to:

doSomethingRelatedToTheClass(myObject.getOtherValue(), myObject.getValue());

So by passing in the whole object, you abstract that detail away, and the method can handle it; namely:

doSomethingRelatedToTheClass(myObject); // Doesn't need to know what you do with it.

public void doSomethingRelatedToTheClass(ObjectA object)
{
    String val = object.getValue();

    String otherVal = object.getOtherValue();
}

When a change to one class, results in a change in other classes, this is an Anti-pattern called Shotgun Surgery.

Edit

I've had chance to review my answer here and I've amended my original answer slightly because I believe it isn't the best solution for all situations. As above, if a method is related to a class specifically, then the instantiation of that class (or more preferably, its superclass or implemented interface[s]) should be the parameter.

The time this is not the case is when the functionality can be generic. An example of a generic function might be:

public String[] findNouns(String sentence);

In this case, finding the nouns in a sentence might be appropriate for lots of use cases, and not just the use cases that you have defined. As such, passing in the value is the only sensible approach because otherwise, you couple two pieces of logic together that have no direct relationship. The finding of nouns and the arbitrary object you have defined.

In Summary

  • If the method is logic that is related to the object, pass in the object

  • If the method has nothing to do with the object, and the object is just using it as a utility function, then pass in the value and name the function generically.

Solution 2 - Java

Let's examine a scenario. Now this may or may not be your scenario but it illustrates a point.

Lets say field1 and field2 in your case are two integers and method1 sums them and returns the result.

If you pass in the objects then that method can only ever sum those two fields. The method is also now strongly coupled with those objects.

On the other hand, if you pass in only the fields, the two integers in this case your method becomes more generic. You can now sum any 2 arbitrary integers regardless of which objects they are on.

In general though, always expose as little of your objects to other methods and classes. This promotes loose coupling.

Exceptions

AS maaartinus points out if for example field1 and field2 were Points and method1 calculated the distance between those two points, then I would have to agree that passing two Points would be better than passing 2 xy integer pairs (4 parameters)

Hope this helps

Solution 3 - Java

I'd say, it depends. A method may be clearer and more general if it operates on the arguments rather than requiring a whole object. Sometimes you have the arguments ready (e.g., x and y) and would have to aggregate them first into e.g. a Point in order to be able to call the method. Sometimes you have a different unrelated object (e.g., some ImmutablePoint, obviously not extending java.awt.Point) and would have to extract the coordinates and create an object to pass.

Usually, if the passed object is the proper abstraction, then passing it as a whole is the way to go. It's not a performance question, it's about readability and maintainability. See also the Law of Demeter which may lead to looser dependency on the passed object.

Solution 4 - Java

As others have said, it depends but in my experience passing entire objects makes code harder to read and maintain.

Lets consider this method getUserDetails(User user) which relies on few methods like getUserAddress(User user) getUserFamilyInfo(User user) etc which may further connect to different data sources to fetch the information.

There is no easy way to know that getUserFamilyInfo needs only userId or it needs userId and lastName or something else from user when entire object is passed. It makes it hard to understand dependencies among different services and do any refactoring.

I prefer to pass individual arguments if count is less than 3 or create a dto if handful of properties are required from a vary large object.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLucasView Question on Stackoverflow
Solution 1 - JavachristopherView Answer on Stackoverflow
Solution 2 - Javan4rzulView Answer on Stackoverflow
Solution 3 - JavamaaartinusView Answer on Stackoverflow
Solution 4 - JavaNitin PandeyView Answer on Stackoverflow