Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Czy zarządzanie transakcjami w kontrolerze to zła praktyka?

Powodem, dla którego mówię, że transakcje nie należą do warstwy modelu jest w zasadzie:

Modele mogą wywoływać metody w innych modelach.

Jeśli model próbuje rozpocząć transakcję, ale nie wie, czy osoba wywołująca już rozpoczęła transakcję, musi warunkowo rozpocznij transakcję, jak pokazano w przykładzie kodu w @Odpowiedź Bubby . Metody modelu muszą akceptować flagę, aby osoba wywołująca mogła powiedzieć, czy może rozpocząć własną transakcję, czy nie. W przeciwnym razie model musi mieć możliwość odpytywania swojego rozmówcy o stan „w transakcji”.

public function setPrivacy($privacy, $caller){
    if (! $caller->isInTransaction() ) $this->beginTransaction();

    $this->privacy = $privacy;
    // ...action code..

    if (! $caller->isInTransaction() ) $this->commit();
}

A jeśli dzwoniący nie jest przedmiotem? W PHP może to być metoda statyczna lub po prostu kod niezorientowany obiektowo. To staje się bardzo nieuporządkowane i prowadzi do wielu powtarzających się kodów w modelach.

Jest to również przykład Sprzęgła sterującego , co jest uważane za złe, ponieważ wywołujący musi coś wiedzieć o wewnętrznym działaniu wywoływanego obiektu. Na przykład niektóre metod Twojego Modelu może mieć parametr $transactional, ale inne metody mogą nie mieć tego parametru. Skąd rozmówca ma wiedzieć, kiedy parametr ma znaczenie?

// I need to override method's attempt to commit
$video->setPrivacy($privacy, false);  

// But I have no idea if this method might attempt to commit
$video->setFormat($format); 

Inne rozwiązanie, które widziałem sugerowane (lub nawet zaimplementowane w niektórych frameworkach, takich jak Propel), to zrobienie beginTransaction() i commit() no-ops, gdy DBAL wie, że jest już w transakcji. Ale może to prowadzić do anomalii, jeśli twój model próbuje dokonać zatwierdzenia i stwierdzi, że tak naprawdę nie jest zatwierdzony. Lub próbuje wycofać i ignoruje to żądanie. Pisałem o tych anomaliach już wcześniej.

Zasugerowany przeze mnie kompromis polega na tym, że modele nie wiedzą o transakcjach . Model nie wie, czy jego żądanie do setPrivacy() jest czymś, co należy zatwierdzić natychmiast, czy też jest częścią większego obrazu, bardziej złożonej serii zmian, która obejmuje wiele modeli i powinna tylko zostać popełnione, jeśli wszystkie te zmiany się powiedzie. To jest punkt transakcji.

Więc jeśli Modelki nie wiedzą, czy mogą lub powinny rozpocząć i dokonać własnej transakcji, to kto wie? GRASP zawiera Wzorzec kontrolera która jest klasą niezwiązaną z interfejsem użytkownika dla przypadku użycia i przypisuje się jej odpowiedzialność za tworzenie i kontrolowanie wszystkich elementów w celu wykonania tego przypadku użycia. Administratorzy wiedzą o transakcjach ponieważ w tym miejscu dostępne są wszystkie informacje o tym, czy cały przypadek użycia jest złożony i wymaga wielu zmian w modelach, w ramach jednej transakcji (lub być może w kilku transakcjach).

Przykład, o którym pisałem wcześniej, czyli rozpoczęcie transakcji w beforeAction() metody kontrolera MVC i zatwierdź ją w afterAction() metoda, jest uproszczeniem . Kontroler powinien mieć swobodę uruchamiania i zatwierdzania tylu transakcji, ile logicznie wymaga do zakończenia bieżącej akcji. Czasami kontroler może powstrzymać się od jawnej kontroli transakcji i pozwolić Modelom na automatyczne zatwierdzanie każdej zmiany.

Ale chodzi o to, że informacje o tym, jakie transakcje są konieczne, są czymś, czego Modele nie znają -- trzeba im je przekazać (w formie parametru $transactional) albo zapytać o to od wywołującego, który i tak musiałby delegować pytanie aż do działania kontrolera.

Możesz także utworzyć Warstwę usług klas, z których każda wie, jak wykonać tak złożone przypadki użycia i czy zawrzeć wszystkie zmiany w jednej transakcji. W ten sposób unikniesz wielu powtarzających się kodów. Ale nie jest powszechne, że aplikacje PHP zawierają odrębną warstwę usług; działanie kontrolera jest zwykle zbieżne z warstwą usług.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MySQL Workbench uzyskuje dostęp do administracji?

  2. Kaskadowe pole kombi formularza dostępu nie pokazuje nic w rozwijanym menu

  3. Jak jeszcze bardziej zoptymalizować tę tabelę MySQL dla pojedynczego zapytania?

  4. Jak naprawić alert Security Advisor MySQL?

  5. usuń wszystkie rekordy z tabeli w mysql