Door
Ozzie PHP
op 03-01-2014 23:46
gewijzigd op 03-01-2014 23:48
2.172 views
Ola,
Nog weer even een leuke...
Stel we hebben een of andere (algemene) copy functie. Als deze false teruggeeft (het kopiëren is mislukt) wil ik een exception gooien. Weer even uit nieuwsgierigheid. Heeft voorbeeld A of voorbeeld B jullie voorkeur?
A:
<?php
if (!copy('foo.php', 'bar.php')) {
throw new Exception('could not make copy bla bla bla...');
}
?>
B:
<?php
if (copy('foo.php', 'bar.php')) {
return;
}
throw new Exception('could not make copy bla bla bla...');
?>
In voorbeeld A zeg ik "als het kopiëren is mislukt gooi dan een exception. In voorbeeld B zeg ik "als het kopiëren is GELUKT verlaat dan de functie. Als het kopiëren dan mislukt dan wordt er niet gereturned en wordt alsnog de exception gegooid. Twee verschillende benaderingswijzen. Methode A voelt denk ik het meest intuïtief en prettig, maar methode B is weer ietsje sneller. Ik weet dat veel mensen voor methode A zouden kiezen, maar ik ben benieuwd of hier ook programmeurs zijn die juist vaker een oplossing a la methode B gebruiken. Van de 2 is methode B dus ietsje sneller (omdat er een positieve vergelijking plaatsvindt in plaats van een negatieve vergelijking zoals bij A). Wat heeft jullie voorkeur?
tja,
dan kun je ook wel zeggen dat
substr('abc', 0,1);
volgens de documentatie 'a' terug zou moeten geven, maar dat dat niet met zekerheid te zeggen is.
En dat kun je wel testen, maar wie zegt dan weer dat dat niet van het tijdstip, de maanstand en de koers van de AEX afhankelijk is.....
Waar ik het hier over heb is het verschil tussen code level en documentatie level. Op code level kunnen we in PHP nooit aannemen dat copy altijd een boolean teruggeeft. Alleen op documentatie level kunnen we aannemen dat copy een boolean teruggeeft en dat nemen we dus ook aan, aangezien we dat gewent zijn in PHP.
Als we bijv. naar Haskell kijken kunnen we op code level zeker weten dat copyFile een IO teruggeeft. Het documentatie level bevestigt dit alleen maar.
Als je nog wat dieper in internals wilt gaan: PHP is gemaakt in C, een taal die strict typed is. Om een lazy typed language in een script typed language te maken heeft PHP een custom C type gemaakt: zval
struct _zval_struct {
/* Variable information */
zvalue_value value; /* value */
zend_uint refcount__gc;
zend_uchar type; /* active type */
zend_uchar is_ref__gc;
};
Dit _zval_struct type bevat meerdere properties, 1 daarvan is de value die de value van het type vasthoudt en 1 daarvan is type, die houdt het type van de value vast.
Die value is ook weer een type:
typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
struct {
char *val;
int len;
} str;
HashTable *ht; /* hash table value */
zend_object_value obj;
} zvalue_value;
Hier wordt een zvalue_value type gemaakt die een union is, dat betekend dat het een verzameling van types is. Wat voor verzameling dit is staat beschreven in het stuk tussen accolades.
De verzameling bestaat dus uit: long (integers), double (floats), struct { char *val; int len; } (string + string lengte), HashTable (array) en zend_object_value (PHP object type).
Wanneer een functie dus een zval type terug geeft kan die al deze bovenstaande types zijn. Welk type het momenteel is wordt opgeslagen in de type property. Maar dat kan zo veranderd worden door convert_to_* functies. Wat type er in zval zit is dus compleet dynamisch.
Hierdoor kunnen we nooit zeggen welk type een functie teruggeeft als hij een zval type teruggeeft. En hierdoor kunnen we dus ook in PHP code nooit een functie limiteren tot het teruggeven van een bepaalde PHP type, aangezien alle PHP types in totaal 1 type is.
Fijn dat het op de achtergrond op die manier gaat, maar als de documentatie zegt dat er een bool terug komt om aan te geven dat copy() gelukt is of niet,
dan lijkt me dat voldoende zekerheid om daar vanuit te gaan.
Mogelijk dat in een uitzonderlijke situatie die functie plotseling een andere value zou kunnen teruggeven, maar dat is dan een bug.
Maar om nu elke functie in twijfel te trekken tijdens het coden in PHP, gaat mij in elk geval te ver.
Het is al erg genoeg dan
NULL, FALSE, 0 en "" allemaal gelijk zijn als je met == vergelijkt.
Wouter, ik ben het met Ivo eens. Als je de documentatie niet meer kunt vertrouwen dan kun je toch net zo goed gelijk stoppen met programmeren?
Als de documentatie zegt dat functie foo een boolean teruggeeft, dan is het toch onzinnig om vervolgens nog eens te gaan controleren of de documentatie het wel bij het rechte eind heeft? Hoe het er achter de schermen ook aan toe gaat, je moet kunnen vertrouwen op de documentatie, of beter gezegd de handleiding. Het lijkt me juist dat je nogal paranoia bent als je zelfs de handleiding niet vertrouwt. Dan kun je alles wel gaan controleren. Dan kun je zelfs als je 2 integers bij elkaar optelt ook nog eens gaan controleren of de uitkomst wel een integer is. Nee, dat lijkt me niet de juiste weg.
Ivo, het is ook niet iets waar je je als PHP developer zorgen om moet maken. Wat ik al zei, dit alles is heeeel strict geneuzel. Het is echter wel iets wat ik vind dat je je als PHP developer ergens diep in je hersenen moet beseffen. Je bent nog meer dan in andere talen bezig met iets waarvan je eigenlijk nooit kunt zeggen wat het is.
En ozzie, nee natuurlijk ga je niet doen:
<?php
$succes = copy(...);
if (false === $succes) {
// failure
} elseif (true === $succes) {
// success
} else {
// iets anders
}
?>
Wat ik hier vertelde was slechts allemaal door gaan op het verhaaltje van ward, dat het omkeren van een conditie niet hetzelfde resultaat oplevert.
Dat heel erg strict bekijken kun je in PHP simpelweg niet doen en daarom moet je je er ook geen zorgen over gaan maken. Maar je moet wel in je achterhoofd houden dat dat dus de grote beperking van PHP is en dat wanneer je in een situatie het dus wel heel erg strict moet weten (dan denken we over mensen bij NASA en CERN enzo) je dus naar een andere taal over moet stappen.
Maar Wouter, dan gat het om bugs. Ik vind dat je php.net gewoon moet kunnen vertrouwen. Dat er iets mis kan gaan, oké... maar dan is er sprake van een bug.