Refaktoryzacja statycznych klas

0

Cześć
Wątek nadaje się w sumie również do architektury softu, ale tutaj akurat konkretnie z php.
Ostatnio w kodzie pojawia mi się coraz więcej klas statycznych, czyli klas, które mają raczej same metody statyczne i ewentualnie właściwości statyczne. Na przykład taka klasa do autentyfikacji userów (pisane na miejscu poglądowo):

class UserAuth
{
    public static function getUser($login, $password){
        //tutaj następuje zapytanie do bazy danych, jeżeli user istnieje zwracany jest jego model (właściwie sama prosta struktura, która zawiera pola tego usera z kolumn z tablicy)
        //jeżeli user istnieje, to zwracany jest jego model, inaczej zwracany jest null lub false
    }
    public static function isLogged(){
        //jeżeli model usera jest zapisany w sesji, to zwracany jest on, inaczej zwracane jest null lub false
    }
    public static function logOut(){
        //jeżeli user jest w sesji, jest kasowany z sesji, jeżeli go tam nie było to rzucać tutaj jakiś wyjątek?
    }
    public static function logIn($userModel){
        //model usera jest zapisywany w sesji, ewentualnie można go zredukować tylko do klucza z tablicy z db i w razie czego zapytywać db o pełniejszy model tego usera
    }
}

Jak widać same metody do autentyfikacji userów w statycznej klasie pogrupowane, zasadniczo to mógłby być namespace, niekoniecznie class.
Teraz, co zrobić z taką klasą, gdyż chyba nie jest to zbyt pięknie wykonane?
Można by użyć singletona i te metody byłyby na obiekcie, ale obiekt byłby de facto globalny, czyli praktycznie to samo (ale potem łatwiej zrobić refaktoryzację, czy też dodać jakieś cache'owanie).
Można zrobić to w zwykłym obiekcie, ale wtedy byłby tworzony obiekt tylko po to, by w zasadzie wywołać funkcję, czyli rolą tego obiektu byłoby tylko grupowanie metod, co również spełnia klasa statyczna.
Czy takie coś załatwiłby DI container, jakieś fabryki (czyli w sumie jakiś podzbiór DIC), czy może coś jeszcze innego? Co byście polecali tutaj zrobić z takim kodem?
Zasadniczo przykład odnosi się do php i klasy do logowania userów, ale jest więcej takich klas, które są naklepywane statycznie z różnych powodów, chociażby złożoności incjalizacji nowych obiektów (tutaj DIC to akurat typowe use-case, co nie?), a i sam język nie musi być php, może być czymś innym.

0

W zasadzie Laravel korzysta z Auth facade i jest to dokładnie statyczna klasa. Jest też jakiś middleware do tego, ale middleware niekoniecznie będzie pasował do innych klas statycznych.
Z drugiej strony takie pogrupowane metody to czyste programowanie funkcyjne, nie zmieniają one żadnego stanu z zewnątrz (jeżeliby podawać tablicę sesji jako argument), czyli chyba nie jest to takie brzydkie?
@Desu możesz podać linki do konkretnych plików laravela z githuba, gdzie to auth siedzi? Jak na razie patrzyłem to jest ta fasada od autentyfikacji i middleware.
Czy DIC byłby tutaj do zastosowania? W ten sposób złożoność tworzenia nowego obiektu jest oddelegowana do jakichś configów i przynajmniej wystarczyłoby zapytywać DIC o obiekt klasy auth.

0

Jak zauważyłeś Auth to tylko fasada, która korzysta z https://github.com/laravel/framework/blob/5.1/src/Illuminate/Auth/Guard.php

0

Tylko po co te metody statyczne? To ma raczej pewne znaczenie praktyczne a co do praktycznej realizacji to lepiej przejrzyj to:

https://kohanaframework.org/3.2/guide/api/Auth
https://kohanaframework.org/3.2/guide/api/Auth_ORM
https://kohanaframework.org/3.2/guide/api/Auth_File

Co tylko pokazuje, że Auth może być nie tylko typu ORM (zauważ że jest jeszcze możliwość logowania i sprawdzania ról a przy wylogowaniu jeszcze opcja niszczenia sesji albo i nie i wylogowania wszystkich użytkowników przy opcji zapamiętaj mnie) ale również i Filebased, gdzie login i hasło jest brane z danych wpisanych na stałe w pliku konfiguracyjnym.

Laravel to po prostu inne podejście, podaję przykłady z KO3 bo są o wiele prostsze do zrozumienia, tam masz wszystko jak na dłoni co się dzieje w kodzie.

0

Moim zdaniem to ta klasa łamie SRP, metoda getUser() ma inny kontekst niż pozostałe.

Na szybko myśląc, to widzę tu dwie klasy - UserService (z metodą getUserByUsernameAndPassword) i AuthService (z pozostałymi metodami). Metody AuthService mogą na przykład przyjmować obiekt Usera. Nie bawiłbym się w metody statyczne czy singletony, tylko wszystko instancyjne plus - tak jak napisałeś - kontener DI i cześć. Może się wtedy to nawet da przetestować :P.

0

Również nie rozumiem. Po co taki podział? W sensie czy w praktyce takie coś a właściwie do przesady przestrzeganie tych zasad mogło by w czymś przeszkadzać (wiadomo coś kosztem czegoś). Ale dalej. Przeglądam te kody Laravela, w szczególności AuthManager, AuthServiceProvider, Guard i mam takie nieodparte wrażenie, że w ogólnym zarysie że realizowane są podobne rzeczy co w Kohanie, tylko inaczej (bardziej nowocześnie) rozwiązane.
W obu przypadkach chodzi o przetrzymywanie całego użytkownika pobranego wcześniej z bazy w sesji, na tej podstawie później sprawdzanie czy jest zalogowany czy nie. Obawiam się że bez gruntownej znajomości Laravela się nie obejdzie, jeśli już chodzi np. o middleware.

0

Dorzucę swoją łapkę do rozwiązania z kontenerem DI i obiektami odpowiednich klas (usługami). Wydaje się, ze to jest właśnie ta strona, w którą zmierza obecnie świat.

[Adam]

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