Php, statikus változók az osztályon belül módszerek és a történelem egy bug
Általában én frontend fejlesztő. De néha meg kell dolgozni a szerverrel. Csapatunk kicsi, és ha minden a valódi back-end programozók elfoglalt gyorsabb, hogy végre néhány módszer is. És néha leülünk együtt dolgozni a problémákat, nem vesztegeti az idejét a színpadon vállalják, hogy ide-oda. Nemrégiben egy év alatt a fordulóban pár programozás mi csapattársa összeütközött egy hiba, ami annyira lenyűgözte, hogy úgy döntöttem, hogy megosztom veletek.
Tehát, amikor vacsora után mentem kollégája római parpalak. éppen befejezte tenni annak érdekében, hogy a unit tesztek, és futott az egész csomagot. Az egyik teszt dobott kivételt, és elesett. Igen, úgy gondoltuk, most kijavítani a hibát. Futunk a teszt önmagában kívül a csomag, és sikeres volt.
Mielőtt dobja ki a délutáni nap, elindítottuk Codeception még néhány alkalommal. A vizsgálati csomag esett, nemhogy telt el, a csomag esett ...
Mi bemászott a kódot.
Fatalka felhívás a saját módszer kirepült egy módszert, amely átalakítja a lényege egy tárgy egy tömbben küldeni az ügyfélnek. Nemrégiben mechanizmusa ez a folyamat változott egy kicsit, de nem minden osztály refactor, így a módszer érdemes megnézni, hogy a felülírt módszert ad egy listát a szükséges mezőket (ez a régi módon) a származtatott osztály. Ha nem, akkor a lista mezővel keresztül reflexió (ez egy új út), és felszólítja a megfelelő getter. Esetünkben az egyik getter nyilvánították mint a magán-, és ennek megfelelően, nem érhető el a bázis osztály. Mindez így néz ki:
Egy kis kódot egyszerűsített összpontosítani a lényeg
Mint látható, az eredmény a reflektor tárolódik el egy statikus változó $ isClientPropsOriginal belül a módszer.
- És mi, visszaverődés olyan nehéz művelet? - kérdeztem.
- Nos, - római bólintott.
Töréspont a sorban a tükörképe nem működik egyáltalán ebben az osztályban. Nem egyszer. Statikus változó már be van állítva, hogy igaz. tolmács bemászott toClientModelNew eljárás és elesett. Felajánlottam, hogy hol folyik hozzárendelés:
A változó $ isClientPropsOriginal állt "PaymentList". Ez egy másik osztályban, amit AbstractEntity. Figyelemre méltó, hogy pontosan két dolgot: ez nem írja felül az eljárás getClientProperties és ő tesztelte a unit tesztek, amelyek már sikeresen dolgoztak egy kicsit korábban.
- Hogy lehet ez? - kérdeztem. - Statikus változó belsejében egy módszert beletúrt öröklés? Akkor miért vagyunk nem vette észre?
Roman volt zavarodva, mint én. Miközben mentem a kávét, húzott egy kis egység teszt utánzata a mi osztály hierarchia, de nem esett el. Van valami figyelmen kívül hagyni. Statikus változó viselkedett megfelelően, nem vártunk, de nem minden esetben, és nem tudtunk rájönni, hogy miért. Gugleniya kérésre „php statikus változó belső osztály módszer” nem adta semmi hasznosat, kivéve, hogy a statikus változók - ez nem jó. Nos, duh!
Most római kiment a kávé, és azt hittem, a PHP-kinyitotta a homokozóban, és írjon a legegyszerűbb kód:
Valami ehhez hasonló működnie kell. Az elv a legkevésbé megdöbbenésére minden esetben. De van valójában egy statikus változó belül meghatározott toClientModel módszer. és ez újra a gyermek osztályban. Mi lenne, ha mi írjuk, mint:
„Milyen különös”, gondoltam. De néhány logika az. A második esetben, az eljárás tartalmazza egy statikus változó, úgynevezett keresztül szülő. Hozamok felhasználva például a szülő osztály? És hogyan lehet kijutni ebből a helyzetből? Azt megvakarta a fejét és kissé kiegészítve a példáját:
Ez az! Roman éppen visszatért, és meg volt elégedve magával, bemutassák eredményeiket. Beletelt csak néhány csapok a billentyűzeten PHPStorm, hogy refactor a szakaszt egy statikus változó egy külön eljárás:
De ott volt! A hiba tartottuk. Közelebbről megnézve, észrevettem, hogy hasOriginalClientProps módszert nyilvánították magán. az én például nem volt nyilvános. Egy gyors ellenőrzés azt mutatta, hogy a védett mű, és az állami. magán és nem fog működni.
Idő szorította, és tovább haladt a további kihívások, de ez a viselkedés rejtélyes. Úgy döntöttem, hogy megtudja, miért viselkedik így a PHP. A dokumentáció nem tudott ásni semmit, de homályos célzásokat. Az alábbiakban megpróbálom rekonstruálni egy képet, hogy mi történik, amely a figyelmes olvasás PHP Internals könyv. PHP Wiki. tanulmány a források és információk objektumok hogyan hajtják végre a más programozási nyelvek.
A funkció van a tolmács leírt belül PHP szerkezet op_array. amely többek között tartalmazza a hash tábla statikus változókat a funkciót. Amikor örökli. ha nincs statikus változók, függvények pereispolzuetsya a származtatott osztály, és ha van - elkészíti annak másolatát, hogy a gyermek osztály a módszert kellett statikus változókat.
Eddig jó, de ha meghívjuk a szülő módszer segítségével parent :: printCount (). Aztán persze, mi esik a szülő osztály módszer, amely együttműködik a statikus változókat. Ezért a 2. példa nem működik, és az 1. példa - működik. És amikor már megtanult egy statikus változó egy külön eljárás, mint a 3. példában, már megmentette a késői kötés: A módszer :: printCount is okozhat egy példányt a módszer :: doPrintCount B. osztályú (ami természetesen megegyezik az eredeti A :: doPrintCount).
Ez a viselkedés megismétlődik minden PHP változat, megpróbáltam a homokozóban. kezdve egy bozontos 5.0.4.
Miért van az, egy hiba a kód projektünk előtt nem érezhetők? Úgy tűnik, a természet ritkán létrehozott heterogén csoportokban, és ha ők hozták létre - majd refactor őket egyszerre. De amikor a tesztek futtatását egy menetben a szkript két tárgy, munka különböző mechanizmusok révén, és az egyikük elrontotta a másik államban.
(Mivel minden cikket komolyan kell következtetéseket)
- A statikus változók - rossz.
Nos, ez olyan, mint bármely más gonosz programozás, ezek gondos és megfontolt megközelítést. Persze, akkor kritizálni minket a lappangó állapotban, de ez egy ügyes alkalmazás lehetővé teszi, hogy írjon nagyon hatékony kódot. Azonban a static'ami lehet lappangó buktatókat, amelyek közül az egyik amit mutattam. ezért
Senki sem tudja garantálni, hogy a rejtett sekély a kódban nem jön ki a fényre után újratervezés. Tehát írjuk teszt kód és fedezi a vizsgálatok. Ha egy ilyen hiba által leírt nekem eredetileg a harci kód helyett a teszteket hibakereső könnyen megtesznek minden nap, ahelyett, másfél-két óra.
- Ne félj, hogy a dzsungelbe.
Még egy ilyen egyszerű dolog, mint egy statikus változót, adhat okot, hogy mély merülést a dokumentációs rendszer és a PHP forráskód. És még ért valamit bennük.
Ui Köszönjük Romana parpalak értékes tanácsokat a készítmény az anyag.