Theodor
Theodor

Reputation: 5656

Separation of interface and implementation in api

I am writing a framework built around jUnit for scripting tests in in Java.

It's task based, and each task is executed in sequence. Here is a simplified view:

The interface which all task uses looks like

public interface Task {
    void run(Callback callback);
}

with the Callback interface providing the task with a way to tell the executer that it has finished.

public interface Callback {
    void done();
    void failed(String wtf);
}

I'm also providing the user with an interface to the executor, to an external (physical) interface and to a settings class. I call this the Runtime Environment, and is implemented abstractly:

public abstract class RuntimeEnvironment {
    void execute(Task task) { ... }
    void schedule(Task task, long delay) { ... }
    SomeExternalInterface external();
    Settings settings();
}

where SomeExternalInterface and Settings are interfaces both used by the framework and the implementing user.

The framework might use members like threadPoolSize from Settings, and 'intialize()' and 'cleanUp()' from SomeExternalInterface

The way this class is passed to tasks are currently through the constructor of the implementing task class. I don't like this. It makes for an ambiguous api compared to having the RuntimeEnvironment specified in the Task interface

Why not add it to the task interface you ask? Like

public interface Task {
    void run(Callback callback, RuntimeEnvironment runtime);
}

becouse, running runtime.settings().getThreadPoolSize() is fine (since its specifed in the interface), but what if the user wants to be able to get runtime.settings().getWonkyTimeUnit() or runtime.external().attemptToDefuseImminentExplotion() which he or her specified in the implementation of the respective interfaces? runtime.settings() returns the interface, not the implementing class.

So ...

How do I allow the api-user to specify hes (or hers) own implementation without compromising the generalization and the unambiguousness of the api?

Upvotes: 1

Views: 333

Answers (3)

ollins
ollins

Reputation: 1849

If the user can have his own implementations/interfaces for Settings and External you must allow that. Your api must have the possibility to set/define the type.

public abstract class RuntimeEnvironment<E, S extends Settings> {
...

   E external();
   S settings();
...
}

is one possibility. The user can implement the abstract class and return his own types.

Upvotes: 1

christian.vogel
christian.vogel

Reputation: 2137

If its all about the settings or better the configuration, you could have a look how Apache Hadoop is handling such circumstances. They have a Context where they store a Configuration class. Same like your RuntimeEnvironment and Settings. Internally the Configuration class uses a Map with all the configurations and you can access them via the keys you gave your specific configuration. See: Hadoop Configuration

Upvotes: 1

assylias
assylias

Reputation: 328598

You could allow custom settings to be get / set using strings: runtime.settings().set("wonky_time_unit"); so that users can add as many properties as they want and they will be available through the settings interface: runtime.settings().set("attemptToDefuseImminentExplotion") = true;.

Upvotes: 1

Related Questions