Projetando interfaces e assíncronas

9

Suponha que eu criei uma interface IFolderRepositorycom métodos assim:

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

e eu implementei DatabaseFolderRepositorye vamos dizer CacheFolderRepositoryDecorator. Agora, 'centenas de linhas depois', gostaria de adicionar a funcionalidade das pastas do SkyDrive para estar pronto para adicionar SkyDriveFolderRepository. Infelizmente, enquanto a DatabaseFolderRepositoryimplementação usou métodos síncronos para conversar com o banco de dados, o skydrive usa muitos asynce await. O que fazer nesse caso? No caso de métodos nulos marcando-o como assíncrono, não é uma solução (é necessário um tratamento de exceção). Devo alterar a interface para retornar Task<T>? Claro que funcionará no exemplo acima, mas são apenas duas classes de implementação de interface. Ou a maioria das minhas interfaces deve ter Tasktipos de retorno (contra você não vai precisar disso)?

fex
fonte
Não relacionado à sua pergunta (desculpe), mas se você tem uma IFolderinterface, por que você confia na implementação concreta ( Folder) em todos os seus métodos?
Konrad Morawski
11
O que seu chamador espera? A API que você implementa é baseada em códigos de erro, exceções, retornos de chamada ou o quê? Você pode mudar isso?
David.pfx
@KonradMorawski foi erro de digitação - desculpe. É baseado em exceções e não posso alterá-lo.
fex

Respostas:

10

Você provavelmente encontrará este artigo do MSDN sobre práticas assíncronas como uma boa leitura.

Você perguntou:

Infelizmente, enquanto a DatabaseFolderRepositoryimplementação usou métodos síncronos para conversar com o banco de dados, o skydrive usa muitos asynce await.

É aqui que a subseção do artigo Async All the Waydo MSDN que vinculei será pertinente à sua situação.

Em particular, geralmente é uma má idéia bloquear o código assíncrono chamando Task.Wait ou Task.Result. Esse é um problema especialmente comum para programadores que estão “mergulhando os pés” em programação assíncrona, convertendo apenas uma pequena parte de seu aplicativo e envolvendo-o em uma API síncrona, para que o restante do aplicativo fique isolado das alterações. Infelizmente, eles têm problemas com impasses.

Como você possui pelo menos uma interface que precisa ser assíncrona, o YAGNI é revertido. Você está indo precisar de fazer alterações para que suas interfaces são consistentes. Sim, isso criará mais esforço antecipadamente para você. Mas o benefício é menos risco de impasse; depuração menos complexa; e bloqueio mais previsível (quando realmente precisa ocorrer).

Estou ignorando algumas das outras perguntas que você fez, pois acho que abordei o núcleo da sua pergunta. Lide com o núcleo e as demais perguntas desaparecem. O artigo é bastante envolvido e aborda os outros pontos que você mencionou, além de apontar armadilhas adicionais.

A programação assíncrona é uma daquelas em que você precisa abraçar todo o conceito e apenas seguir em frente. Tentar apenas "mergulhar os dedos dos pés" em uma base fragmentada acaba sendo muito mais complicado do que simplesmente pular direto.


fonte