Projektowanie interfejsów i asynchronizacji

9

Załóżmy, że utworzyłem interfejs IFolderRepositoryz takimi metodami:

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

i wdrożyłem DatabaseFolderRepositoryi powiedzmy CacheFolderRepositoryDecorator. Teraz „setki linii później” Chciałbym dodać funkcjonalność folderów SkyDrive, więc jestem gotowy do dodania SkyDriveFolderRepository. Niestety, podczas gdy DatabaseFolderRepositoryimplementacja używała synchronicznych metod do komunikowania się z bazą danych, skydrive używa wielu asynci await. Co zrobić w takim przypadku? W przypadku metod void oznaczenie go jako asynchronicznego nie jest rozwiązaniem (potrzeba obsługi wyjątków). Czy powinienem zmienić interfejs, aby powrócić Task<T>? Pewnie, że zadziała w powyższym przykładzie, ale są to tylko 2 klasy implementacji interfejsu. A może większość moich interfejsów ma Tasktypy zwrotów (przeciwko tobie nie będzie to potrzebne)?

fex
źródło
Niepowiązane z twoim pytaniem (przepraszam), ale jeśli masz IFolderinterfejs, dlaczego polegasz na konkretnej implementacji ( Folder) we wszystkich swoich metodach?
Konrad Morawski
1
Czego oczekuje Twój rozmówca? Czy implementowany interfejs API oparty jest na kodach błędów, wyjątkach, wywołaniach zwrotnych lub co? Czy możesz to zmienić?
david.pfx
@KonradMorawski to błąd literówki - przepraszam. Opiera się na wyjątkach i nie mogę tego zmienić.
fex

Odpowiedzi:

10

Prawdopodobnie ten artykuł MSDN o praktykach asynchronicznych będzie dobrym lektorem.

Zapytałeś:

Niestety, podczas gdy DatabaseFolderRepositoryimplementacja używała synchronicznych metod do komunikowania się z bazą danych, skydrive używa wielu asynci await.

W tym miejscu podsekcja Async All the Wayw artykule MSDN, który podłączyłem, będzie związana z twoją sytuacją.

W szczególności zwykle złym pomysłem jest blokowanie kodu asynchronicznego przez wywołanie Task.Wait lub Task.Result. Jest to szczególnie powszechny problem dla programistów, którzy „zanurzają palce u stóp” w programowanie asynchroniczne, przekształcając tylko niewielką część swojej aplikacji i pakując ją w synchroniczny interfejs API, aby reszta aplikacji była odizolowana od zmian. Niestety mają problemy z impasem.

Ponieważ masz co najmniej jeden interfejs, który musi być asynchroniczny, YAGNI jest odwrócony. Państwo to będzie trzeba wprowadzić zmiany tak, że interfejsy są spójne. Tak, będzie to dla ciebie więcej wysiłku. Ale korzyścią jest mniejsze ryzyko impasu; mniej skomplikowane debugowanie; i bardziej przewidywalne blokowanie (kiedy faktycznie musi nastąpić).

Pomijam niektóre inne pytania, które zadałeś, ponieważ myślę, że odniosłem się do sedna twojego pytania. Zajmij się rdzeniem, a reszta twoich pytań odpada. Artykuł jest dość zaangażowany i dotyczy innych poruszonych kwestii, a także wskazuje dodatkowe pułapki.

Programowanie asynchroniczne jest jednym z tych, w których musisz przyjąć całą koncepcję i po prostu iść z nią. Próba po prostu „zanurzenia palców” na kawałku sprawia, że ​​jest o wiele bardziej skomplikowana niż po prostu skakanie prosto.


źródło