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!?
Answer
There are a few reasons I’d go with the first option, i.e. an object with state over static functions, particularly for complex calculations but also for simpler ones.
- Objects work better for the command pattern.
- Objects work better for the strategy pattern.
- Static methods can turn unit tests into a nightmare.
- Static is an anti-pattern in OOP because it breaks polymorphism, with the side-effect that related techniques will break with it, e.g. open/closed, mocking, proxies, etc.
That’s my 2c at least.
The weird part of your first example is that those calcX
methods don’t say anything about idempotency, so it’s unclear what this.bla
is when it’s being manipulated. For complex computations with optional settings, an alternative is to construct an immutable object using a builder pattern, and then offer calcX
methods that return the result based on fixed object state and parameters. But the applicability of that really depends on the use case, so YMMV.
Update: With your new code, a more OOP approach would be to decorate Mat
. Favouring delegation over inheritance, you’d get something like
public class MyMat { private Mat i; public MyMat(Mat i) { this.i = i; } public Mat getBackingMat() { return this.i; } public MyMat cannyEdges(int low, int high) { // ... return new MyMat(I); // lets you chain operations } public MyMat cannyEdges() { return new MyMat(ImageProcessing.cannyEdges(I, ContourDetection.CANNY_LOWTHRES, ContourDetection.CANNY_HIGHTHRES)); } public MyMat getHoughLines(...some_conf_vars...) { // ... } } MyMat myMat = new MyMat(I); lines = myMat.cannyEdges(20, 100).calcHoughLines();
This is just a guess, cause I have no idea what those things mean. 🙂