Vrijeme je za promjenu alata koje koristim. I reći ću vam zašto!
Prije svega, želim biti siguran da znate o mojim namjerama. Ne pokušavam raspravljati o Laravelu ili zašto bi drugi okviri mogli biti bolji.
Ovaj je članak vrlo subjektivan. Iznijet ću vam svoja razmišljanja i pokušati vas natjerati da preispitate i svoje okvire. A kad se držite Laravela nakon ponovne procjene, to je u redu. Ne namjeravam ljude preusmjeriti iz Laravela u druge okvire ili jezike. Ali važno je pogledati izbliza i osigurati da znate što koristite i zašto ga koristite.

Uvod
S Laravelom radim otprilike dvije godine. Uvijek sam uživao u tome kako je lako zavrtjeti aplikaciju i krenuti za nekoliko minuta. Pruža toliko korisnih alata iz kutije. Naredbe konzole podržavaju vas u svakom pogledu tijekom kodiranja. Oni generiraju klase, skele za autentifikaciju i još mnogo toga.
No, što dublje idete i što projekti postaju veći, to će razvoj s Laravelom biti kompliciraniji. Ili, dopustite mi da to preformuliram: što će drugi alati bolje obaviti posao. Ne kažem ni da je kriv samo Laravel. Dijelom je to i zbog toga što PHP nije dobro dizajniran.
Sad, krenimo!
Elokventan ORM
Ako ste već surađivali s Laravelom, zasigurno znate za Eloquent. To je ORM koji se isporučuje sa zadanom instalacijom. Dolazi s puno urednih karakteristika. Ali njegov dizajn čini vašu aplikaciju bespotrebno složenom i sprječava IDE da pravilno analizira vaš kôd.
To je djelomično zbog aktivnog uzorka ORM-a koji se koristi, a dijelom zbog činjenice da Eloquent želi spasiti programera od pisanja više koda. Da bi to učinio, programer omogućuje puno toga da uvrsti u model koji tamo ne pripada.
Zvuči kao dobra namjera, ali počeo sam to sve više voljeti.
Pogledajmo primjer:
Prvo što vidite je da na modelu nema svojstava . To se čini nebitno, ali za mene to čini popriličnu razliku. Sve se čarobno ubrizgava u razred čitajući metapodatke tablice. Naravno, vaš IDE to ne razumije bez pomoći. I nemate priliku imenovati svojstva drugačije od stupaca.
Sada pogledajte metodu opsega. Za korisnike Laravela prilično je jasno čime se bavi. Ako pozovete ovu metodu, ona obuhvaća temeljni SQL upit dodavanjem zadane klauzule WHERE.
Vidite, nije statičan. To bi značilo da ova metoda djeluje na određeni objekt klase. Ali u ovom slučaju nema . Opseg se poziva na graditelju upita. To nema nikakve veze sa samim objektom modela. Objasnit ću vam to nakon što vidite kako obično nazivate te opsege:
Zovete statičnu metodu popular()
koju nikad nitko nije definirao. No budući da Laravel definira metodu __call()
i i __callStatic()
, njome se rukuje. Te metode prosljeđuju poziv graditelju upita.
To nije samo nešto što vaš IDE ne razumije. To otežava refaktoriranje, može zbuniti nove programere, a statička analiza postaje teže.
Uz to, stavljajući takve metode na svoj model, kršite S ČVRSTOG. U slučaju da vam to nije poznato, SOLID je kratica koja stoji:
- S ognjište Odgovornost Princip
- O pero / Zatvoreni princip
- L iskovski princip supstitucije
- Ja nterface SEGREGIRANA načelo
- D ependency inverzije Princip
Kada upotrebljavate Eloquent, vaši modeli imaju višestruku odgovornost. Sadrži podatke iz vaše baze podataka, što modeli obično rade, ali u sebi ima i logiku filtriranja, možda sortiranja i još više. Ti to ne želiš.
Globalni pomagači
Laravel dolazi s nekoliko globalnih pomoćnih funkcija. Djeluju vrlo zgodno i da, zgodni su .
Jednostavno morate znati da žrtvujete svoju neovisnost zbog te praktičnosti i vaš se globalni prostor imena zagađuje. Rijetko dovodi do sukoba, ali treba preferirati njihovo potpuno izbjegavanje.
Pogledajmo nekoliko primjera. Evo popisa tri pomoćne metode koje imamo, ali nam ne trebaju, jer postoje bolje alternative:
app_path()
- zašto? Ako vam je potreban put aplikacije, pitajte objekt aplikacije. Dobivate ga nagovještavanjem tipa.app()
- ha? Ova metoda nam nije potrebna. Možemo ubrizgati instancu aplikacije!collect()
- Ovo stvara novu instancu klase Collection. Jednostavno možemo novi objekt postaviti sami.
Još jedan konkretan primjer:
Koristimo Laravelov globalni request()
pomagač za dohvaćanje POST podataka i stavljanje ih u naš model kao atributa.
Umjesto da koristimo globalni pomoćnik, mogli bismo upisati Request
objekt kao parametar u metodi kontrolera. Dispečer u Laravelu zna kako nam pružiti potreban objekt. Pomoću nje će pozvati našu metodu i ne moramo pozivati pomoćnika.
I možemo napraviti ovaj korak dalje kako bismo se još više razdvojili. Laravel je u skladu s PSR-7. Dakle, umjesto da napišete objekt Zahtjev, mogli biste upisati i hint ServerRequestInterface
. To vam omogućuje da cijeli okvir zamijenite bilo čime što je u skladu s PSR-7. Sve u ovoj metodi i dalje će raditi. To ne bi uspjelo ako i dalje koristite pomoćne metode. Novi okvir ne dolazi s pomoćnom metodom i zato ćete morati prepisati taj dio koda.
Rijetko promijenite cijeli okvir, ali postoje ljudi koji to rade. Pa čak i ako se nikad ne prebacite, to je i dalje važno za interoperabilnost. Mogućnost ubrizgavanja ovisnosti i sažet protok podataka umjesto rješavanja i traženja ovisnosti i podataka iznutra je put kojim se ide. Omogućuje testiranje, refaktoriranje i gotovo sve što je lakše kada se savladate.
Bio sam sretan kad sam pročitao da se uz Laravel 5.8 pomoćnici za niz i niz uklanjaju iz jezgre i stavljaju u zaseban paket. Ovo je dobar prvi korak. No, dokumentacija bi trebala početi obeshrabrivati upotrebu svih pomoćnih funkcija.
Fasade
Argumenti iz posljednjeg dijela i ovdje dolaze u obzir. Čini se da su fasade lijep alat za brzi pristup nekim metodama koje zapravo nisu statične. Ali oni vas još jednom vežu u okvir. Koristite ih za ručno rješavanje ovisnosti umjesto da naložite okruženju da ih pruži.
Isto vrijedi i za složenost propuštanjem svega kroz čarobne metode.
Budući da smo razgovarali o IDE podršci, znam da bi me neki od vas mogli uputiti na IDE paket pomoći s barryvdh. Ne trebate. Ovaj paket već znam. Ali zašto je uopće potrebna? Jer neke odluke o dizajnu u Laravelu jednostavno nisu dobre. Postoje okviri u kojima vam to nije potrebno. Uzmimo za primjer Symfony. Nema potrebe za IDE pomoćnim datotekama, jer je dobro dizajnirana i implementirana.
Umjesto fasada, mogli bismo ponovno upotrijebiti injekciju ovisnosti kao što smo to učinili u prethodnom primjeru. Imali bismo stvarni objekt i mogli bismo na njemu pozvati prave metode. Puno bolje.
Još jednom ću vam dati primjer:
To bismo lako mogli očistiti. Recimo Laravelu da ubrizga a ResponseFactory
i proslijedi nam trenutni zahtjev:
Sada smo uspješno eliminirali upotrebu fasada s našeg kontrolera. Kôd i dalje izgleda čisto i kompaktno, ako ne i bolje nego prije. A budući da naši kontroleri uvijek proširuju opću Controller
klasu, mogli bismo učiniti sve korak dalje premještanjem tvornice odgovora u tu roditeljsku klasu. Ionako nam treba u svim ostalim klasama kontrolera.
Čuo sam da neki ljudi daju "previše parametara konstruktora" kao argument protiv ubrizgavanja svega. Ali ne slažem se s tim. U prvom redu skriva samo ovisnosti, a time i složenost. Ako ne volite imati 10 do 20 argumenata u svom konstruktoru, u pravu ste.
Rješenje ipak nije čarolija. Potreba da toliko ovisnosti u jednoj klasi znači da ova klasa najvjerojatnije ima previše odgovornosti. Umjesto da sakrijete tu složenost, prepravite tu klasu. Podijelite ga na nove i poboljšajte arhitekturu aplikacije.
Zabavna činjenica: postoji pravi dizajnerski uzorak nazvan „fasadni uzorak“, predstavljen u knjizi Gang of Four. Ali ima sasvim drugo značenje. Laravelove fasade u osnovi su statički lokatori usluga . Imenovanje to jednostavno ne prenosi. Isto imenovanje različitih stvari također otežava rasprave o arhitekturi u projektima, jer bi druga strana mogla očekivati nešto sasvim drugo iza tog imena.
Zaključak
Dođimo do kraja. Uskoro bih mogao napisati nastavak o tome koje tehnologije danas više volim koristiti. Ali trenutno, dozvolite mi da sažmem ono što smo naučili:
Laravelov pristup da sve bude što lakše moguće je dobar. No, teško je snaći se kad vaše aplikacije postanu naprednije. Više volim strašnu IDE podršku, jače tipkanje, stvarne objekte i dobar inženjering. Možda se vratim u Laravel kada želim napisati manju aplikaciju.
Za puno mojih stavova nije kriv samo Laravel. Mogao bih zamijeniti dijelove koji mi se ne sviđaju, na primjer ORM. Ali umjesto toga, jednostavno ću zamijeniti alat, tamo gdje zadane vrijednosti bolje odgovaraju mojim potrebama. Ne vidim smisla koristiti okvir u kojem moram trošiti više vremena u izbjegavanju zamki koje postavlja zbog lošeg inženjerstva nego u razvoju svoje aplikacije. Ostali okviri i alati dolaze s bolje dizajniranim zadanim postavkama i manje čarolije.
Zato ću se za sada oprostiti od Laravela.
Hvala na vašem vremenu. Bio bih zahvalan na lijepoj raspravi u komentarima i naravno otvoren sam za vaša pitanja i prijedloge.
PS: Posebna hvala Marcu Pivetti na probnom čitanju i dodatnom unosu!
Uredi 1. ožujka 2019 .:
Otkako je moj članak objavljen na Redditu, stvorio sam Reddit račun kako bih odgovorio na nekoliko komentara. Moj račun nije onaj s kojeg je članak objavljen, već ovaj: //reddit.com/u/nschoellhorn
Uredi 13. ožujka 2019 .:
Ako ste pročitali ovoliko daleko, možete pogledati i moj Twitter profil. Zahvaljujemo na vašem daljnjem zanimanju za ovu temu! Uvijek sam otvoren za produktivne rasprave, pa vas slobodno kontaktirajte ovdje ili na Twitteru.