I have a Gene
class that keeps track of genes. Gene
has a method for calculating the distance between two genes. Are there any reasons to make it static?
Which is better?
public static int geneDistance(Gene g0, Gene g1)
or
public int geneDistance(Gene other)
Arguments for/against making it static? I understand what it means for a member to be static, I'm just interested in its implications for maximum cleanliness/efficiency/etc.
I repeat the same pattern for returning trimmed versions of two genes, finding matches between genes, finding matches between animals (which contain collections of genes), etc.
public static int geneDistance(Gene g0, Gene g1)
would be part of a separate utility class likeCollections
andArrays
in Java whereaspublic int geneDistance(Gene other)
will be part of theGene
class. Considering you have other operations like "trimmed versions of two genes, finding matches between genes, finding matches between animals (which contain collections of genes), etc" I would create a separate static utility class for them as these operations aren't semantically meaningful to what aGene
is.If the the semantics of "gene distance" can be wrapped up into your
equals(Object o)
method then you could consume it there or else include it in your static utility.Here's a meta-answer, and a fun exercise: survey a bunch of the Java SDK's library classes and see if you can categorize the commonalities between static methods in different classes.
I'd select the second approach. I see no advantage in making the method static. Since the method is in the Gene class, making it static only adds one extra parameter with no extra gain. If you need a util class, that's a whole different deal. But in my opinion there's usually no need for a util class if you can add the method to the class in question.
Two important considerations which have not been mentioned are whether gene1.geneDistance(gene2) is always expected to match gene2.geneDistance(gene1), and whether Gene is and always will be a sealed class. Instance methods are polymorphic with respect to the types of the things upon which they are invoked, but not the types of their arguments. This can cause some confusion if the distance function is supposed to be transitive, but things of different types might compute distance differently. If the distance function is supposed to be transitive, and is defined as being the shortest transformation that either class knows about, a good pattern may be to have a protected instance method
int getOneWayDistance(Gene other)
and then have something like:Such a design will ensure that distance relation behaves transitively, while allowing individual types to report shortcuts to instances of other types that those other types may not know about.
I would like to start answering on your question with the new one: What your class Gene is responsible for? May be you have heard about the 'Single-Responsibility Principle': A class should have only one reason to change. So, I believe if you answer this question you will be able to decide how your application should be designed. In this particular case, I would not use neither the first approach nor the second one. In my opinion it is much better to define new responsibility and encapsulate it in a separate class or may be a function.
IMO there is no absolute "better", but
public int geneDistance(Gene other)
is stylistically more similar to other methods in Java (e.g. Object.equals, Comparable.compareTo), so I'd go that way.