[Development] async operation error guidance

Frank Osterfeld frank.osterfeld at kdab.com
Tue Nov 5 17:41:50 CET 2013


On Nov 5, 2013, at 5:12 PM, Tony Van Eerd wrote:

> Most of BlackBerry's APIs are async.
> We are looking at moving some of these APIs into Qt.
> Just as one  example, WiFi Direct.
> 
> I have been attempting to come up with some solid guidelines of how to deal with errors on async operations.
> 
> Some things to consider:
> 
> - the initial request may fail. ie
> 
> 	WifiDirect::connectToDevice(someparams);
> 
> this could fail immediately if wifi is not on or various other reasons.  So does it return an error:
> 
> 	ConnectError connectToDevice(SomeParams someparams);
> 
> or should even the immediate error be made async?

I'd prefer to have all errors be async, for what's it's worth. That the connect can fail immediately is an implementation detail to me, and
requires yet another code path for error handling.

> 
> It could also fail later, as it is mostly asynchronous. Or it could succeed with a result. ie
> 
> 	Q_SIGNAL void deviceConntected(SomeDevice device);
> 	Q_SIGNAL void deviceConnectionFailed(SomeOtherConnectError error);
> 
> or one signal:
> 
> 	Q_SIGNAL void deviceConnectionResult(SomeDevice device, ConnectionResult result);

Looking at other async APIs like QProcess and QNetworkReply having two signals isn't unusual.

> Also consider that there are multiple async operations, not just 'connectToDevice'.  There is scan, startSession, etc.
> 
> Should there be a single error() covering everything?  Or one per task? Or a way to link the error back to the task?
> 
> 	RequestId startSession();
> 	RequestId startScan();
> 
> 	Q_SIGNAL void error(RequestId requestId, BigSetOfErrorEnums error, QString errorStringAsWellMaybe);

Please don't! Such APIs are ugly and hard to use. I'd consider to wrap the operations in classes and return them when starting the operation.
Like QNetworkAccessManager does for QNetworkReply. The returned object then handles the state and emit the signals for the particular context.
E.e. connectToDevice() could return a WiFiDevice or WiFiConnection object, which then handles the state for that particular connection.

> And there are a bunch more considerations. ie:
> 
> - "Error" vs "Result"  (I dislike Error::NoError, prefer Result::Success)

I think error is more consistent, but I don't have a strong opinion here.

> - Is "finished()" OK if it didn't _complete_ (successfully) or should it be... "ended()" or some better word?

finished() is commonly used also when operations succeed (e.g. QNetwork). It shouldn't be too many different signals, otherwise users will forget 
to connect to some of the signals.

-- 
Join us in November at Qt Developer Days  2013 - https://devdays.kdab.com

Frank Osterfeld | frank.osterfeld at kdab.com | Senior Software Engineer
KDAB (Deutschland) GmbH&Co KG, a KDAB Group company
Tel. Germany +49-30-521325470, Sweden (HQ)  +46-563-540090
KDAB - Qt Experts - Platform-independent software solutions




More information about the Development mailing list