Jeśli masz logikę, która musi być współużytkowana przez dwa kontrolery, gdzie ją trzymasz?

10

Mam zestaw funkcji jednego celu, których potrzebuję w dwóch osobnych kontrolerach. W tej chwili mam tylko zduplikowany kod i chcę się go pozbyć. Ten kod jest częścią kontrolera i nie należy do mojej warstwy usług. Gdzie byś to położył?

Erin
źródło
CakePHP nazywa je Komponentami: book.cakephp.org/2.0/en/controllers/components.html może to trochę inspiracja.
Luc Franken

Odpowiedzi:

12

Nie powiedziałeś, jaką logikę udostępniasz. Krótko mówiąc, czy ta logika kontrolera czy funkcja pomocnika? Dwie metody radzenia sobie z tym w języku obiektowym to dziedziczenie i kompozycja. Dziedziczenie ma sens, jeśli między dwoma kontrolerami jest akcja wspólna. Kompozycja ma sens przez resztę czasu. Przykład zastosowania dziedziczenia znajduje się w mojej oryginalnej odpowiedzi poniżej dzielnika.

Często zdarza się, że klasa użyteczności lub klasa pomocnicza jest zależna od twojego frameworka. Na przykład w strukturach sieciowych Java i C # możesz mieć pakiet / przestrzeń nazw dla narzędzi. W Ruby on Rails możesz korzystać z Helperklasy dzielącej logikę między kontrolerami i widokami. Zasadniczo wyglądałoby to tak:

// NOTE: group similar functions
static class LoginUtility
{
    static bool IsLoggedIn(Request request) { /* ... */ }
}

Alternatywnie możesz uczynić z niej klasę, którą tworzysz. Kluczem do powyższego wzorca klasy statycznej jest uczynienie funkcji czystymi funkcjami. Innymi słowy, przekazujesz w dowolnym stanie, który musi wykonać, a funkcja nie odwołuje się do żadnego innego stanu statycznego w systemie.

W obu przypadkach uzyskasz dostęp do każdego z kontrolerów w następujący sposób:

void MyAction()
{
    if (LoginUtiltiy.IsLoggedIn(Request))
    {
        // Do something ...
    }
}

Oryginalna odpowiedź

Nie powiedziałeś, jaka była Twoja platforma, ponieważ może to wpłynąć na odpowiedź. Zakładając , że jest to język zorientowany obiektowo, najczęstszym podejściem jest utworzenie klasy podstawowej, którą rozszerzają oba kontrolery. Na przykład w Ruby on Rails możesz mieć:

class BaseController < ApplicationController
    def my_special_function
        # ...
    end
end

class Controller1 < BaseController
    # ...
end

class Controller2 < BaseController
    # ...
end

Możesz przetłumaczyć ten pomysł na inne języki. To samo podejście będzie działać w przypadku ASP.NET MVC, Apache Wicket, Grails lub niemal każdej innej zorientowanej obiektowo struktury sieciowej. Jeśli twój język nie jest zorientowany obiektowo, to tak naprawdę zależy to od tego, w jaki sposób zaprojektowano framework, aby uzyskać najlepsze podejście.

Berin Loritsch
źródło
3
Alternatywą jest umieszczenie logiki w osobnej klasie, a następnie utworzenie instancji tej klasy i wywołanie logiki z obu kontrolerów.
Kramii
5
Tak, zawsze wolę kompozycję niż dziedziczenie
Reno
1
Wykonaj sugestię Kramii zamiast dodawać dodatkową warstwę dziedzictwa. Ale myślę, że jego prawdziwe pytanie brzmiało, gdzie w rozwiązaniu idzie ta klasa.
Nikt
1
Zależy to od funkcji i struktury. W szynach może należeć do klasy Helper. W programie ASP.NET lub Java może istnieć klasa narzędzi dla tego typu funkcji. To naprawdę zależy od tego, jak blisko kontrolera musi żyć.
Berin Loritsch
To logika kontrolera. Po prostu potrzebuję go w dwóch miejscach. Teraz mam klasę rozszerzeń, której używam do umieszczenia logiki w jednym miejscu.
Erin