0

I want to build an API (Java) that heavily relies on a connection object to a data server that manages a connection to a real device. All i have is a DeviceConnection object. Currently i have a big class that presents the user with everything the device can do and manage the connection object inside that class.

That works quite well when working with the API as it is, but becomes really complex and hard to use when trying to test against it. It also violates the Single Responsibility Principle.

How would you structure an API, where almost all the calls depend on a single connection object? What about calls that just configure the device and calls that return some rather uninteresting device specific information?

This is what i would think of:

DeviceConnection conn = new DeviceConnection();
conn.connect(connectionData);

// This one is kinda ok
DeviceDataReceiver dataRec = new DeviceDataReceiver(conn);
Data data = dataRec.getData();

// This one feels like i don't really need the object
DeviceInformation devInfo = new DeviceInformation(conn);
Information info = devInfo.getInfo();

// This one feels really awkward to use
DeviceSettingsManager settingsManager = new DeviceSettingsManager(conn);
settingsManager.setOptionA(true);

How would you architect this kind of API? How should i name my classes? How should i pass around my connection object?

It's not that my approaches are not working, it's just that it doesn't feel like a good API at the moment.

1 Answer 1

1

Typically there are few improvements you can do to this API, to make it better,

  1. Use interfaces
  2. Use DI

So it would look like,

    public interface IDeviceConnectionProvider{
        DeviceConnection GetConnection();
        CloseConnection(DeviceConnection conn);
    }

    public class DeviceConnectionProvider : IDeviceConnectionProvider {
        public DeviceConnection GetConnection(){
           DeviceConnection conn = new DeviceConnection();
           conn.connect(connectionData);
           return conn;
        }

        public void CloseConnection(DeviceConnection conn)
        {
            //close it
        }
}

This class will create the connection to the device, and close it. Depending on your requirement and resource intensity of opening a connection, you might want to pool connections here, but it's out of the scope of this discussion.

public interface IDeviceDataReceiver{
     public Data GetData();
}

public class DeviceDataReceiver : IDeviceDataReceiver {
     private IDeviceConnectionProvider connectionProvider;

     public DeviceDataReceiver( IDeviceConnectionProvider provider){
         this.connectionProvider = provider;
     } 

     public Data GetData(){
         DeviceConnection conn = this.connectionProvider.GetConnection();
         Data data = //get data from connection;
         this.connectionProvider.CloseConnection(conn);
         return data;
     }
}

Now you have to register interfaces and their implementation in DI container.

When you want to use it somewhere, simply inject your API,

public class SomeClass : ISomeInterface
{
    private IDeviceDataReceiver receiver;

    public SomeClass(IDeviceDataReceiver receiver){
        this.receiver = receiver;
    } 

    public void DoSomethingWithDeviceData(){
        Data data = this.receiver.GetData();
        //do stuff
    }
}
3
  • I already use interfaces for almost every class, mostly to make testing (specifically mocking) more easy. The code in your last example actually looks pretty clean, i might go with that. Any ideas how i should name the class that only configures the device? May 31, 2016 at 6:52
  • And what do you think about a factory class that returns "pre-configured" working objects based on a connection? Something like IDeviceConfigurator configurator = DeviceCommunicationFactory.getConfigurator(connection);? May 31, 2016 at 6:58
  • 1
    assuming device configuration is to obtain the connection,you could pass something like device id to the IDeviceConnectionProvider , where it can read additional config values from a store and do needful. About the second question, this pattern is known as service locator pattern, while it might be useful in some cases like designing a public API, one drawback is every class will have a dependency on your service locator for more info see stackoverflow.com/questions/1557781/… Jun 1, 2016 at 0:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.