To pytanie dotyczy języka C #, ale spodziewam się, że obejmie inne języki, takie jak Java lub TypeScript.
Microsoft zaleca najlepsze praktyki korzystania z wywołań asynchronicznych w .NET. Spośród tych rekomendacji wybierzmy dwa:
- zmień podpis metod asynchronicznych, tak aby zwracały Zadanie lub Zadanie <> (w TypeScript byłoby to Obietnicą <>)
- zmień nazwy metod asynchronicznych na końcówkę xxxAsync ()
Teraz, gdy zamieniasz synchroniczny komponent niskiego poziomu na asynchroniczny, wpływa to na cały stos aplikacji. Ponieważ async / await ma pozytywny wpływ tylko wtedy, gdy jest używany „do samego końca”, oznacza to, że podpis i nazwy metod każdej warstwy w aplikacji muszą zostać zmienione.
Dobra architektura często wymaga umieszczania abstrakcji między poszczególnymi warstwami, tak że zamiana komponentów niskiego poziomu na inne jest niewidoczna dla komponentów wyższego poziomu. W języku C # abstrakcje mają formę interfejsów. Jeśli wprowadzimy nowy komponent asynchroniczny niskiego poziomu, każdy interfejs w stosie wywołań musi zostać zmodyfikowany lub zastąpiony nowym interfejsem. Sposób rozwiązania problemu (asynchronizacja lub synchronizacja) w klasie implementującej nie jest już ukryty (abstrakcyjny) dla dzwoniących. Dzwoniący muszą wiedzieć, czy jest to synchronizacja czy asynchronizacja.
Czy asynchronizacja / oczekiwanie na najlepsze praktyki nie są sprzeczne z zasadami „dobrej architektury”?
Czy to oznacza, że każdy interfejs (powiedzmy IEnumerable, IDataAccessLayer) potrzebuje swojego asynchronicznego odpowiednika (IAsyncEnumerable, IAsyncDataAccessLayer), aby można je było zamienić na stosie podczas przełączania na zależności asynchroniczne?
Jeśli posuniemy problem nieco dalej, czy nie byłoby łatwiej założyć, że każda metoda jest asynchroniczna (aby zwrócić Zadanie <> lub Obietnica <>), oraz metody synchronizacji wywołań asynchronicznych, gdy tak naprawdę nie są asynchronizować? Czy tego należy się spodziewać w przyszłych językach programowania?
CancellationToken
, a te, które to robią, mogą chcieć podać wartość domyślną). Usunięcie istniejących metod synchronizacji (i proaktywne złamanie całego kodu) jest oczywistym początkiem.