Zewnętrzne API a flow na produkcji / dev

0

Hej,
tak się zastanawiam jak podejść do problemu, gdzie mamy integrację z różnymi usługami zewnętrznymi, z których chcemy korzystać jedynie w produkcyjnej wersji. Przykład: mamy sklep gdzie chcemy wykonać akcję "finish order". Wiąże się to z kilkoma krokami takimi jak ustawienie statusu, wysłanie maila i inne, ale także na uderzeniu do zewnętrznej usługi, aby zapisać tam jakieś dane. A więc flow wygląda mniej więcej tak:

<?php

class OrdersController 
{
    function finishOrder($orderNumber)
    {
        .
        .
        .
        $this->OrderService->finishOrder($orderNumber)
    }
}

class OrderService 
{
    function finishOrder()
    {
        $this->setStatus();
        $this->sendEmail();
        // sprawdzamy tutaj?
        if ($prodmMode) {
            $this->ExternalService->doSomething();
        }
    }
}

class ExternalService
{
    function doSomething()
    {
        // sprawdzamy tutaj?
        if ($prodmMode) {
            $this->http->makeApiCall(
                [
                    //może tutaj jakiś fake lub pusty url i po prostu pomijamy to wywołanie
                    'url' => ''
                ]
            )
        }
    }
}

I teraz gdzie stawiacie jakąś flagę, która determinuje czy uderzymy do zewnętrznego API w zależności, czy jesteśmy na środowisku testowym, czy produkcyjnym? Robicie to w kontrolerze lub serwisie (Order) na zasadzie if (isProd) czy może w każdym serwisie osobno sprawdzacie taką flagę (serwis per zewnętrzne API) czy może ustawiacie jakiś pusty/predefiniowany URL, który wiadomo, ze nie zadziała, ale flow przejdzie... a może jeszcze inaczej?

Po prostu zastanawiam się jakie podejście jest najlepsze jeśli chodzi o czytelność kodu. Mam trochę starego kodu gdzie to jest na zasadzie sprawdzenia w kontrolerze czy środowisko jest produkcyjne, ale wydaje mi się, ze to zaśmieca kod a na dodatek wraz ze wzrostem liczny zewnętrznych usług tych if-ów jest więcej (jeśli przykładowo wywołania nie mogą być w jednym miejscu) i chciałbym to zrefaktorować trochę.

Ważne: testowa wersja API nie istnieje, a więc nie mogę na dev-ie po prostu uderzyć do niej :)

1

Łączę się z testową wersją zewnętrznego API.

0

@somekind: Wspaniałe założenie, z którego korzystam :)
Zapomniałem niestety wspomnieć, że taka testowa wersja nie istnieje dla niektórych usług i tutaj jest problem :)

3

No to trzeba ją zrobić.

0

Ale to nie jest możliwe na dzień dzisiejszy i nie zależy ode mnie.

0

Literówka (tak a propos wyższości / niższości niektórych języków)

1

SoapUI i niemożliwe staje się możliwe w mniej niż 2-3h.

1

I teraz gdzie stawiacie jakąś flagę, która determinuje czy uderzymy do zewnętrznego API w zależności, czy jesteśmy na środowisku testowym, czy produkcyjnym?

W propertiesach, które są nadpisywane zmiennymi środowiskowymi. Jak nie ma w środowiskowych to jazda z testowymi źródłami / mockami, jak jest to w zależności od tego co tam jest ustawione. W ten sposób łatwo sobie CI/CD można ustawić ;)

1

Jeśli złożoność powierzchni API z której korzystasz nie jest duża, to polecam zaimplementowanie sobie fakea (osobny serwis deployowany tylko na dev/qa). Zagrożeniem jest oczywiście jakakolwiek zmiana zachowania tego zewnętrznego API, ale jeśli nie możesz skorzystać z produkcji (może inne konto?) to wydaje się to rozsądne.

0

Zastosuj wzorzec Strategy. Wyabstrahuj komunikację z API i podmieniaj implemetancję zależnie od konfiguracji. Wtedy jedna implementacja to ta właściwa która uderza po HTTP, natomiast druga zwraca jakiś mock obiekt.

2
  1. Stawiasz http mocka który udaje to zewnętrzne API i jedyne co różni środowisko dev i prod to host/port do tej usługi
  2. Ewentualnie możesz od biedy mieć inną wersje klienta do tej usługi i w zależności od properties albo utworzysz gdzieś RealExternalClient albo FakeExternalClient, ale to jest słabe bo uruchamiasz inny kod niż na produkcji więc rośnie ryzyko ze coś wam nie wyjdzie w testach tylko dopiero na produkcji.

1 użytkowników online, w tym zalogowanych: 0, gości: 1