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 okDeviceDataReceiver dataRec = new DeviceDataReceiver(conn);Data data = dataRec.getData();// This one feels like i don't really need the objectDeviceInformation devInfo = new DeviceInformation(conn);Information info = devInfo.getInfo();// This one feels really awkward to useDeviceSettingsManager 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.
Building an API with one central connection object to an external device
java;architecture;api
Typically there are few improvements you can do to this API, to make it better,Use interfacesUse DISo 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    }}