PHP típuskezelés
Sziasztok!
Ugye behozták a szigorú típusosságot PHP7-be, megéri ezt használni?
Már úgy értem, hogy nem fogja a teljesítményt megfogni, vagy távol állni a PHP ideológiájától?
Példaként, mivel PHP ökológiájában ez újnak számít, lehetséges, hogy a későbbi implementáció megváltoztatása nem lesz visszafele kompatibilis - feltételezve, hogy jelenleg csupán !egy! darab típus megadása lehetséges?
(persze ezen kérdések a skalár típusokra értendők)
szerk.:
A PHP által nyújtott névterek hogyan hasznosíthatók a gyakorlatban? Megéri használni?
■ Ugye behozták a szigorú típusosságot PHP7-be, megéri ezt használni?
Már úgy értem, hogy nem fogja a teljesítményt megfogni, vagy távol állni a PHP ideológiájától?
Példaként, mivel PHP ökológiájában ez újnak számít, lehetséges, hogy a későbbi implementáció megváltoztatása nem lesz visszafele kompatibilis - feltételezve, hogy jelenleg csupán !egy! darab típus megadása lehetséges?
(persze ezen kérdések a skalár típusokra értendők)
szerk.:
A PHP által nyújtott névterek hogyan hasznosíthatók a gyakorlatban? Megéri használni?
Szia!Kifejtenéd mit értesz
Kifejtenéd mit értesz ez alatt? Nem teljesen világos
A namespacek használata jó. Sok előnye van, köztük szerintem a legnagyobb - legalább is nekem ezen a ponton a legértékesebb - az az autoload. Nagyban megkönnyíti az osztályok rendszerezése alapján történő automatikus fájlbetöltést. (Pl.: Ha a namespace struktúrád követi a könyvtárstruktúrát, akkor egy egyszerű konvenció alapján megoldhatod az összes PHP osztályod automatikus betöltését)
Előny még, hogy egy ugyanolyan nevű osztályt egy alkalmazáson belül többször is létrehozhatsz és használhatsz egy időben, ha azok külön namespaceben szerepelnek. (Pl.: lehet két Request nevű osztályod is, és használhatod is mindkettőt egy időben, ha külön névtérbe rakod)
A névterek ezen
A másik:
Típusmegadással csupán egyetlen egy skalár, vektor-, vagy objektum-alapú típust adhatunk meg. Mi lenne, ha egy másik típust is meg tudnánk adni?
Eme problémára (így utólag) egyetlen elfogadható választ találtam: a PHP mostantól az objektumorientáltságra fog hajtani. Így elég egyetlen egy, megadott típusú objektumot visszaadni.
Mostmár csak annyi a kérdés, hogy miképpen fog a hibakezelés működni? Milyen módon érdemes megoldani? Kivétel dobásával? Saját "Notice" objektummal? A beépített Error objektummal?
Igazából én a PHP-t most is a
A hibakezelés szerintem az 5-ös PHP-ben is már jól működik, és nincs szükség saját metodológiára. Természetesen egy jó error handler sose rossz, de ezt is már megoldották a keretrendszerek fejlesztői (pl. Symfony), így csak használni kell azokat.
Egy pillanatra visszalépnék még: tudnád szemléltetni néhány sor példakóddal, hogy mire gondolsz? Biztos nálam a hiba, de írtál néhány kerek mondatot, amiből minden szót értek, viszont nem teljesen értem, hogy mire szeretnél kilyukadni.
Igen!
Igen, sokkal fejlettebb
A teljesítmény sokkal jobb, már "gyárilag is" hamarabb "tesz" típust a változódra, mint az 5.x
Nem kötelező megadnod típust, de annyiból hasznos, mert memóriában csak úgy lehet; ha te előre deklarálod, PHP gyorsabban fordítja.
Részben azért sokkal gyorsabb a 7, mert nagyot fejlődött minden típus tárolása terén.
Az ideológia hála Istennek az értelmes programozás felé mozdult el, én nagyon remélem, hogy mondjuk 8.x től kezdve már kötelező is lesz a típus megadása.
Másik újdonság, hogy fv visszatérési érték is lehet előre megadott típusú, ami megint plusz teljesítmény javulás lehet (ha jól használod).
1 vs több típus: a többnek semennyi értelme sincs. Az az érzésem, hogy nem tudod, miért is van egy változónak típusa... Mindig is volt és lesz is, legfeljebb nem látod / láttad.
Nem "hozták be" a szigorú típusosság ot, mert nem kötelező megadnod.
Akkor lesz jó, ha kötelező lesz, mert végre kikerülhet az interpreter ből a rengeteg konverziós eljárás, na akkor sok sebességet kapunk még. :)
Most ez kb fele út, ha adsz típust mindenhol, akkor csak egy egy feltétel, hogy "már van neki", nem kell vizsgálni. De ez jelenleg minden változón és property n végig megy.
Lett pár kényelmi újítás is, pl lehet constant deklaráció expression is.
Arra érdemes figyelni, hogy változó kiértékelés szigorúan csak balról jobbra történik.
$this->$x[y]->valami ()
nem azt jelenti, mint 5.x alatt.A több típus megadására
A nyelvi kiértékelést a fent említett okok miatt nem is használom, egyrészt, mert kevésbé olvasható, másrészt, mert komplexebb kód esetén nincs is szükség hasonló kifejezésekre.
Tobb tipus
+1
Kérdések
Másrészt a kötelező típusok bevezetésével használhatatlanná válna a világ PHP-s kódbázisának 90%-a.
De nem is értem a felvetésed. Ha ennyire hiányoznak a típusok, miért nem programozol inkább mondjuk Go-ban? Hasonló szintaktika, gyorsabb futás, egy csomó érv szól mellette.
szőr szálak...
Más az, ha te tudod, hogy "10" - ed van és neked integer fog kelleni, mint ha a fordító deríti fel, hogy hol lesz felhasználva, ott mi kell majd és most mi.
nem ugyanaz konvertálni; és kideríteni, hogy kell-e és ha igen , akkor mit mire konvertálni és ezután végre hajtani a konverziót. Itt most megint hatalmas túlzásba estél Gábor, és semmi más nem indokolja ezt a hű de kényelmes típus nélküli világot, mint a gyengébb fejlesztők lustasága tanulni...
Egy szóval sem mondtam, hogy le kell majd fejleszteni magadnak, hogy (int) $valami; .
Adatbázis driver ek voltak vannak és lesznek. Ez is a te fixed mindset - ed, hogy mindig is string lesz. Gondolom itt csak a MySQL re gondoltál.
A PHP 7 is kb 90% arányban "kinyírta" az 5.x alatt működő site okat, de távolról sem mondanám, hogy kódbázis 90% - a lenne. Egy eléggé nagynak mondható rendszerrel már migráltunk 7 - re, nagy munka volt, de egyrészt megérte, másrészt a kód max 2% - a változott. Az igaz, hogy ebben az igazán nagy kihívás a "mindent megtalálni" volt - jócskán 1000 feletti class ról beszélek.
Mondjuk Go?
Fenti kódbázist mondjuk most elkezdjük (a full team) le fejleszteni Go ban (v bármi más nyelven), amiben most ugyanolyan tapasztalt mindenki, mint PHP ban (= bulshit), akkor talán jövő karácsonyra kezdhetik tesztelni a tesztelők. Még ha meg is finanszíroznád, akkor sem menne, mert egy évig maga a fejlődés nem állhat meg, az ügyfelek keresnének mást, stb.
A 90% ról még annyit, hogy aki lusta, nem fejlődik tovább, hát tőlem használjon PHP 3 - at akár, csak hát lassan erre saját szervert is kell üzemeltessen. :)
A PHP közösség jelentősen elindult valódi OOP irányba, ezzel együtt jár a típusosság is.
Akkor is, ha lázadsz ellene.
Mi ez?
A mi kódunkat egyáltalán nem kellett a PHP7 miatt módosítani - megéri egyszerű eszközökkel dolgozni.
És ezzel most nem azt akarom mondani, hogy álljatok át Go-ra, hanem arra célzok, hogy mintha sokszor előbb lőnél és utána kérdeznél.
Szerintem a PHP egy nagyon jó nyelv, de megvannak a korlátai, csodákat nem lehet tőle várni. A Go egy jó alternatíva, és a sebesség/memóriakritikus részeknél megéri megéri elgondolkodni a váltáson, ha a rendszer független modulokból áll.
Nalunk sem
+1, nalunk egyetlen egy projekten kellett nagyon kis mertekben modositani es abban regi szemethalmaz kod volt. A tobbi, mar altalunk gyartott projekt (kozotte ~3-5 eves kodbazissal) siman megy PHP 7-en. Igaz, nagyon odafigyeltunk, hogy ne hasznaljunk egzotikus PHP funkcionalitast.
A PHP-t azert nem lehet hanyagolni, mert gyakorlatilag de facto szabvany ha az ugyfel hordozhato weboldalt akar. Esetleg meg Node JS-el lehet kiserletezni, arra van kello mennyisegu tarhely szolgaltato, de a Java, Go kulon erolkodest igenyel uzemeltetesileg.
De ez off topic erosen. :)
Felhő
Szolgaltatasok
Szerver
A node.js-sel pedig a tavalyi menedzsment fiaskó meg az API instabilitása miatt komoly cég nem foglalkozik.
Virtgep
gyakorlat
Nálunk is a módosítás nagy része a balról jobbra szabály és az örökített class fv overwrite paraméterek azonossága miatt volt.
-》 Ez mondjuk egy szükséges kód minőségi javulás is, egyáltalán nem baj.
Külső modulok: ha nem fejlesztik eléggé, keresünk mást vagy fejlesztjük mi.
de többnyire fejlesztik, nincs mindenki a fejlődés ellen. :)
PHP 5-ről PHP 7-re váltva a
A type hinting pedig így működik, idézet a dokumentációból:
Ez egy csomó újabb kérdést felvet, például, hogy tulajdonképpen mit nyertetek ezekkel az egzotikus funkciókkal? Mert azt látjuk, hogy mit vesztettetek. Hogy lehet, hogy ezek nélkül is készíthetőek működő szolgáltatások? Valóban fejlődés ezeknek a használata? Mi lesz, ha a 8.0-ban hasonlóan sok meló lesz az egzotikumok átírása?
Ha a főnökötök lennék, én bizony feltenném a gárdának ezeket a kérdéseket.
látja :)
Ha nem, akkor alkalmas időben meg fogom mutatni neki.
Egzotikumok:
Ahol sok fejlesztő és "fejlesztő" (<- idéző jel!) meg fordul, ott sokminden kerülhet a kódba.
És a példámnál maradva 5.x alatt semmi gondot nem okozott, ha volt egy parent
function valami ($x)
és egy child fv valami ($x, $y) .Annyi, hogy 7.x ezt már nem preferálja. Vagyis terel a valódi OOP felé.
Nyugodtan szidd a rendszerünket, egyelőre regionálisan a legjobbak vagyunk, és ezt a pozíciót meg is tartjuk, 8.x alatt is. :)
Így utólag vissza nézek és azt látom, hogy a 7-re állás is leginkább azért volt nagy munka, mert még nem volt sok tapasztalatunk a verzióban. (Hozzá teszem, hogy bár "utólag könnyű okosnak lenni", le vonva az 5.x -》7.x tanulságait, a 8.x - re váltásban mindenképp nagy szerepet akarok vállalni.)
Maga az átállás hozta a szükséges tapasztalatot.
Tanulság: megijedni nem kell, helyette alapos (kézi is!) tesztelés kell élesítés előtt.
Nem bántásnak szánom: hála Istennek nem te vagy a főnököm. :)
Ne értsd félre: jórészt hasznosnak tartom itt a kérdéseid / aggodalmad, tanulok is belőle / miatta, annyi az egész, hogy van amikor gyors és csak "valamennyire" működő megoldás kell, és van amikor szigorúan tartani kell az elveket, és javítani, ami eltér tőlük.
Szerencsére a főnököm ezeket nagyon jól látja.
Nem értelek
A lényegi kérdések megválaszolását látványosan kerülöd.
Példa
print $haha;
}
hehe(12); //12
hehe('123'); //123
hehe('a123'); //Fatal error: Uncaught TypeError: Argument 1 passed to hehe() must be of the type integer, string given
function hehe2(int $haha) {
$haha = 'asd';
print $haha;
}
hehe2(123); //asd
Hogy ettől nem fog gyorsabban futni a kódotok, az száz százalék.
gyakorlati példa
(és tippre még gyorsabb is)
Helyes tipp
Erre próbáltam rá világítani fentebb is.
Nem értelek
típusos: 0.81011414527893
típus nélküli: 0.75525093078613
Intel Atom 1,3GHz, Windows, PHP 7.0.2
nézz eggyel fentebb :)
Látom, hogy nem foglak meg győzni, ha gondolod, használj PHP -8.x - et is tőlem, nyilván a régi a jobb, utáljuk és félünk a változástól. :)
Csak zárójelben: a rand () fv futásideje önmagában eléggé random, te pedig 2x hívod, míg a tesztelt fvt 1x...
De ez végül is mindegy, úgyis találsz másik "jó" példát; engem már meggyőzött a saját (éles) tapasztalatom: azok a class ok (és fv ei ) is gyorsabban futnak, amikhez nem is nyúltunk.
Ehhez képest bocsi, de nem eléggé meggyőző az, hogy te egyedül mást állítasz.
Egy 20 soros példa áll szemben sacra jóval több, mint 200 ezer sorral...
De egy irányba fel keltetted a figyelmem: én is fogom tesztelni kizárólag az átadott paramétert is. (rand nélkül)
Lehet, hogy jelenleg csak akkor hasznos, ha a visszaadott érték is típusos. (Mondjuk igazi értelme akkor van.)
Mikro
Nem
Hibakezeles
Nem értem
Type hint
Azert csinalunk type hintet, hogy hibat kezeljunk es aktivan dokumentaljuk, hogy mit varunk.
Ez a ket megvalositas funkcionalitasat tekintve ekvivalens:
Hibakezelés
Két eset lehetséges:
1, A teljes kontroll a te kezedben van, azaz a kódot te írtad, ekkor nincs miért aggódni. Ilyenkor akár az egészet megírhatod strict_types=1-gyel.
2, Ha a programkódod egy rutinkönyvtár része, akkor kívülről fogják meghívni, azaz nem tudod biztosan, mit fogsz kapni.
Ez utóbbi eset az érdekes, és itt is van válaszlehetőséged. A függvénynek mindenképp karakterlánccal kell dolgoznia, ezt garantálni kell, s erre két lehetőség van:
a, A hívóra bízod a konverziót, a függvény paraméterében type hintet használsz. Ekkor a függvényed minden meghívása előtt le kell futnia az ellenőrző és konverziós kódnak, amit a fenti négy példa közül a másodikban láthatunk. Ebben az esetben használhatsz type hintinget.
b, A szükséges ellenőrzést és konverziót magában a függvényben végzed el. Ilyenkor nincs "szóismétlés", és a programod csak akkor fog hibát dobni, ha a bejövő paraméter biztosan nem felel meg a követelményeknek.
---
Szólj, ha valamit félreértek vagy nem gondoltam át teljesen.
A helyzetet bonyolíthatja, hogy a strict_types csak a felhasználói függvényekre vonatkozik, a PHP beépített funkcióira nem, azaz a típusellenőrzéseket és konverziókat nem biztos, hogy megúszod.
Innentől kezdve számomra kérdéses a type hinting értelme és haszna, hisz ha a példafüggvényed meghívása előtt mindenképp kell ellenőrzést és opcionális konverziót végezni, akkor a type hinting egyrészt fölösleges, másrészt biztosan lassítja a futást.
Az 1-es pont - nem kell
A 2-esnél a b-t mitől gondolod opciónak? Az ellenőrzés, konverzió csak zaj a kódban, és minden hívásnál a te kódodnak kell csinálja. Olvashatóbb biztos nem lesz a kódod, és erősen kétlem, hogy hatékonyabb, mintha a futtatókörnyezet funkcionalitását használnád. És nem utolsósorban a bármit lemappelünk az elvárt típusra... Mégis hogy? :) Mi van, ha egy összetett típus jön? Azt mindig a hívónak kell garantálja, hogy a megfelelő típusú és tartalmú paramétert adja át, hisz nála van meg az a kontextuális információ, hogy mit jelent a nála lévő adat, és hogyan van reprezentálva. Jöhet hívás nem megbízható forrásból, ekkor lehet érdemes boundary checkeket csinálni, ami futás idejű hibát kell okozzon, ha nem megfelelő a paraméter.
Az 1-es pont - nem kell
A másik esetben azt írtam le, hogy nem tudod megspórolni az esetleges típusellenőrzést és konverziót, például azért, mert a PHP beépített függvényei is mind gyengén típusosak, legalábbis a PHP wikiben ezt írják. Innentől kezdve valakinek el kell végeznie az ellenőrzéseket, és az már ízlés kérdése, hogy szétszórva a kódban (2/a) vagy egy helyen (2/b) valósítod meg.
Cégen belül a megfelelő
Fajlonkent
Tegyuk fel, hogy en egy intet varok, de pl. stringet kapok. Mi fog tortenni?
1. Ha a string elejen van egy szam, akkor a tobbit a PHP eldobja az elso intre castolasnal, a szamot megtartja. Ez valtozatos es erdekes bugokhoz vezethet, ha pl. a tizedespont helyett tizedesvesszo jott a stringben, akkor a
'123,456'
-bol123
. Egyertelmuen hibas a bemenet, egyertelmuen hibas mukodeshez fog vezetni, de a kod megis tovabb fut.2. Ha a a string elejen nem szam van, az int 0-ra konvertalodik. Meg rosszabb.
Vagyis a problema abbol adodik, hogy a programod nem vart es hibas bemenetre is latszolag helyes kimenetet ad, ami adott esetben adatveszteshez vezet es akar csak evekkel kesobb derul ki.
Lassuk be, ez 100%-ban a PHP hulyesege, mert egy nem tiszta szamot tartalmazo stringre csendben elvegezni a tipuskonverziot boduletes baromsag. Egy normalisan megcsinalt duct typing nyelvvel ez nem lenne AKKORA problem, mert legalabb hibat kapnal.
Viszont: en eleg fegyelmezett fejlesztonek gondolom magam, de ennek ellenere elofordul, hogy nem figyelek oda es a tesztek ellenere sikerul atadnom egy olyan adatot amit nem akartam. Ilyen esetekben a Hacklang compile-time typecheckere a nyakamba vagja hogy hulye vagyok. Es minden egyes esetben igaza van, nem ugy akartam osszekotni azokat a reszeket ahogy gondoltam. Minden. Egyes. Esetben. Sokkal jobb, ha mar a compiler ram tud szolni hogy hulye vagyok mint amikor runtime, sok teszteles aran veszem eszre hogy nem azt adtam at amit akartam. Vagy nem tesztelem elegge es production kornyezetben derul ki.
Raadasul egy normalis szerkezetu programban minimalis mennyisegu tipuskonverzio van, tobbnyire ott ahol mas rendszerekkel erintkezik, ott pedig ugyis le kell ellenorizni hogy megis mi a fenet kapsz.
strict
test.php:3:9,20: Invalid lvalue (Parsing[1002])
Megmutatom akkor, hogy mire
Tetszőleges hibakezelő rutinokat beépítve az OPResult lenne a programunk logolásáért felelős alrendszer felülete, amelynek felületét csupán a belső mechanizmusoknak kellene ismernie.
Ti milyen szempontok alapján építenétek fel egy ilyen rendszert? A fentebb vázolt megoldás megfelelne az elvárásoknak?
Alahuzas
A define-okat szinten kerulnem, helyette osztalyok konstansait hasznalnam.
Aláhúzás helyett
Pl camelCase
Meg egy dolog
Irtam erre egy kiserletet, lehet hogy erdemes belole inspiraciot meriteni.
"mindegyik latvanyosan rossz. "
_szerintem_ azért, mert sokan esnek abba a hibába, hogy "ha már query builder, akkor tudjon már ... is" ...
Vagyis túlságosan el ragaszkodik az adott feladat scope jától.
(Mert hirtelen fel akarja találni a kereket.)
Mert folosleges
Edit: az is lehet, hogy ezek az emberek buta szerkesztot hasznalnak ami nem kepes szolni ha hibas az SQL kod es igy a query buildertol remelik a hibamentes SQL kodot. Ha hasznalnanak tisztesseges IDE-t, ez mind nem lenne problema.
Kérdések
1, A típusosságot igazából csak a Limitnél és az Offsetnél tudod kihasználni, de igazából ott sem értem, mire jó. Ugyanis mi van, ha ezeket az értékeket adatbázisból veszed, aminek a visszatérési típusa karakterlánc, azaz valahol a programban mindenképp kell típuskonverziót végezni. Ezt az opcionális átváltást miért nem ezekben a metódusokban végzed el?
2, Mi a célod ezzel a megvalósítással? A típusoknak akkor lenne értelme, ha adatbázismezőnként meg lehetne adni egy SELECT-ben, hogy ide egész számokat várok, ide dátumot, amoda meg karakterláncot. Ennek hiányában legfeljebb arra jó az egész, hogy össze tudod legózni a lekérdezéseket.
De ez újabb kérdéseket vet fel:
a, A témában n féle ilyen illesztőt írtak már, miért írsz sajátot? Gyakorolnál? Arra mondjuk épp jó.
b, Ezzel az eszközkészlettel csak rendkívül primitív lekérdezéseket tudsz összeszerelni – akkor tulajdonképpen mire jó az egész? Ráadásul jóval lassabb lesz, mintha te ragasztgatnád össze a lekérdezéseket vagy prepared statementeket használnál.
3, Miért OOP ez az egész? Mivel az általánosan használt MySQL-től mindegyik más adatbáziskezelő jelentősen eltér, nagyon nehéz olyan PHP kódot és SQL-t írni, ami mondjuk postgresql esetében is jól fog működni.
Ha ez így van, akkor nem látom értelmét ennek az absztrakciónak, bőven elég az, amit mondjuk a PDO nyújt.
A lekérdezések eredményeinél miért van szükség a visszafele léptetésre (
fetchPreviousRow
)? Miért nem kérsz le egyben minden sort, beteszed egy tömbbe, és kész, azon már lehet egyfor
ciklussal végigiterálni? A hibakezelés ettől még maradhat a lekérdezést végző függvényben, de ha már kaptál tőle visszatérési értéket, biztos lehetsz benne, hogy az hibátlan.A
Database
és aDatabaseInteractions
miért két külön interfész?Csak 3.:
- Ilyen "kis gagyi" CMS, mint a Drupal, többször is meg lépte, nem csak(!) az általad megadott 2 motorral. :)
- Mindent egy tömbbe: 100 000 000 rekord környékén már kissé meredek gondolat; vagy te mindig veszel nagyobb vasat, ha béna a kódod és lassú?
Egyébként - ha erre gondoltál - abban egyetértek, hogy nem lehet és nem kell olyan db interfészt írni, ami "mindenre jó".
Re
Úgy látom, hogy ez ezen a terepen van még mit fejlődnöm..
Static