Architecture – Which layer does async code belong

Architectureasynchronous-programmingdomain-driven-designlayers

I am developing an application that consumes data from an external service. The application is being implemented following a typical layered architecture with UI, Presentation, Domain and Data layers. The service client resides within the Data layer.

As is typically the case, I do not want the UI to 'lock-up' while waiting for calls from the external service to complete. However, implementing the service agents with asynchronous methods results in a complicate model chaining async methods up the layers so the UI can stay responsive.

For example:

In the ViewModel:

TheRepository.LoadDataAsync().ContinueWith(t => { _data = t.Result; });

In TheRepository:

public Task<TheData> LoadDataAsync()
{
    return ServiceClient.GetDataFromServiceAsync();
}

(Note, this is a significant over-simplification meant to convey what I mean by task chaining.)

Because the requirement is a UI requirement (prevent the UI from 'locking'), doesn't it make sense to keep the Domain and Data layers synchronous and leave it up to the Presentation layer to decide when it needs to perform some operation asynchronously?

On the other hand, it is so easy and natural to implement the service client/proxy with async methods (VS will auto-generate them if needed) because this is what we think of when we think about the need for async.

If the application was pulling data out of a database instead of making a service call, the layers wouldn't be any different and it shouldn't really change how the UI, Presentation or Domain layers have been implemented, right? In this case, we wouldn't think twice about having the data access be synchronous.

Would it be a better design to model the Domain synchronously and leave it to the Presentation layer to address performance issues in the UI? Or, in the emerging async world, should we just accept async as the norm and make everything fit this model?

Best Answer

Whether a component does work synchronously or asynchronously is an implementation detail. Your design choice for each layer should be independent.

You stated a use case for the UI layer being asynchronous, it needs to not lock up so it should be asynchronous. For each other layer if they have a use case for being asynchronous then make them asynchronous otherwise make them synchronous. As you describe it currently I don't see any advantage in having your repository asynchronous.