2014-08-28 15 views
6

Myślę, że jest to raczej ogólne pytanie (więc nie php ograniczone) w odniesieniu do ddd i wzorca polecenia.Schemat poleceń w aplikacjach php: jak radzić sobie z działaniami kontrolera?

Załóżmy, że wykonuję CreatePostCommand z poziomu działania create mojego kontrolera, polecenie zostanie obsłużone i ostatecznie zostanie pomyślnie wykonane. Jaki jest właściwy sposób powiadomienia kontrolera, która odpowiedź ma zostać zwrócona w przypadku niepowodzenia lub sukcesu polecenia? Biorąc pod uwagę, że obsługa komend uruchomi zdarzenie związane z daną domeną, mógłbym podłączyć kontroler do zdarzenia, ale to wydaje się dość kłopotliwe, również nieodpowiednie w każdej sytuacji (np. Post mógł zostać utworzony gdzieś indziej, a kontroler naprawdę nie o tym wiedz :)).

public function createAction($title, $content) 
{ 
    $this->commandBus->execute(new CreatePostCommand($title, $content); 

    $this->render('…'); // what if the command execution failed? 
} 

Jakieś przemyślenia na ten temat?

+0

Jeśli wykonanie nie powiedzie się, zostanie zgłoszony wyjątek, co oznacza, że ​​linia, którą skomentowałeś, nie zostałaby uruchomiona. –

+2

Tak, na pewno. Powinienem być bardziej konkretny tutaj.Powiedzmy, że wykonanie polecenia powiodło się i chcę przekierować do/post/edit/{$ id}, kontroler nie byłby świadomy tego posta, chyba że zarówno kontroler, jak i kontroler akcji udostępnią np. repozytorium wpisów. Czy to ma więcej sensu. – iwyg

+0

Powracanie wartości z polecenia spowoduje przerwanie wzorca. Więc tak, masz rację, że zarówno kontroler, jak i obsługa dowodzenia będą musieli wiedzieć o repozytorium. Ale jeśli potrzebujesz czegoś, co powróci z polecenia, spójrz na wzór funktora. –

Odpowiedz

1

Wydaje mi się, że jeśli naprawdę próbujesz przestrzegać schematu poleceń DDD, musisz potraktować magistralę poleceń jako pożar i zapomnieć o procesie asynchronicznym, który może zająć dużo czasu.

Rozważ natychmiastowe przekierowanie do kontrolera weryfikatora poleceń. Od weryfikatora komend zależy aktywne sprawdzenie statusu polecenia i sprawdzenie, czy zadziałało.

W większości przypadków polecenie zakończy się pomyślnie, a następnie Twój weryfikator może ponownie przekierować, aby kontynuować normalny przepływ.

Jeśli polecenie nie powiedzie się, wówczas weryfikator wstawi odpowiedni komunikat o błędzie.

Jeśli polecenie jest w toku, można wykonać całą pętlę przekierowania, informując użytkownika, że ​​polecenie jest w toku.

Coś jak:

// Execute the command 
$command = new CreatePostCommand($title, $content); 
$this->commandBus->execute($command); 

return redirect '/command-verifier/' . $command->getId(); 

// The verification action 
public function verifyCommandAction($commandId) 

$commandStatus = $this->commandBus->getStatus($commandId); 

if ($commandStatus == SUCCESS) redirect to all is well; 

if ($commandStatus == FAILED) then oops; 

if ($commandStatus == IN_PROGRESS) then maybe pause a bit and redirect again while keeping the user informed. 

Oczywiście jest sporo macha ręką dzieje, ale myślę, że jest to najbardziej ogólne podejście zwłaszcza z php gdzie każde żądanie rozpoczyna się od punktu zerowego.

+0

Być może źle cię zrozumiałem, ale to oznaczałoby, że obiekt polecenia $ w późniejszym momencie ma przypisaną wartość identyfikatora? To by znaczyło, że nie jest niezmienny. Częścią tej techniki jest to, że twoje polecenie sygnalizuje intencję, a nie stan lub zachowanie - to podejście łamie ten paradygmat. – Oddman

+0

A alternatywą jest? Jeśli celem jest utworzenie postu, to w jaki sposób sygnalizowałbyś, czy post został utworzony, czy nie? – Cerad

+0

Istnieje kilka sposobów - jednym jest, aby program obsługi komend zwrócił pomyślne utworzenie postu (standardowe zachowanie), ale w przypadku błędu (nieco trudniejszego) można albo wyrzucić wyjątek, albo napisać usługę, która zarządza tymi oczekiwaniami za pomocą kontrolera wstrzyknięty jako zależność obserwatora, która może sformułować poprawną odpowiedź na podstawie wyniku wykonania polecenia. – Oddman

0

Sposób, w jaki obecnie to robię jest następujący (przepraszam długi wpis).

public function createAction($title, $content) { 
    try { 
     $post = $this->commandBus->execute(new CreatePostCommand($title, $content); 
    } 
    catch (Exception $e) { 
     return $this->render('some error template file', $e); 
    } 

    return $this->render('successful creation template file', $post); 
} 

ten sposób tworzysz post i jeśli wszystko pójdzie zgodnie z planem, zwróci obiekt $ post i wysłać to do widzenia. Z drugiej strony, gdy wyjątek jest zgłaszany podczas wykonywania, wychwytujesz ten błąd i wysyłasz go do widoku.

Mój preferowanym sposobem jest połączenie kontrolera metodę na usługi, która udaje, że zachowanie i mieć kontroler wstrzykiwany jako słuchacz, który zarządza odpowiedzi, a mianowicie:

public function createAction($title, $content) { 
    $service = new CreateActionService($title, $content); 

    return $service->create($this); 
} 

public function onError(Exception $e) { 
    return $this->render('some error template file', $e); 
} 

public function onSuccess($post) { 
    return $this->render('success', $post); 
} 

Następnie w swojej służbie. ..

public function create($listener) 
{ 
    try { 
     $this->commandBus->execute(new CreatePostCommand($title, $content); 
    } 
    catch (Exception $e) { 
     return $this->listener->onError($e); 
    } 

    return $this->listener->onSuccess($post); 
} 

ten sposób usługa jest zarządzanie różnymi wyniki handler komenda może powrócić, a kontroler pozostaje po prostu zarządzać odpowiedzi, które możesz wrócił do swojej warstwy prezentacji.

+0

Co jest w porządku, gdy kontroler może czekać na zakończenie polecenia. Ale w krainie DDD mamy pojęcie o ostatecznej spójności, w której zakończenie operacji może potrwać kilka minut, godzin lub nawet dni. Dwa zupełnie różne problemy. – Cerad

+0

Jest to prawdą, zwłaszcza jeśli mówimy o takich rzeczach, jak systemy CQRS. W obu przypadkach mogą wystąpić i wystąpić problemy - a zarządzanie nimi w ten sposób oznacza, że ​​starannie dbasz o wszelkie problemy, które mogą wystąpić z nieprzewidzianych okoliczności. – Oddman