Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: When to use attributes, when to use method parameters?

I tried googling and searching for this question but somehow couldn't find anything relevant about it. I'm wondering if there is a bbest-practise guide on when to use attributes in a class and when not, but rather use parameters to the single methods.

Many cases are clear to me, e.g.

public class Dog
{
 private name;
 public setName(...) {....}
}

But sometimes it's not clear to me what's better to use. E.g. the following, either use:

public class calculation
  XYZ bla;
  public calculation(XYZ something)
  {
    this.bla = something;
  }
  public void calc1()
  {
    // some calculations with this.bla
  }
  public void calc1()
  {
    // some more calculations with this.bla
  }
  public XYZ getBla()
  {
    return this.bla;
  }
}

or maybe do:

public class calculation
  public calculation() {}
  public static XYZ calc1(XYZ bla) // maybe static, if not dependant on other attributes/instance-variables etc
  {
    // some calculations with bla
    return bla;
  }
  public static XYZ calc1() // maybe static, if not dependant on other attributes/instance-variables etc
  {
    // some more calculations with bla
    return bla;
  }
}

I mean you can argue for both cases. I see advantages and maybe disadvantages for both different styles, but somehow I prefer the second one as far as long as there are not too many arguments/parameters needed. Sure, if I need many many more attributes etc., then the first one will be better, simpler etc. because I dont need to pass so many parameters to the method...

Just a question of personal style? Or how to decide for one approach? Thanks


EDIT: A better example: I'm curently doing much image processing and the question would be wether to store the image internally in the state of the object or not. I'm currently NOT doing it because I'm using static methods, and psasing the image itself I to each method:

public class ImageProcessing
{
    /**
     * 
     */
    public static Mat cannyEdges(Mat I, int low, int high)
    {      
        // ...
        return I;
    }
    public static Mat cannyEdges(Mat I)
    {
        return ImageProcessing.cannyEdges(I, ContourDetection.CANNY_LOWTHRES, ContourDetection.CANNY_HIGHTHRES);
    }

    /**
     * 
     */
    public static Mat getHoughLines(Mat Edges, ...some_conf_vars...)
    {
        // ...
        return I;
    }
}

and then I'm calling it from the outside like this e.g.:

// here: read image to I...
Mat edges = ImageProcessing.cannyEdges(I, 20, 100);
Mat lines = ImageProcessing.getHoughLines(I);

// draw lines...

question is: Does I belong to the state of the object? Would it make sense to convert to non-static and then use for example:

// here: read image to I...
ImageProcessing IP = new ImageProcessing(I);
IP.cannyEdges(20, 100); // CHANGE OF cannyEdges: Also save `edges` internally as property!?
IP.calcHoughLines(); // also save the lines internally maybe?
Mat lines = IP.getLines(); 

// draw lines...

is this nicer? The question arising is then again: Should I for example store the result of getHoughLines() (i.e. the lines) internally or should I directly return it to the caller!?

like image 677
tim Avatar asked Mar 27 '14 23:03

tim


Video Answer


2 Answers

I can use some examples:

public class Multiplier {
    private int number;

    public Multiplier(int number) {
        this.number = number;
    }

    public int multiply(int other) {
        return number * other;
    }
} 

This class could be instantiated like:

Multiplier multiplyByTwo = new Multiplier(2);

I could use it to multiply many elements on a list by 2.

But I could need to multiply pairs of numbers. So the following class could be what I neeed:

public class Multiplier {       
    public static int multiply(int number, int other) {
        return number * other;
    }
}

I could make it static since no state is needed.

This example could be used like this on a list:

for (int x:listOfInts) {
    print(Multiplier.multiply(x * 2));
}

But probably in this specific case the 1st example was nicer.

for (int x:listOfInts) {
    print(multiplyByTwo(x));
}

or even nicer used with a Java 8 ''map''

If I need to get the elements of the multiplication and the result at many points in my code i could do.

class Multiplier {
    private int x;
    private int y;

    public int multiply() {
        return x * y;
    }
    // getters and setters for x and y
}

In this last case I may consider not adding setters and pass x, y in the constructor.

Every structure could be used in some specific cases.

like image 80
Raul Guiu Avatar answered Oct 20 '22 23:10

Raul Guiu


It's not entirely a question of personal style. But nevertheless, I assume that this topic might be slightly controversial (opinion-based) and thus not perfectly suited for a Q/A-site.

However, the obvious question is: Does an object of the respective class really carry a state? That is, is there any benefit in having the state represented by an instance? If the sole purpose of the instance is to be an accumulator of variables that are modified with a sequence of set... calls and a final call to an execute() method, then there is usually no real justification for such an instance - except for avoiding to have a static method with "many" parameters.

I think that the advantages of static methods outweigh most of the potential clumsiness of calling a method with "many" parameters. One of the most important ones is probably that the approach with static methods doesn't increase the state space. Every field is another dimension in the state space, and documenting state space properly can be hard. Static methods enforce a more "functional" programming style: They don't have any side-effects, and thus, are thread-safe (which is becoming increasingly important).

(Note: All this refers to static methods that are not related to any static state - that should be avoided anyhow. And of course, this refers to methods that are not involved in or aiming at anything related to polymorphism).

And after all, one can easily call any static method from anywhere - even from within an instance method, and pass in some fields as parameters. The opposite is not so easy: When you want to call a method that depends on many instance fields, it can be a hassle when you first have to create an object and set the fields appropriately (still not knowing whether it is in a valid state to call the method). I also see the default methods of Java 8 as a nice application case where static utility methods come in handy: The default method may easily delegate to the utility method, because no state is involved.

like image 24
Marco13 Avatar answered Oct 20 '22 22:10

Marco13