Have pairs of static and instanced methods that perform the same tasks?

When developing a two-dimensional vector class as part of a mathematical library, I consider the possibility of using static and instance pairs of methods for stylistic and convenient reasons. That is, two equivalent functions, but one of them is static and does not mutate, and the other instantiates and mutates. I know that I am not the first person to consider this problem (see here ), but I did not find any information that is directly addressed to him.

The advantages of having static pairs of instances and instances:

  • Some people prefer to use one or the other, and in some cases the choice makes the code more readable.
  • It is understood that static methods do not mutate when both static and instanced methods are provided. This can make the calling code more understandable, for example:

    someVector = Vector2d.add(vec1, vec2); someVector = (new Vector2d(vec1)).add(vec2); // does the same thing although more convoluted. // similarly adding directly to a vector is simpler with a mutator method. someVector.add(vec2); someVector = Vector2d.add(someVector, vec2); 

    This is especially important when using long chains of function calls that are common to vectors.

  • On-site operations can be faster than computing than creating a new instance for each operation. The user decides when performance is important. For users of the Vector class, performance can be important because vectors are often used in an expensive calculator.

The benefits of using only static methods or instances, but not both:

  • Lack of significant code redundancy. Easier to maintain.

  • Less bloating. Javadocs will be almost half as much.

  • There is no need to inform users that static methods never mutate, and non-getter methods always mutate.

How did static / instance pairs frown on him? Is it used in any major libraries?

Is the pattern “static methods not mutate, instance methods” widely known?

+6
source share
2 answers

I think your concept of providing both static / immutable and instance / mutable methods is good. I believe this difference is easy to explain, and API users will be easy to understand and remember.

I think your API implementation code will not have redundant business logic. You will find that you are repeating the pattern in which the static implementation creates a new instance and calls the instance method for this new instance.

Given that I am lazy, I would look at creating an infrastructure that automatically creates static methods, their javadoc, and their unit tests at compile time. This would be redundant if you have 10 methods, but it becomes a big win if you have 1000 methods.

+3
source

In the first part, “static methods do not mutate,” which are widely used in OOP. I have not heard this expressed explicitly. But common sense: "If you are changing an object, why a static method, if it can be an instance method?" Therefore, I completely agree that "static methods do not mutate."

The second part is "instance methods [mutate]", which are actually not as widely used. It rather depends on whether you decide that your project applies immutability or variability. Examples from the Java API: java.lang.String immutable, java.util.Date is mutable (most likely by accident / poor design), java.lang.StringBuilder intentionally changes (which is its purpose). Mutability can lead to defensive cloning to protect code from mutational errors. Whether this is really a problem depends on several things:

  • Will another API be used? You never know how they will use your code ... IMO, it is more important to protect the API code from mutational errors than regular code.
  • How well is unit test covered? Can your units check for all mutation errors that can penetrate? If you are following TDD correctly (Uncle Bob 3 TDD Laws) and this is a non-API code, mutation errors are unlikely to penetrate without immediate detection.
  • If you have code that needs to protect itself against mutation errors using protective cloning, how often is this code called? If defensive clones are created frequently, it may be better to use immutable objects than mutable objects. This is basically a call to the number of calls to read-only methods (which will ultimately be protected) to map classes compared to the number of calls to mutator methods in the class itself.

Personally, I prefer immutable objects, I'm a fan of final (if I could change Java, I would make final default value for all fields and variables and enter the var keyword to make them non-final), and I try to do functional programming in Java, although it is not a functional programming language, as far as possible. In my experience, I know that I spend significantly less time debugging my code than others (in fact, I run the Java debugger, maybe twice a year). I don’t have enough empirical data and the right analysis to create any “causal relationships” between experience, immutability, functional programming and correctness, so I’ll just say that I believe that immutability and functional programming help in the correctness, and you have to come up with own judgment about it.

Finishing the second part, “instance methods make [mutate]” - a widely used assumption in case the object is changed anyway, otherwise the instance methods will be cloned.

+1
source

Source: https://habr.com/ru/post/978573/


All Articles