2

I am creating an API of a list of checking functions. There is an object passed in as an argument to be checked.

The object is like below:

public class People{

    private String name;
    private String address;
    private int age;
    private String job;

    public getter() ...
    public setter() ...

}

I create a class including a list of checking function to make sure the provided information is valid or not. For example:

public class checkingFunctions {

public static boolean checkName(People ppl){

     perform the name checking function;

}

public static boolean checkAge(People ppl){

     perform the age checking function;

}

}

I know the above way works as an API so that other people can call checkingFunctions.checkName(ppl). But is this the correct way to build the API that will be exposed to others as jar file ? I was thinking to create an interface of checkingFunctions like below:

   public interface ICheckingFunctions {

        boolean checkName(People);

        boolean checkAge(People);

}

And let the checkingFunctions class to implement it, like

public class checkingFunctions implements ICheckingFunctions {

}

BUt it won't compile because the checkName and checkAge can not be declared as static if it is overriding a superclass method.

Or should I just use the interface and let it implement the interface, but remove the static from all checking method. So, if others want to use my API, they just instantiate the interface, and use instance.checkName() to call method ? is that a good way ?

I am wondering whether there there exists an industry standard or design pattern standard to create such an interface so that others can call it.

Thanks a lot.

Balder
  • 8,623
  • 4
  • 39
  • 61
Terry
  • 855
  • 4
  • 12
  • 16
  • http://stackoverflow.com/questions/3612567/how-to-create-my-own-java-libraryapi – J.K Jan 17 '15 at 02:22
  • 2
    @Devs not really, that question is about how to package code as an API, this question is more about what a good API looks like. – fvu Jan 17 '15 at 02:24
  • the `setName()` method can check the name or you can add the `checkName() `method to the People class. would that help? – flup Jan 17 '15 at 02:26
  • Thanks, or should I just use the interface and let it implement the interface, but remove the static from all checking method. So, if others want to use my API, they just instantiate the interface, and use instance.checkName() to call method ? is that a good way ? – Terry Jan 17 '15 at 02:29
  • @flup I can not add the checkNname in people class. I am not the owner of that class. – Terry Jan 17 '15 at 02:31
  • 1
    Shouldn't the object itself be self validating? That's kind of the point of OO. A procedural language would have functions for validating other "structures", but an OO language should focus on self contained units of work - IMHO. Not to say you wouldn't have business logic that wouldn't do extra checking though – MadProgrammer Jan 17 '15 at 03:01
  • Ask yourself why users of your class would benefit from having an interface rather than your static methods. If you don't find any reason, then keep it simple. But respect the Java naming conventions, and add javadoc to your methods. Nobody will use your API if it looks crappy and if you can't even know what a method is doing. – JB Nizet Jan 17 '15 at 07:01
  • Do take a look at the competition. http://stackoverflow.com/questions/397852/java-validation-frameworks lists a couple validation frameworks for example. And there's a JSR for Bean Validation (JSR-349). – flup Jan 18 '15 at 22:18
  • @MadProgrammer The people needs to pass the pipeline where my checking service is one of the services in the pipeline. Thus, I can not put the checking method into the people object. – Terry Jan 18 '15 at 23:04
  • @JB Nizet Thanks. My caller is a spring web service. will creating bean for that interface be better than directly calling the static method ? Which is better ? – Terry Jan 18 '15 at 23:05

1 Answers1

1

How to design such an API very much depends on how your API is intended to be used.

If it for example turns out, that your People class is best implemented as a final class, and you want to make sure, that it is always checked in the same consistent way, then providing a number of public static check... methods is certainly a reasonable way to go.

If on the other hand you do not know in advance how your People class should be checked, then I'd consider providing an ICheckingFunctions interface that declares the necessary check... methods. But if you go this route, you will perhaps also need to provide a way for the user to change the actually used implementation of ICheckingFunctions.

You should also consider, that while using an interface is certainly much more flexible and extensible, it is also more work to maintain and it could also provide a possible security risk - e.g. if you allow users to change the used ICheckingFunction, then you no longer have control of how your People class is checked.

One possible way to implement such an API using an interface is allowing users to register/unregister the used ICheckingFunction in your class. A very naive implementation could look like this:

public final class CheckingFunctions {
    private static ICheckingFunctions checkFunction;

    public static void registerCheckFunction(ICheckingFunctions checkFunction) {
        CheckingFunctions.checkFunction = checkFunction;
    }

    public static boolean checkName(People ppl){
        return checkFunction.checkName(ppl);
    }

    public static boolean checkAge(People ppl){
        return checkFunction.checkAge(ppl);
    }
}

This is of course just a minimal example. In an actual API you would have to decide quite a lot of additional details. For example:

  • Is there only ever a single ICheckingFunctions instance available? If there may be more registered ICheckingFunctions - how do you choose which of these functions are used?
  • Who is allowed to register/unregister an ICheckingFunctions instance?
  • May the ICheckingFunctions be called from different threads?
  • etc.

You must also consider in which environment your API is going to be used. If you for example want to support usage of your API in an OSGI environment, then you could e.g. supply your ICheckingFunctions as an OSGI service.

Last but not least I would consider the following: May your users subclass the People class? If yes, then it would perhaps be a good idea to make the ICheckingFunctions interface generic, and allow registrations of implementations for different classes. Here again a very naive example of this approach:

public final class CheckingFunctions {
    public interface ICheckingFunctions<T extends People> {
        boolean checkName(T p);    
        boolean checkAge(T p);
    }

    private static Map<Class<?>,ICheckingFunctions<?>> checkFunctions = new ConcurrentHashMap<>();

    public static <T extends People> void registerCheckFunction(ICheckingFunctions<T> checkFunction, Class<T> c) {
        checkFunctions.put(c, checkFunction);
    }

    private static <T extends People> ICheckingFunctions<T> getRegisteredCheckFunction(Class<T> c){
        ICheckingFunctions<T> checkFunction = (ICheckingFunctions<T>) checkFunctions.get(c);
        if (checkFunction == null) {
            // provide some reasonable default?
            throw new IllegalStateException();
        }
        return checkFunction;
    }

    public static <T extends People> boolean checkName(T ppl, Class<T> c){
        return getRegisteredCheckFunction(c).checkName(ppl);
    }

    public static <T extends People> boolean checkAge(T ppl, Class<T> c){
        return getRegisteredCheckFunction(c).checkAge(ppl);
    }
}
Balder
  • 8,623
  • 4
  • 39
  • 61
  • Thanks very much for your elaborated and useful feedback. I actually know how the people class is going to be checked. but just the people class may be changed and I also need to make some change on my checking function. But, I know how the people class is going to change and how I should change my check function. The consumer of my checking function dont need to change their code for existing checking function like check name, and they need to add new function call for newly added checking function like checkingAddress. Yes, I should make the ppl class final cause I just read it not write – Terry Jan 17 '15 at 20:30
  • For the case is like the comment above, should I still use this registering way to build this API ? or static method. How about making all checking funcion the public (non static) method, and define an interface including all these checking function. caller just need to instantiate this interface (e.g., checkingfunctions), and call the function like: checkingfunctions.checkName(ppl); is this also feasible ? For this interface one and class including static methods, which one is recommended ? Thanks – Terry Jan 17 '15 at 20:33
  • If only you alone ever need to change the checking function but your users are never supposed to change them, then I would definitely use public static methods for these functions. But if somehow possible, I'd consider adding a single default checking method instead of multiple ones. E.g. just `public static check(People)`. This default method could then call the more specific functions like `checkName`, `checkAddress` etc. as appropriate. This way your users would perhaps not need to change their code each time you add a new checking function to your code. – Balder Jan 18 '15 at 17:21
  • I wouldn't provide an interface to the public api if you know that there is only ever going to be a single class that extends this interface... – Balder Jan 18 '15 at 17:24
  • Thanks, yes, that is what I did. I create a method call checkPeople including all related method like checkName, checkAge. but the caller told me they also need to access some specific method like checkName individually. Thus, it need to open all checking methods to them. I can use the static method. BTW, I am the only owner of this checking service and no one else can change it. – Terry Jan 18 '15 at 23:02