Проектирование интерфейсов и асинхронность

9

Предположим, я создал интерфейс IFolderRepositoryс такими методами:

IEnumerable<Folder> GetAllFolders();
Folder GetFolderWithId(int id);
void AddFolder(Folder newFolder);
void ModifyFolder(Folder folderToModify, Folder folderAfterModification);
void RemoveFolder(Folder folderToRemove);

и я реализовал DatabaseFolderRepositoryи скажем CacheFolderRepositoryDecorator. Теперь, «сотни строк спустя», я бы хотел добавить функциональность папок SkyDrive, так что я готов добавить SkyDriveFolderRepository. К сожалению, в то время как DatabaseFolderRepositoryреализация использовала синхронные методы для взаимодействия с базой данных, skydrive one использует много asyncи await. Что делать в таком случае? В случае void методов, помечающих это, асинхронность не является решением (необходимость обработки исключений). Должен ли я изменить интерфейс, чтобы вернуться Task<T>? Конечно, это будет работать в приведенном выше примере, но это всего лишь 2 класса реализации интерфейса. Или у большинства моих интерфейсов должны быть Taskтипы возврата (против вас это правило не понадобится)?

FEX
источник
Не имеет отношения к вашему вопросу (извините), но если у вас есть IFolderинтерфейс, почему вы полагаетесь на конкретную реализацию ( Folder) во всех ваших методах?
Конрад Моравский
1
Что ожидает ваш абонент? API, который вы реализуете, основан на кодах ошибок, исключениях, обратных вызовах или что? Вы можете изменить это?
david.pfx
@KonradMorawski это была опечатка - извините. Он основан на исключениях, и я не могу его изменить.
февраля

Ответы:

10

Вы, вероятно, найдете эту статью MSDN об асинхронных практиках хорошей читкой.

Ты спросил:

К сожалению, в то время как DatabaseFolderRepositoryреализация использовала синхронные методы для взаимодействия с базой данных, skydrive one использует много asyncи await.

Именно здесь подраздел Async All the Wayв статье MSDN, который я связал, будет иметь отношение к вашей ситуации.

В частности, обычно плохая идея блокировать асинхронный код, вызывая Task.Wait или Task.Result. Это особенно распространенная проблема для программистов, которые «погружают свои пальцы» в асинхронное программирование, преобразуя лишь небольшую часть своего приложения и оборачивая его в синхронный API, чтобы остальная часть приложения была изолирована от изменений. К сожалению, они сталкиваются с проблемами с тупиками.

Поскольку у вас есть хотя бы один интерфейс, который должен быть асинхронным, YAGNI меняется на противоположный. Вы это собирается необходимо внести изменения , чтобы ваши интерфейсы совместимы. Да, это создаст больше усилий для вас. Но выгода - меньше риск тупика; менее сложная отладка; и более предсказуемое блокирование (когда это действительно должно произойти).

Я пропускаю некоторые другие вопросы, которые вы задавали, так как я думаю, что рассмотрел суть вашего вопроса. Разберитесь с ядром, а остальные ваши вопросы отпадут. Эта статья довольно интересна и затрагивает другие затронутые вами вопросы, а также указывает на дополнительные подводные камни.

Асинхронное программирование является одним из тех, где вы должны охватить всю концепцию и просто пойти с ней. Попытка просто «опустить пальцы» по частям оказывается намного сложнее, чем просто прыгать прямо внутрь.


источник