Existuje elegantní řešení pro manipulaci zpětná volání z externích zařízení v čisté architektuře?

0

Otázka

Jsem budování komplexní systém, založený na čisté architektury (https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html), s použitím mnoha externích komponent, například platební terminál. Uvedené platební terminál má knihovna, která obsahuje základní funkce, včetně místa předat callback, tak, že terminál může informovat o průběhu transakce, např. (vložte pin nebo odebrat platební kartu).

Uvažujme scénář:

  1. Uživatel stiskne tlačítko "Provést transakci", pomocí nějakého adaptéru, systém zjistí, že uživatel chce provádět transakce.
  2. Systém využívající jiný druh adaptéru volání externího rozhraní API, a řekne "provést transakci".
  3. Nyní bychom chtěli informovat uživatele o pokroku... přes externí API callback.

aby bylo možné použít zpětné volání API, jeden nebo více z našich aplikací třídy musí implementovat metodu zpětného volání(s), a proto musí splňovat některé abstrakci definované API poskytovatele. Takže naše třídy musí záviset na API. Což znamená, že API nemůže být snadno terčem posměchu či narazil. Musíme zacházet s našimi callback objekty jako součást adaptér pro rozhraní API, a zkontrolujte ostatní aplikace tím, zesměšňovat nebo klučky.

Na jednu stranu, nechtěl bych, aby architektura závislá na externí API, ale vytvoření nové entity, konkrétně zvládnout API událostí se zdá, přes-inženýrství na mě.

2

Nejlepší odpověď

0

Chtěl bych vytvořit pokroku rozhraní, v případě použití vrstvy, protože to hlásí průběh případu užití.

Pak bych realizovat pokrok presenteru a předat ji k užívání věci, když je nazývá správce.

Případ užití může pak projít postup do platebního terminálu přes adaptér je rozhraní.

+------------+     +-------------------+  <<create>>  +------------+
| View Model | <-- | ProgressPresenter | <----------  | Controller |
+------------+     +---------+---------+              +------------+
                             |                              |
UI                           |                              |
=============================|==============================|==========
Use Case                     V                              V
                       +----------+                    +----------+
                       | Progress |                    | Use Case |
                       +----------+                    +----------+
                             ^                              |
                             |                              V
                             |                     +-----------------+
                             |                     | PaymentTerminal |   
                             |                     +-----------------+
                             |                              | 
=============================|==============================|==========
External                     |                              V
                             |                  +------------------------+
                             +------------------| PaymentTerminalAdapter |
                                                +------------------------+

V klientovi aplikace ViewModel je obvykle připojen k součásti uživatelského ROZHRANÍ prostřednictvím pozorovatel vztah a způsobí UI aktualizovat, když ViewModel změny. Do webové aplikace můžete buď to udělat přes nějaký websocket nebo uložit pokrok v nějaký druh úložiště (relace nebo databáze) a nechat klienta anketa hodnotu.

2021-11-16 06:14:12

Děkuji vám za odpověď. V odkazu na diagramu, 'PaymentTerminalAdapter muset přeložit externí API pro domény protějšek. Tak například, pokud terminál 3 zpětné volání stavy v popsané enum (ENTER_CARD, ENTER_PIN, REMOVE_CARD) nyní musíme vytvořit doménu subjekt, což bude ekvivalentní koncových stavů. Rozumím tomu správně?
akkolyth

To je pravda. Nebo můžete vytvořit TerminalProgress to poskytuje metody enterCard(), enterPin(), removeCard() a moderátor provádění dělá to, co je třeba aktualizovat zobrazení modelu.
René Link

@akkolyth jsem vyslán další odpověď, která vám mohou pomoci udělat dobré rozhodnutí.
René Link
0

Jsem znovu myslel, že moje předchozí odpověď. Tam je možná lepší řešení, protože Terminal vypadá to, že jen další I/O zařízení. Pokud toto řešení je vhodné pro vás, závisí na tom, jak terminal api je určen.

Protože nevím, jak api funguje, budu předpokládat, že něco. Možná, že to vyhovuje vašim požadavkům, nebo vám dává nové nápady.

Vytvořit koncový adaptér při spuštění terminálové relace a připojení k presenteru. Můžete volat případy použití a předat jim PaymentTerminal rozhraní.

+-----------+                    
| ViewModel |
+-----------+
      ^
      |
+-----------+     +-----------------+      +------------+
| Presenter | <-- | TerminalAdapter | <--- | Controller |
+-----------+     +-----------------+      +------------+
                           ^                     |
===========================|=====================|===============
                           |                     V
                     +----------+          +----------+
                     | Terminal | <------- | Use Case |
                     +----------+          +----------+

Některé pseudo controller kód:

public void startPaymentSession(){
    PaymentModel paymentModel = .. // get the model
    PaymentPresenter paymentPresenter = new PaymentTerminalPresenter(paymentModel);

    this.paymentTerminalAdapter = new PaymentTerminalAdapter();
    this.paymentTerminalAdapter.setCallbacks(paymentPresenter);

    UseCase uc = new UseCase(this.paymentTerminalAdapter);
    uc.execute();
}

V tomto případě jsme se připojit vnější vrstva' Terminal API pomocí adaptéru (Terminal API pokrok subjekty Moderátorka pokrok subjekty) de facto obcházet případ použití vrstvy. Zda to by mohlo způsobit nějaké architektonické porušení? Každopádně, osobně se toto řešení zdá být rozumné, aby mě.

Protože já nevím terminálu api používáte, mohu jen hádat...

Pro mě to vypadá jako terminál api je míchání pohled a aplikační logiky věci. Tam je nějaký druh registrace zpětného volání používá k informování uživatele a další metody, které zpracovávají aplikační logiky. Tak bych propojit termial api UI část v presenteru a předat část aplikační logiky (jako interface) pro případ použití. V tomto případě si myslím, že to není architektonický porušení, protože část terminálu adaptér je zařízení I/O.

To by mohlo být špatně, protože je to založené na mé předpoklady. Nicméně jsem vám chtěla ukázat další způsob, jak pro situace, kdy moje předpoklady jsou pravdivé.

Nakonec myslím, že to není opravdu jedno, pokud se podíváme na terminálu api jako externí služby nebo I/O zařízení. Pro mě jeden gól architektury je důležitější - testovatelnost případy použití, moderátor a tak dále.

2021-11-17 06:26:29

Zajímavé, na jednu stranu díky tomuto řešení nemáme definovat více domény entit, které by odpovídaly těm z terminálu API (to je bohužel nucen často používaný), tak je to v pořádku. Nicméně v tomto případě jsme se připojit vnější vrstva' Terminal API pomocí adaptéru (Terminal API pokrok subjekty Moderátorka pokrok subjekty) de facto obcházet případ použití vrstvy. Zda to by mohlo způsobit nějaké architektonické porušení? Každopádně, osobně se toto řešení zdá být rozumné, aby mě.
akkolyth

V jiných jazycích

Tato stránka je v jiných jazycích

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................