In his book "Concurrency in C# Cookbook", Stephen Cleary writes:
If you can, try to organize your code along modern design guidelines, like Ports and Adapters (Hexagonal Architecture), which separate your business logic from side effects such as I/O. If you can get into that situation, then there's no need to expose both sync and async APIs for anything; your business logic would always be sync and the I/O would always be async.
However, I don't find that to be true in my design and I am wondering how it's supposed to be so I can have a sync domain and async infrastructure code.
For example, given the following:
public interface IContentRepository
{
Content GetContent (Guid contentId);
}
public class MyDomainObject
{
public void Foo (IContentRepository repo)
{
var content = GetContent(someId);
...
}
}
public class ContentRepository : IContentRepository
{
// Uh oh, either...
// 1. implement it sync here or
// 2. use sync-over-async or
// 3. make IContentRepository return Task<Content> (and live with an async domain)
}
How's that supposed to be designed such that my domain can stay sync-only and can make use of async infrastructure code. Is that even possible? Have I misunderstood Stephen?