dimanche 31 juillet 2022

WebSocket static methods vs instance methods

I need a module that handles connections and subscriptions to one or more specified WebSockets (URLs are hardcoded inside the module). The module provides various methods to interact with these WebSockets and also REST APIs associated with these WebSockets. It should only establish a connection when there's a request and close when the WebSockets are not needed anymore. But it never exposes the WebSocket instances.

This question is not about the inner workings of the module, but about the API. I see two main ways to create the interface: Through static methods (individually exported functions) or through instancing a class that provides those methods.

Both ways have pros and cons. However, I would argue that it doesn't make much sense to create a class with methods that references these WebSockets, since the WebSockets are static by definition (they're declared at the top level of the module, outside any function definitions). This just adds an unnecessary layer of complexity, it's basically a proxi to the static methods. The only benefit I see in creating an instance is that the connection is guaranteed before interacting with the WebSocket in question (see code example below).

I'm interested in your experience and opinion.

The examples should illustrate how these modules could be used. I've coded both and both work. But still not quite sure which is best.

Static methods:

// Import all the functions
import * as SpecificWebSocketManager from 'specific-websocket-manager.js';

// Subscribing to the private WebSocket requires an authentication token
const token = await SpecificWebSocketManager.getWebSocketToken({ apikey: 'string', secret: 'string' });

// Any private subscription requires this token along with other informations 
const subscription = {
    token: 'string',  
    apikey: 'string', 
    name: 'subscriptionName', 
    callback: subscriptionCallback,
};

// The manager establishes a connection to the WebSocket 
//     if it has not yet been established. This is an async call 
// This doesn't guarantee that the subscription will be successful, 
//     the connection might fail
SpecificWebSocketManager.subscribe(subscription).catch();

// The manager closes the WebSocket when there are no more subscriptions
SpecificWebSocketManager.unsubscribe(subscription); 

Instancing:

// Import default
import SpecificWebSocketManager from 'specific-websocket-manager.js';

// The manager establishes a connection to the WebSocket 
//     if it has not yet been established. This is an async call 
// The WebSocket token will be fetched internally if it doesn't exist
// This guarantees that a connection is established if the instance is created
// Note that we anyway need to make a static call to create an instance (factory)
const privateInstance = await SpecificWebSocketManager.privateInstance({ apikey: string, secret: string }).catch(); 

// Apikey is already provided and token already fetched
const subscription = { 
    name: 'subscriptionName',
    callback: subscriptionCallback 
};

// Connection is already established, no async call here
privateInstance.subscribe(subscription);

// The manager keeps the connection alive, even if there are no other subscriptions
//     because I might subscribe again at a later point in time
privateInstance.unsubscribe(subscription);

// The manager only closes the WebSocket if all instances are closed
// This will not allow me to subscribe again
privateInstance.close();

// This will allow me to subscribe again 
privateInstance.connect().catch();

Aucun commentaire:

Enregistrer un commentaire