设计接口和异步


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使用了很多asyncawait。在这种情况下该怎么办?在使用void方法将其标记为异步的情况下,这不是解决方案(需要进行异常处理)。我应该更改接口返回Task<T>吗?当然可以在上面的示例中使用,但是它们只是2个接口实现类。还是我的大多数接口都应该具有Task返回类型(因此您不需要规则)?


与您的问题无关(抱歉),但是,如果您有IFolder接口,为什么Folder在所有方法中都依赖具体的实现()?
康拉德·莫劳斯基

1
您的来电者期待什么?您实现的API是基于错误代码,异常,回调还是什么?你能改变吗?
david.pfx 2014年

@KonradMorawski,这是拼写错误-抱歉。它基于例外,我无法更改。
fex 2014年

Answers:


10

您可能会发现这篇有关异步实践的 MSDN文章很不错。

您问:

不幸的是,当DatabaseFolderRepository实现使用同步方法与数据库进行通信时,skydrive使用了很多asyncawait

这是Async All the Way我链接的MSDN文章中的小节,与您的情况有关。

特别是,通过调用Task.Wait或Task.Result阻止异步代码通常是一个坏主意。对于正在“将脚趾浸入”异步编程,仅转换其应用程序的一小部分并将其包装在同步API中的程序员来说,这是一个特别常见的问题,因此应用程序的其余部分不受更改的影响。不幸的是,它们遇到了死锁问题。

由于您至少有一个需要异步的接口,因此YAGNI是反向的。你会需要修改,以便您的接口是一致的。是的,它将为您带来更多的努力。但是好处是死锁的风险降低了。调试不太复杂;和更可预测的阻止(实际上需要发生时)。

我跳过了您提出的其他一些问题,因为我认为我已经解决了您问题的核心。处理核心问题,其余问题就消失了。这篇文章相当涉及,并论述了您提出的其他要点,并指出了其他陷阱。

异步编程是其中您必须接受整个概念并随其而去的一种方法。尝试只是零散地“浸入脚趾”最终会变得复杂得多,然后直接跳进去。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.