Class with Single Method -- Best Approach

Class with single method -- best approach?

I used to love utility classes filled up with static methods. They made a great consolidation of helper methods that would otherwise lie around causing redundancy and maintenance hell. They're very easy to use, no instantiation, no disposal, just fire'n'forget. I guess this was my first unwitting attempt at creating a service oriented architecture - lots of stateless services that just did their job and nothing else. As a system grows however, dragons be coming.

Polymorphism

Say we have the method UtilityClass.SomeMethod that happily buzzes along. Suddenly we need to change the functionality slightly. Most of the functionality is the same, but we have to change a couple of parts nonetheless. Had it not been a static method, we could make a derivate class and change the method contents as needed. As it's a static method, we can't. Sure, if we just need to add functionality either before or after the old method, we can create a new class and call the old one inside of it - but that's just gross.

Interface woes

Static methods cannot be defined through interfaces for logic reasons. And since we can't override static methods, static classes are useless when we need to pass them around by their interface. This renders us unable to use static classes as part of a strategy pattern. We might patch some issues up by passing delegates instead of interfaces.

Testing

This basically goes hand in hand with the interface woes mentioned above. As our ability of interchanging implementations is very limited, we'll also have trouble replacing production code with test code. Again, we can wrap them up but it'll require us to change large parts of our code just to be able to accept wrappers instead of the actual objects.

Fosters blobs

As static methods are usually used as utility methods and utility methods usually will have different purposes, we'll quickly end up with a large class filled up with non-coherent functionality - ideally, each class should have a single purpose within the system. I'd much rather have a five times the classes as long as their purposes are well defined.

Parameter creep

To begin with, that little cute and innocent static method might take a single parameter. As functionality grows, a couple of new parameters are added. Soon further parameters are added that are optional, so we create overloads of the method (or just add default values, in languages that support them). Before long, we have a method that takes 10 parameters. Only the first three are really required, parameters 4-7 are optional. But if parameter 6 is specified, 7-9 are required to be filled in as well... Had we created a class with the single purpose of doing what this static method did, we could solve this by taking in the required parameters in the constructor, and allowing the user to set optional values through properties, or methods to set multiple interdependent values at the same time. Also, if a method has grown to this amount of complexity, it most likely needs to be in its own class anyways.

Demanding consumers to create an instance of classes for no reason

One of the most common arguments is, why demand that consumers of our class create an instance for invoking this single method, while having no use for the instance afterwards? Creating an instance of a class is a very very cheap operation in most languages, so speed is not an issue. Adding an extra line of code to the consumer is a low cost for laying the foundation of a much more maintainable solution in the future. And finally, if you want to avoid creating instances, simply create a singleton wrapper of your class that allows for easy reuse - although this does make the requirement that your class is stateless. If it's not stateless, you can still create static wrapper methods that handle everything, while still giving you all the benefits in the long run. Finally, you could also make a class that hides the instantiation as if it was a singleton: MyWrapper.Instance is a property that just returns new MyClass();

Only a Sith deals in absolutes

Of course, there are exceptions to my dislike of static methods. True utility classes that do not pose any risk to bloat are excellent cases for static methods - System.Convert as an example. If your project is a one-off with no requirements for future maintenance, the overall architecture really isn't very important - static or non static, doesn't really matter - development speed does, however.

Standards, standards, standards!

Using instance methods does not inhibit you from also using static methods, and vice versa. As long as there's reasoning behind the differentiation and it's standardised. There's nothing worse than looking over a business layer sprawling with different implementation methods.

Design question: Java Class with single method ok?

In this case, since you have no true member data, making the single method a static method inside the class would be the appropriate design choice:

public class ListUtils
{
public static List Merge(List l1, Listl2)
{
List l3 = new List();
// merge l1 and l3 into l3
return l3;
}
}

You can then use the code without having to create an instance of your class (especially when it serves no purpose):

List l1 = new List();
List l2 = new List();
// Fill the lists

List merged = ListUtils.Merge(l1, l2);

Java best practice: Class with only static methods

I would say you're doing it right. Apart of that, some advices for your utility class:

  • Make sure it doesn't have any state. This is, there's no field in the class unless it's declared static final. Also, make sure this field is immutable as well e.g. Strings.
  • Make sure it cannot be a super class of other classes. Make the class final so other programmers cannot extend it.
  • This one is debatable, but you may declare a no-arg constructor private, so no other class could create an instance of your utility class (using reflection or something similar will do, but there's no need to go that protective with the class). Why you may not do this? Well, this is the strange case where you want/need to inject an instance of the utility class e.g. through an interface rather than directly using it along your class. Here's an example of this. This design is really odd but may happen (as shown in the link above), but if you will not run in such case, the best advice is to keep the constructor private.

There are lot of libraries that provide utility classes in order to help us programmers with our work. One of the most known is Apache Common set of libraries. It's open source and you can check the code to see how they design these utility classes in order to create yours. (DISCLAIMER: I do not work or support these libraries, I'm a happy user of them)

Important Note: Avoid using a singleton for your utility class.

Is there an elegant way to make every method in a class start with a certain block of code?

I don't know about elegant, but here is a working implementation using Java's built-in java.lang.reflect.Proxy that enforces that all method invocations on Foo begin by checking the enabled state.

main method:

public static void main(String[] args) {
Foo foo = Foo.newFoo();
foo.setEnabled(false);
foo.bar(); // won't print anything.
foo.setEnabled(true);
foo.bar(); // prints "Executing method bar"
}

Foo interface:

public interface Foo {
boolean getEnabled();
void setEnabled(boolean enable);

void bar();
void baz();
void bat();

// Needs Java 8 to have this convenience method here.
static Foo newFoo() {
FooFactory fooFactory = new FooFactory();
return fooFactory.makeFoo();
}
}

FooFactory class:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class FooFactory {

public Foo makeFoo() {
return (Foo) Proxy.newProxyInstance(
this.getClass().getClassLoader(),
new Class[]{Foo.class},
new FooInvocationHandler(new FooImpl()));
}

private static class FooImpl implements Foo {
private boolean enabled = false;

@Override
public boolean getEnabled() {
return this.enabled;
}

@Override
public void setEnabled(boolean enable) {
this.enabled = enable;
}

@Override
public void bar() {
System.out.println("Executing method bar");
}

@Override
public void baz() {
System.out.println("Executing method baz");
}

@Override
public void bat() {
System.out.println("Executing method bat");
}

}

private static class FooInvocationHandler implements InvocationHandler {

private FooImpl fooImpl;

public FooInvocationHandler(FooImpl fooImpl) {
this.fooImpl = fooImpl;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass() == Foo.class &&
!method.getName().equals("getEnabled") &&
!method.getName().equals("setEnabled")) {

if (!this.fooImpl.getEnabled()) {
return null;
}
}

return method.invoke(this.fooImpl, args);
}
}
}

As others have pointed out, it does seem like overkill for what you need if you only have a handful of methods to worry about.

That said, there certainly are benefits:

  • A certain separation of concerns is achieved, because Foo's method implementations don't have to worry about the enabled check cross-cutting concern. Instead, the method's code only needs to worry about what the method's primary purpose is, nothing more.
  • There is no way for an innocent developer to add a new method to the Foo class and mistakenly "forget" to add the enabled check. The enabled check behavior is automatically inherited by any newly added method.
  • If you need to add another cross-cutting concern, or if you need to enhance the enabled check, it's very easy to do so safely and in one place.
  • It is kind of nice that you can get this AOP-like behavior with built-in Java functionality. You are not forced into having to integrate some other framework like Spring, though they can definitely be good options too.

To be fair, some of the downsides are:

  • Some of the implementation code that handles the proxy invocations is ugly. Some would also say that having inner classes to prevent instantiation of the FooImpl class is ugly.
  • If you want to add a new method to Foo, you have to make a change in 2 spots: the implementation class and the interface. Not a big deal, but it's still a bit more work.
  • Proxy invocations are not free. There is a certain performance overhead. For general use though, it won't be noticeable. See here for more information.

EDIT:

Fabian Streitel's comment got me thinking about 2 annoyances with my above solution that, I'll admit, I'm not happy about myself:

  1. The invocation handler uses magic strings to skip the "enabled-check" on the "getEnabled" and "setEnabled" methods. This can easily break if the method names are refactored.
  2. If there was a case where new methods need to be added that should not inherit the "enabled-check" behavior, then it can be pretty easy for the developer to get this wrong, and at the very least, it would mean adding more magic strings.

To resolve point #1, and to at least ease the problem with point #2, I would create an annotation BypassCheck (or something similar) that I could use to mark the methods in the Foo interface for which I don't want to perform the "enabled check". This way, I don't need magic strings at all, and it becomes a lot easier for a developer to correctly add a new method in this special case.

Using the annotation solution, the code would look like this:

main method:

public static void main(String[] args) {
Foo foo = Foo.newFoo();
foo.setEnabled(false);
foo.bar(); // won't print anything.
foo.setEnabled(true);
foo.bar(); // prints "Executing method bar"
}

BypassCheck annotation:

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BypassCheck {
}

Foo interface:

public interface Foo {
@BypassCheck boolean getEnabled();
@BypassCheck void setEnabled(boolean enable);

void bar();
void baz();
void bat();

// Needs Java 8 to have this convenience method here.
static Foo newFoo() {
FooFactory fooFactory = new FooFactory();
return fooFactory.makeFoo();
}
}

FooFactory class:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class FooFactory {

public Foo makeFoo() {
return (Foo) Proxy.newProxyInstance(
this.getClass().getClassLoader(),
new Class[]{Foo.class},
new FooInvocationHandler(new FooImpl()));
}

private static class FooImpl implements Foo {

private boolean enabled = false;

@Override
public boolean getEnabled() {
return this.enabled;
}

@Override
public void setEnabled(boolean enable) {
this.enabled = enable;
}

@Override
public void bar() {
System.out.println("Executing method bar");
}

@Override
public void baz() {
System.out.println("Executing method baz");
}

@Override
public void bat() {
System.out.println("Executing method bat");
}

}

private static class FooInvocationHandler implements InvocationHandler {

private FooImpl fooImpl;

public FooInvocationHandler(FooImpl fooImpl) {
this.fooImpl = fooImpl;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass() == Foo.class
&& !method.isAnnotationPresent(BypassCheck.class) // no magic strings
&& !this.fooImpl.getEnabled()) {

return null;
}

return method.invoke(this.fooImpl, args);
}
}
}

How to define a method in abstract class with different classes as input parameter?

If you want to use just one class instead of three classes, you can create a base class or interface and put the same behaviour into this newly created abstract class. And then just call it in your Func method.

For example, we can create an abstract class Display:

public abstract class Display 
{
public abstract string Show();
}

And then it is necessary to create concrete implementations of this base class Display:

public class SamsungDisplay : Display
{
public override string Show()
{
return "I am Samsung";
}
}

public abstract class SonyDisplay : Display
{
public override string Show()
{
return "I am Sony";
}
}

public abstract class DellDisplay : Display
{
public override string Show()
{
return "I am Dell";
}
}

and then we can use any derived class instead of base class:

// Here you can pass SamsungDisplay, SonyDisplay or DellDisplay 
public void UseDisplay(Display display)
{
display.Show();
}

Class-specific method visibility

There is something like you are asking for in C++, it is called friend classes. Nevertheless, that concept is not supported by Java:

'Friends' equivalent for Java?

A second option is to use code reflection to access a class private members but it isn't such a clean solution and only works for protected elements:

public class C1 {

public C1()
{
x = "Hello Word!";
}

protected String x;
}

At a different class's method:

String val = (String)obj.getClass().getDeclaredField("x").get(obj);
System.out.println("val: " + val);

EDIT: After making a little bit of research I found it is possible even to access private members:

Field field = obj.getClass().getDeclaredField("x");
field.setAccessible(true);
String val = (String)field.get(obj);
field.setAccessible(false);

Static methods in Python?

Yep, using the staticmethod decorator:

class MyClass(object):
@staticmethod
def the_static_method(x):
print(x)

MyClass.the_static_method(2) # outputs 2

Note that some code might use the old method of defining a static method, using staticmethod as a function rather than a decorator. This should only be used if you have to support ancient versions of Python (2.2 and 2.3):

class MyClass(object):
def the_static_method(x):
print(x)
the_static_method = staticmethod(the_static_method)

MyClass.the_static_method(2) # outputs 2

This is entirely identical to the first example (using @staticmethod), just not using the nice decorator syntax.

Finally, use staticmethod sparingly! There are very few situations where static-methods are necessary in Python, and I've seen them used many times where a separate "top-level" function would have been clearer.


The following is verbatim from the documentation::

A static method does not receive an implicit first argument. To declare a static method, use this idiom:

class C:
@staticmethod
def f(arg1, arg2, ...): ...

The @staticmethod form is a function decorator – see the description of function definitions in Function definitions for details.

It can be called either on the class (such as C.f()) or on an instance (such as C().f()). The instance is ignored except for its class.

Static methods in Python are similar to those found in Java or C++. For a more advanced concept, see classmethod().

For more information on static methods, consult the documentation on the standard type hierarchy in The standard type hierarchy.

New in version 2.2.

Changed in version 2.4: Function decorator syntax added.

Modifying an Existing Method to handle another type of class - Best Practice Recommendations

This is what I had in mind. Firstly we create an interface:

public interface IMyInterface
{
string Name { get; set; }
DateTime CreatedOn { get; set; }
bool Valid { get; set; }
string getName();
}

Next we create two classes that implement this interface:

public class Class1 : IMyInterface
{
public string Name { get; set; }
public DateTime CreatedOn { get; set; }
public bool Valid { get; set; }
public string getName()
{
return "Class1Name is " + Name;
}
public decimal SpecialValue { get; set; }
}

and:

public class Class2 : IMyInterface
{
public string Name { get; set; }
public DateTime CreatedOn { get; set; }
public bool Valid { get; set; }
public string getName()
{
return "Class2Name is " + Name;
}
public decimal SpecialValue { get; set; }
}

Now we can create two Lists, one of each class:

var class1s = new List<Class1>
{
new Class1{ Name = "Article1",
CreatedOn = new DateTime (2022,5,8),
SpecialValue = 62.5M,
Valid = false},
new Class1{ Name = "Article2",
CreatedOn = new DateTime (2022,7,19),
SpecialValue = 46.1M,
Valid = true}
};
var class2s = new List<Class2>
{
new Class2{ Name = "Article3",
CreatedOn = new DateTime (2022,2,2),
SpecialValue = 18.5M,
Valid = true},
new Class2{ Name = "Article4",
CreatedOn = new DateTime (2022,11,27),
SpecialValue = 19.9M,
Valid = false}
};

Next comes the clever bit. We combine the two lists into a new List of type IMyInterface (just one line of code):

var merged = class1s.Concat<IMyInterface>(class2s).ToList();

Note the Concat<IMyInterface>. That effectively tells the compiler to join the two lists, but only insofar as their respective implementations of IMyInterface.

Finally we can loop through this list:

foreach (var m in merged)
{
string name = m.getName();
bool valid = m.Valid;
decimal val = m.SpecialValue; //compiler error here
}

I have deliberately left a compiler error here: SpecialValue is not accessible. Why? Both classes have a SpecialValue of the same type. However this property is not in the interface. Within our foreach loop on the merged list, we only have access to those properties and methods that are defined in the interface.



Related Topics



Leave a reply



Submit