Czym jest wzorzec Command?

W REST API Allegro istnieją zasoby, które odzwierciedlają typowe operacje CRUD (ang. Create, Read, Update, Delete) i są one zmapowane na odpowiednie metody HTTP POST, GET, PUT, DELETE.

Obok takich zasobów, które są semantycznie proste, występują również zasoby, które odnoszą się do wykonania złożonych operacji lub określonych akcji w odniesieniu do obiektu (np. oferta, transakcja, użytkownik itp.).

Żądanie skierowane do takiego zasobu może wiązać się z wykonaniem kilku operacji po stronie platformy Allegro i/lub dokonaniem zmian w atrybutach obiektów; bądź też wywołuje określone biznesowe konsekwencje dla platformy Allegro (w tym zintegrowanych systemów) oraz użytkowników uczestniczących w danym procesie (wystawienie oferty, transakcja zakupowa). Przykłady takich operacji: “wstrzymanie i wznowienie oferty”, “zmiana ceny Kup Teraz w aktywnej ofercie”.

W przypadku takich operacji realizując RESTowe API zastosowany został wzorzec programistyczny Command.

Command jest operacyjnym wzorcem projektowym, którego celem jest enkapsulacja czynności do wykonania i ich parametrów. Wzorzec ten określa polecenie jako obiekt, który jest wysyłany od klienta do odbiorcy, co pozwala nam na takie funkcjonalności jak: kolejkowanie poleceń, kontrolowanie historii (nawet z operacją ‚undo’) i temu podobne.

Konstrukcja takich zasobów w przypadku Allegro REST API wygląda następująco:

Żądanie:

 PUT /zasób-biznesowy/{identyfikator-zasobu}/{typ-polecenia}-commands/{identyfikator-polecenia-uuid}

Body:

 {
    // dane wejściowe właściwe dla polecenia np.:
    “input”: {
        "buyNowPrice": {
            "amount": "122",
            "currency": "PLN"
         }
    }
 }

Odpowiedź:

 201 Created
 {
    “id”: “9b84e1bc-5341-45e7-837e-4250720e606f”,
    “input”: {
        "buyNowPrice": {
            "amount": "122",
            "currency": "PLN"
         }
    },
    “output”: {
        "status" : "RUNNING",
        "errors" : []
        // inne dane zwrotne  odpowiednie dla tego polecenia
    }
 }

Dla przykładu zasób pozwalający na wykonanie operacji zmiany ceny:

 PUT /offers/12345/change-price-commands/84c16171-233a-42de-8115-1f1235c8bc0f

Wykonując żądanie na powyższy zasób - do kolekcji czynności mających się wykonać na ofercie wskazanej przez identyfikator = 12345, dokładamy polecenie zmiany ceny o identyfikatorze 84c16171-233a-42de-8115-1f1235c8bc0f.

Należy zwrócić uwagę, że w przypadku tych zasobów używamy metody http PUT, a nie POST. Co oznacza, że to klient wskazuje (przesyła) identyfikator pod jakim będzie figurowało zgłoszone polecenie

W celu zapewnienia, że przesyłany od klienta w żądaniu identyfikator polecenia jest unikatowy wymagane są identyfikatory w standardzie UUID.

Zastosowanie

Co daje zastosowanie takiego wzorca?

  • standaryzowany sposób deklaracji wykonania operacji - otrzymujemy jednolite API, a wszystkie złożone operacje wykonujemy na zasobach, które zrealizowane są w taki sam sposób - mamy czynność do wykonania i parametry;

  • standardowy mechanizm śledzenia statusu operacji asynchronicznych - obok zasobu wywoływanego metodą http PUT może istnieć zasób wywoływany poprzez metodę GET, który zwróci aktualny status przetwarzania polecenia;

  • wykonanie operacji w sposób idempotentny - metoda PUT jest idempotentna co oznacza, że każde ponowne żądanie powoduje aktualizację tego samego zasobu i nie zmienia wyniku.

Źródła