Au risque de décevoir, il ne s'agit de pépites de grande valeur, bien au contraire, puisque j'utilise ce mot de manière plus qu'ironique.
En effet, indépendamment du niveau et de l'expérience du développeur à l'origine du code, il m'arrive de tomber sur du code peu efficace, voir complètement stupide.
C'est donc une compilation de quelques-unes de ces mauvaises pratiques que je me propose de partager.
Je vais donc commencer par une technique permettant de localiser la clef de la dernière valeur valant TRUE
dans un tableau :
<?php
...
$lastTrue = null;
foreach ($values as $key => $value)
{
if ($value == true)
{
$lastTrue = $key;
}
}
...
?>
Il est vrai que c'est beaucoup plus efficace et lisible que cela :
<?php
...
$lastTrue = array_search(true, array_reverse($values, true));
...
?>
La gestion du temps est parfois également un problème, d'ailleurs, l'une de mes expressions favorites est que le temps, c'est chiant (et c'est un ancien développeur d'opentime qui le dit).
Le but est cette fois de calculer le numéro du jour de la semaine, 1 devant correspondre au lundi, et 7 au dimanche.
<?php
...
$day = date('w', $timestamp);
if ($day == 0)
{
$day = 7;
}
...
?>
C'est à se demander la raison pour laquelle les développeurs de PHP ont cru bon d'ajouter l'argument N
à la fonction date()
avec PHP 5.1 (et pour information, le code incriminé devait être exécuté sur PHP 5.3 minimum).
<?php
...
$day = date('N', $timestamp);
...
?>
Il arrive également parfois que le développeur éprouve le besoin d'initialiser un tableau avec un suite d'entier.
J'ai vu pas mal d'énormité pour réaliser cette simple tâche, mais la plus répandue est celle qui suit.
<?php
...
$array = array(1, 2, 3, 4, 5, 6, 7 , 8, 9, 10 /* en on peut aller très loin comme cela */);
...
?>
Apparemment, il y a des gens qui aiment avoir le bout des doigts carrés.
Personnellement, dans ce cas, j'applique à la lettre l'une des maximes favorites de mon professeur de C++ : un bon développeur est un développeur fainéant.
<?php
...
$array = range(1, 10);
...
?>
Je vais m'arrêter là pour ce billet, car sinon, j'en connais certain qui vont crier au lynchage en place publique, et d'autres qui me diront que si je veux lire du code de qualité, je n'ai qu'à lire autre chose que du code en PHP, ce qui, dans un cas comme dans l'autre, ne sera pas très constructif.
Et puis, il faut que j'en garde sous le coude pour le prochain florilège, même si la matière n'est pas très difficile à trouver, malheureusement.
Pourtant, quoiqu'on dise et quoiqu'on pense du langage, il est possible d'écrire du beau
code en PHP, c'est à dire un code qui est efficace tout en étant lisible et évolutif.
Cependant, pour pouvoir en écrire, il y a pré-requis incontournable, connu sous le vocable RTFM, et qui pourrait être traduit, dans un langage beaucoup moins imagé, par le faite de prendre la peine de lire régulièrement et en profondeur la documentation de PHP.
C'est d'ailleurs la première chose que je demande à mes stagiaires lors de leur arrivée.
Ils me prennent alors bien souvent pour un dingue, mais ils finissent toujours par comprendre l'intérêt de la démarche, car ils découvrent systématiquement des pépites (cette fois dans le bon sens du terme) qui leur simplifie leur travail.
Car s'il y a une chose qu'il est possible de dire au sujet des cas présentés ci-dessus, c'est qu'il laisse transparaître une méconnaissance totale de certaines fonctions pourtant très basiques, mais au combien puissantes, du langage.
À bon entendeur...
44 réactions
1 De Palleas - 11/05/2011, 09:22
J'suis tombé sur du code PHP un peu rigolo dans ce genre là récemment. C'était d'autant plus rigolo que c'était de la part de personnes qui vont te dire que "PHP c'est de la merde".
Comme quoi, c'est ma grand-mère qui a raison : "il n'a pas de mauvais outils, il n'y a que des mauvais ouvriers"
2 De Amaury - 11/05/2011, 09:24
Dans le même genre d'idée, j'ai le cas inverse d'un développeur qui ne connaissait pas la fonction array_walk(). Je lui ai montrée, pour qu'il puisse factoriser intelligemment un bout de code inutilement compliqué à base de foreach. Et par la suite, il transformait systématiquement et aveuglément tous ses foreach en array_walk(), même lorsque ça n'avait aucune utilité et que ça complexifiait de code...
3 De Steuf - 11/05/2011, 09:39
Pourquoi array_reverse est utilisé dans le premier exemple ?
4 De Eric - 11/05/2011, 10:03
Pas mal j'ai eu aussi des bouts de codes assez sympas.
@Steuf: C'est pour répondre à la problématique 'localise la clef de la dernière valeur valant TRUE dans un tableau'
5 De Steuf - 11/05/2011, 10:06
Sinon cet article est assez
, des pépites on en fait tous, quelque soit notre niveau... D'ailleurs pour moi ce ne sont pas des "pépites" car au niveau algorithmique il n'y a absolument rien de choquant dans les exemple cités... ce sont juste une connaissance des possibilités qu'offre le PHP par rapport à d'autres langages.On ne connait pas forcément toutes les fonctions d'un langage mais parfois des fonctions qui paraissent
.Bref pour moi rien de choquant ici... Cet article me fait plus penser à un lynchage qu'autre chose (surtout vu le ton employé) :/
Cela aurait par contre été bien plus drôle avec des algorithmes abracadabrant qui n'ont ni queue ni tête C’est encore plus drôle quand c'est du code que l'on a écrit soit même et que l'on relit un moment après avec un peu de recul
6 De piouPiouM - 11/05/2011, 10:09
@Steuf array_search() va retourner l'index du premier true trouvé en partant du début du tableau. Appliquer un array_reverse() permet de simuler une recherche depuis la fin du tableau.
7 De mageekguy - 11/05/2011, 10:14
@Steuf : Je pense que tu es passé complètement à côté du message porté par ce billet ;).
Relis le dernier paragraphe, là ou il a la lettre R, suivie de T, suivie de F, suivie de M.
8 De Steuf - 11/05/2011, 10:16
@piouPiouM
Oui merci j'avais compris, mais ça ne correspond pas au premier exemple (si l'on veut la même chose écrite différemment). Dans le premier exemple la recherche ne se fait pas par la fin, donc pourquoi l'avoir ajouté dans la version "réécrite" ? C'est plus ça ma question.
9 De mageekguy - 11/05/2011, 10:18
@Steuf : Ça correspond parfaitement.
le but est de trouver la dernière valeur à
TRUE
dans le tableau.Le
foreach
parcours donc tout le tableau et met à jourlastTrue
au fur et à mesure, à chaque fois qu'une valeur vautTRUE
(d'ailleurs, pour rebondir à l'un de tes précédents commentaires, comme algorithme inefficace, on ne fait guère pire).array_search()
cherche le premier élément d'un tableau ayant la valeur donnée comme premier argument.Donc pour trouver la dernière valeur ayant une valeur précise avec
array_search()
, il faut commencer par retourner le tableau, en conservant l'ordre des clés, d'où l'utilisation dearray_reverse()
avecTRUE
en second argument.10 De Steuf - 11/05/2011, 10:20
Au temps pour moi... j'ai mal lu le premier exemple j'ai imaginé un break; juste après $lastTrue = $key;
Mea culpa
@mageekguy C'est juste la façon d'apporter le message qui est "bizarrement" amené. Je suis d'accord sur le fond, pas sur la forme du message
11 De Steuf - 11/05/2011, 10:28
@mageekguy Oui oui je me suis rendu compte de mon erreur avant même que tu publie ton commentaire Donc totalement d'accord, même au niveau algo ce n'est pas très performant mais ce n'est pas faux ni abracabrant C'est juste la forme la plus simple qui vient le premier à l'esprit chez les débutants d'ailleurs.
Un stagiaire m'avait bien passé 3 jours une fois à m'écrire une fonction de validation des adresse IP... Qui est faisable simplement avec filter_var.
12 De desfrenes - 11/05/2011, 10:29
Beaucoup d'explications pour ce petit bout de code... sans douter de son efficacité, c'est à se demander s'il est aussi lisible que ça.
13 De Arkh - 11/05/2011, 10:32
Je ne peux qu'approuver le conseil de lire la documentation comme premier réflexe. Celle de php est extrêmement bien construite et les commentaires ajoutés peuvent faire gagner des heures de boulot.
Une heure passée à simplement parcourir cette documentation (surtout si on commence par ce qui concerne les fonctions en rapport avec les tableaux et chaînes de caractères) se transforme vite en dizaines d'heures économisées à ne pas réinventer une roue carrée.
Sinon, pour de vraies pépites, voire un bonne dose de désespoir, le site thedailywtf.com reste incontournable. Par exemple http://thedailywtf.com/Articles/Tho...
14 De Joris - 11/05/2011, 10:36
Je pense qu'il faut continuer à faire émerger les petites fautes de développeurs comme cela car c'est un excellent moyen de les faire évoluer.
Bien sur que si on n'a étudié ou fait que des langages de bas niveau et qu'on ne passe pas un certain temps sur la doc', on a tendance à vouloir refaire la roue avec PHP alors que des outils sont déjà existants (cf. l'exemple de la lecture d'un fichier avec le while()).
15 De Steem - 11/05/2011, 11:17
@Steuf: bien d'accord avec toi.
Quel est l'intérêt de ce post ?
La manière dont il est amené laisse supposer que tout ton code est optimisé en profondeur, que ta manière de coder est la seule qui soit correcte...
Tout le monde fait des erreurs, n'a pas eu le temps de se palucher la doc PHP en long, en large et en travers (ou de suivre tous les commits sur le trunk PHP), n'a pas x années d'expérience en PHP.
La première qualité d'un développeur senior est d'accompagner les profils juniors sans mépris, ni leçon de morale.
Es-tu du genre à fouetter un développeur en place publique lorsque celui-ci "casse" une application suite à un commit ?
Je ne doute pas que tu maitrises parfaitement PHP mais, à trop vouloir le faire savoir, ça en devient ridicule.
16 De mageekguy - 11/05/2011, 11:35
@Steem :
Je pense que tu est également passé à côté du message principal de ce billet.
J'essaye effectivement d'écrire un code de qualité.
Mais je n'ai nullement la prétention d'écrire LE code.
Tout le monde fait des erreurs, certes.
Mais lire la documentation du langage qu'il utilise est le boulot de tout développeur, alors ne vient pas me dire qu'il n'a pas le temps de le faire : il doit le prendre, tout simplement, car c'est son job.
Et d'autant plus lorsqu'il n'a pas d'expérience.
Quand à la réflexion sur mon suivi du trunk, elle m'a bien fait rire.
Cela veut-il dire qu'il ne faut jamais dire ce qui est mal, uniquement ce qui est bien ? J'ai du mal à croire qu'une telle attitude permette à un junior de progresser.
Je te remercie cependant de te tirer toi-même une balle dans le pied en donnant la raison d'être de ce billet.
Aucunement, et le fait que tu me poses la question prouve que tu me connais bien mal.
Et j'ai du mal à voir le rapport de cette question avec mon billet.
C'est justement parce que je n'ai pas la prétention que tu me portes et que je suis très humble par rapport à cela que je RTFM régulièrement, sur énormément de sujet et que je fais également une veille technologique intensive.
17 De stealth35 - 11/05/2011, 13:43
j'aime bien le coup de l'array, on voit plus souvent celui en alpha (alors que : range('a', 'z') )
pour les dates y'a du fun aussi :
- faire une liste avec la traduction... alors que y'a strftime ou DateFormatter
- parser une date avec des explode (pardon split) et compagnie, mais pas un seul strtotime (même si ce n'est pas la solution miracle)
18 De De passage... - 11/05/2011, 14:50
@stealth35 : lorsqu'il s'agit de faire une appli portable devant fonctionner sur tout type d'hébergement, l'emploi d'un array pour les traductions de dates est une solution satisfaisante. strftime est trop dépendante de la configuration du serveur de l'hébergeur... Attention à ne pas tomber dans la critique facile sans connaître le contexte et les contraintes qui s'imposaient alors au développeur
19 De stealth35 - 11/05/2011, 18:19
@De passage : si tu part du principe que la config est naze ton commentaire est encore plus facile que le mien...
De plus un serveur mal configuré dans un env pro (puisque tu parles de "développeur") c'est pas très logique en soit.
Et pour te dire même chez "free (en PHP 4)" ça marche.
Y'a 5 ans OK, de nos jours pitié non.
20 De Marc - 11/05/2011, 19:55
C'est bien d'optimiser mais je pense qu'il faut garder à l'esprit qu'un code doit pouvoir être relu et compris facilement par un autre dev qui devrait le reprendre.
Par exemple, j'utilise beaucoup les ternaires, même pour 5 ou 6 conditions. Du coup, je fais 10 lignes en 1 ou 2. Par contre, quand certains repassent derrière, ils me disent que j'abuse...
21 De Closure - 11/05/2011, 20:28
Il m'est aussi arrivé de trouver chez des "développeurs" (très) juniors, les sempiternelles variables nommées $toto ou encore $mavariable. Voire même une fois un jeune qui stockait tout dans des variables, même s'il n'y avait qu'une utilisation, par exemple, $x = 'Hello world'; echo $x;
Là, quelque soit l'outils c'est bien l'ouvrier qui pose problème.
22 De desfrenes - 11/05/2011, 21:58
@stealth35 explique-moi ça: http://framework.zend.com/svn/frame...
23 De desfrenes - 11/05/2011, 22:46
ah oui... un peu off-topic mais bon... dans le genre php ça pue...
En python, afficher le nom du mois depuis un datetime avec la locale en cours:
now.strftime("%B") # yes, nickel, exactement ce que je veux et exactement comme la doc
En PHP, avec un DateTime:
$now->format("%B"); // ah ben nan... ça marche pas... ce format n'est pas supporté
$now->format('M');// ah ben nan... c'est en anglais ça...
Et après on se demande pourquoi les "juniors" réinventent la roue... t'as beau RTFM ça finit toujours par WTF.
24 De Olivier - 12/05/2011, 01:04
@Marc : les commentaires, c'est pas fait pour les chiens. Donc oui, tu abuses de ne pas commenter ton code.
25 De De passage... - 12/05/2011, 10:01
stealth35@: tu ne m'as pas compris.
Je ne pars pas du principe que la config est naze en phase de développement. Dans le cadre d'une appli type framework, cms, forum ou autre, devant être proposée à un vaste public en téléchargement et devant se retrouver hébergées sur des configurations très hétérogènes, l'emploi de strftime est "casse-gueule". Bien-sûr, tu peux le spécifier dans les pré-requis, tu peux aussi assurer un support technique, etc. Mais la non utilisation de strftime évitera bien des soucis. J'ai pris cet exemple car c'est celui sur lequel tu t'es jeté. Il y en a plein d'autres qui sont le résultat d'un mauvais choix évident de la part du développeur, mais pas celui-là, désolé !
Maintenant, s'il s'agit de développer une appli dont on maîtrise le déploiement, ok.
D'où ma phrase : "Attention à ne pas tomber dans la critique facile sans connaître le contexte et les contraintes qui s'imposaient alors au développeur"...
26 De De passage... - 12/05/2011, 10:08
mageekguy@ Dans la lignée de ce topic, tu pourrais inaugurer une nouvelle série, qui permettrait de confronter nos solutions pour résoudre un problème précis. Le problème ferait l'objet du topic, et les commentaires proposeraient des solutions. Et comme c'est toi qui valides les commentaires, tu pourrais les valider tous à la fois, au bout d'une semaine, par exemple, pour croiser les solutions et éviter la copie ou l'inspiration de la solution d'un autre
27 De stealth35 - 12/05/2011, 10:21
@desfrenes, c'est autre chose ça.
Intl c'est pareil les formats sont en dur, et strftime c'est aussi la même chose .... en dur, tu crois que les dates elles sortent de nul part ???
Moi je te parle de ne pas recréer les formats puisque qu'ils existent déjà (peu importe la forme ou l'endroit)
28 De Marc - 12/05/2011, 10:37
@Olivier : qui a parlé de commentaires ? Bien heureusement que mon code est commenté... C'est une question d'intuitivité de lecture, qui est forcément moindre qu'une boucle if / else, commentaires ou pas. Je suis un dev flemmard, mais mes collègues aussi...
29 De mageekguy - 12/05/2011, 21:00
@De passage... : Vu que tu n'es que de passage ;), tu ne le sais peut être pas, mais je l'ai déjà fait à plusieurs reprises (il faut fouiller un peu dans les archives du blog pour trouver le reste), sous une forme un peu différente il est vrai.
30 De syndrael - 13/05/2011, 09:56
Pas mal de commentaires intéressants et un vrai débat de fond qui se pose..
Doit-on tout optimiser ? Est-ce utile de prendre du temps pour optimiser en fonction de l'appli ? Est-ce que cela nuit à la compréhension du code ? Est-ce que ça ne restreint pas le nombre de personnes qui peuvent comprendre le code (surtout dans le cas d'un débugging) ?
Ma logique est de faire un code bateau et compréhensible pour une appli qui sera effectué une fois tous les 36.. même pas optimisée.. je m'en moque.. !!
Par contre, celui qui veut diffuser un framework, un CMS ou tout autre logiciel qui servira de base à la création de quelque chose, là il se doit d'optimiser et d'être quasi-irréprochable..
Y'a toujours un jour ou on rencontre plus expert que soi.. !!
Donc tout est relatif !! ..comme beaucoup de choses d'ailleurs.
S.
31 De mageekguy - 13/05/2011, 10:19
@syndrael : Je ne suis pas vraiment d'accord avec le fait que ce qui est présenté dans ce billet soit de l'optimisation, ou du moins de l'optimisation .
Certes, le code de départ remplit son office, mais celui qui le remplace n'est pas, ou n'a pas vocation à être plus efficace en terme de performances (date('w') et date('N'), en terme de ressource, c'est bonnet blanc et blanc bonnet), sauf dans un cas, le premier.
En effet, dans son cas, non seulement l'implémentation était inadéquate par rapport aux possibilités offertes par le langage, mais en plus, l'algorithme était mauvais, puisque partir du début d'un tableau pour en extraire la dernière clef ayant une valeur précise est loin d'être optimum.
Et à mon sens, l'optimisation
ne se fait pas sur la façon d'utiliser le langage mais sur la mise en œuvre de processus plus pertinent.Les autres exemples sont donc plus à mon sens la démonstration d'une utilisation efficace et intelligente du langage grâce à une bonne connaissance de ses possibilités et une lecture attentive et régulière de sa documentation que de l'optimisation (même s'il y en a forcément un peu, mais je ne pense pas qu'elle soit très significative dans la plupart des cas).
32 De joey - 30/05/2011, 00:19
Sooooo bullshit ! Ca dépend beaucoup des cas, réfléchis à ce que fait array_reverse : un parcours de tout le tableau et une recopie en sens inverse, en bouffant de la RAM au passage (et les allocations mémoire ne sont pas gratuites).
Fais différents tests en variant la taille du tableau et l'emplacement de la variable true. Et aussi, éventuellement, remplace le == true par === true de l'autre technique.
Dans un cas, ta technique était carrément 8x plus lente qu'avec l'algorithme dont tu te moques.
T'es sûr de vouloir continuer à faire des articles sur ce sujet ?
33 De mageekguy - 30/05/2011, 13:14
@joey : J'adore les affirmations gratuites comme les tiennes.
Voici donc un premier script, qui met en œuvre la solution
foreach
:Tu remarqueras que je me suis mis dans le cas le plus défavorable à ma solution, puisque la valeur TRUE est la première valeur du tableau de 500 000 éléments.
Voici les résultats, sous MacOS X Snow Léopard et PHP 5.3.4 (avec xdebug) :
Voici maintenant le second script, utilisant le combo a
rray_search()
+array_reverse()
:Et voici les résultats :
La solution basée surarray_search() +
foreach
est donc plus de deux fois plus lente, sans parler de sa consommation de mémoire, dans le cas le plus défavorable au comboarray_reverse()
.Effectivement, le recours à
===
accélèreforeach
, qui fait alors jeu égal avec array_search(), si l'on passe également à cette dernièreTRUE
en dernier argument, pour qu'elle effectue également un contrôle de type similaire à===
pourforeach
, mais pour autant, la consommation de mémoire deforeach
reste de loin la plus importante.À la rigueur, tu aurais mieux fait d'argumenter sur le fait que le code que j'ai mis dans le billet n'est pas iso-fonctionelle en l'état, ta remarque aurait été alors beaucoup plus... pertinente et pour le coup, n'aurait pas été du
.Tu es sur de vouloir continuer à mettre des commentaires sur ce blog ?
34 De joey - 30/05/2011, 15:06
euuuh... tu as vérifié ce que faisait :
Parce que parcourir un tableau avec des indexes numériques ne me parait pas vraiment en adéquation avec le code foreach ... $key=>value.
Initialise-le avec :
Et là, surprise ! ton code est plus de deux fois plus lent, trois fois plus lent avec un ===true (sous OS X).
Quant à l'usage de mémoire, personnellement je préfère mettre le booléen real_usage à true. Mais on peut aussi tester le peak, qu'en dis-tu ?
donc :
et à la fin :
Résultats sous OS X 10.6 :
Résultat sur une Debian 64 :
P.S. : le memory_get_peak_usage avec ou sans flag real_usage revient au même : ton script nécessite plus de mémoire à cause du array_reverse.
P.P.S. : "À la rigueur, tu aurais mieux fait d'argumenter sur le fait que le code que j'ai mis dans le billet n'est pas iso-fonctionelle en l'état" c'est vraiment pas mon genre.
35 De mageekguy - 30/05/2011, 15:32
@joey :
On va dire que oui ;).
À partir du moment ou il faut localiser la clef d'une valeur, je ne vois pas en quoi la nature de cette clef a de l'importance, mais bon...
Euuuhhh.... non !Euuuuhhhhhh... non (bis).
En conclusion, désolé, mes tests ne recoupent pas du tout tes résultats, même lorsque des tableaux associatifs sont utilisés (d'ailleurs, il n'y a aucune raison technique pour que ça change le résultat) :
foreach
se fait enfoncer dans les grandes largeurs.Maintenant, si tu veux continuer à faire aux drosophiles des choses que certaines religions réprouves, je te suggère ce code, qui a le mérite par rapport au
foreach
de ne pas parcourir l'intégralité du tableau si ce n'est pas nécessaire :36 De syndrael - 31/05/2011, 13:59
Je regrette que sur ce blog on ne soit pas prévenu des nouveaux commentaires.. les optimisations PHP et algorithmiques me plaisent en général, et cette conversation me plait dans la mesure où on trouve enfin des gens qui savent de quoi ils parlent..
Toutefois, SAUF à travailler sur des sites à forte sollicitation il ne faut pas partir dans le capillotracté.. Hélas bien souvent (en tout cas de mon coté) je dois faire du compréhensible pour le développeur lambda (dont le dév n'est pas le métier premier, et surtout la compétence première).
Mais le coup du 'for' qui ne va pas jusqu'au bout allait être ma solution.
Ca pourrait être sympa de proposer une problématique et de tester les solutions respectives (compréhension, technicité, memoire, temps d'éxecution).
Bonne journée à tous
S.
37 De mageekguy - 31/05/2011, 14:38
@syndrael : Il me semble qu'il y a le fil RSS des commentaires, pour être tenu au courant des nouveaux commentaires.
38 De joey - 31/05/2011, 16:20
"Toutefois, SAUF à travailler sur des sites à forte sollicitation il ne faut pas partir dans le capillotracté.."
Il m'arrive assez souvent d'avoir des choses assez lourdes à faire, comme par exemple de chercher 200.000 chaines dans 300.000 messages en case insensitive. Dans ce cas, par exemple, une lecture simple du manuel fera utiliser stripos, sauf que ça n'est pas du tout efficace : il vaut mieux tout convertir en minuscules et utiliser strpos pour les recherches.
En réalité c'est beaucoup plus logique pour la machine : on convertit une fois pour lui permettre de faire des centaines de milliers de comparaisons strictes, alors qu'un stripos va, pour chaque caractère, tester en majuscule ou minuscule.
Concernant le problème du billet : dans le cas du for, on fait un seul passage sur des données connues. Dans l'autre cas c'est illogique pour la machine : on lui demande de créer une copie inversée du tableau pour ensuite faire une seule recherche "performante"*. A lire pour un humain, c'est plus clair, au niveau machine c'est aberrant... capillotracté, si vous préférez :o).
Et le for proposé par mageekguy en utilisant directement les clés semblerait être la meilleure solution, mais en réalité elle ne l'est pas toujours : le problème c'est que key et prev sont des fonctions et qu'elles font perdre du temps.
En fait ça dépend : ça peut être la meilleure alternative *si on sait qu'il y aura surtout un true vers la fin du tableau, mais si ça n'est pas le cas (qu'on a généralement des true vers le début ou même pas de true), il vaut mieux utiliser la solution décriée dans ce billet car elle n'utilise que des instructions simples et ne nécessite pas de recopie des données, elle est par conséquent assez efficace.
Si on avait un certain nombre de recherches à effectuer de valeurs attendues en fin de tableau, par contre, le array_reverse pourrait être le plus efficace : ça ne serait toujours pas le plus logique pour la machine, mais ça serait justifié pour profiter de la vitesse des instructions natives. Quoique... avec Hip Hop PHP par exemple, le résultat pourrait être différent.
Bref, il est toujours extrêmement délicat de savoir pourquoi un programmeur choisit une solution plutôt qu'une autre, et la plupart du temps ça dépend de tout un contexte.
CF, pour ceux que ça intéresse, les essais de John Resig pour trouver un bon algo de recherche dans un dictionnaire, par exemple :
http://www.google.com/search?&q...
(lien vers Google pour lire les articles en cache - les deux premiers - , le site est down en ce moment)
39 De mageekguy - 31/05/2011, 22:14
@joey : Tu devrais te documenter sur le fonctionnement de la VM de PHP et lire le source du langage, car tes raisonnements, potentiellement pertinent dans un langage comme le C, ne s'applique pas forcément dans son cas.
PHP dispose en effet d'une gestion de la mémoire spécifique, basée entre autre sur des compteurs de référence et du
, qui fait, par exemple, quearray_reverse()
ne duplique pas en mémoire l'intégralité du tableau qui lui est passé en argument comme tu le penses.C'est d'ailleurs le même mécanisme qui fait que
foreach
travaille sur des copies de tableaux sans pour autant dupliquer l'intégralité du tableau considéré en mémoire.De plus, tu sous-estimes apparemment l'intelligence des développeurs de PHP, puisque
stripos()
ne fait nullement une comparaison caractère par caractère, mais utilise ton algorithme, à savoir que les chaînes passée en argument sont converties en minuscule avant d'être utilisées (cependant, je ne veux nullement dire questripos()
est la bonne solution dans ton cas, juste que tes connaissances sont imprécises).40 De joey - 01/06/2011, 15:14
"PHP dispose en effet d'une gestion de la mémoire (...) sans pour autant dupliquer l'intégralité du tableau considéré en mémoire."
Ok donc il copie simplement les références et ne duplique les données qu'en cas de changement appliqué à l'une des références, c'est ça ? Même si c'est bien plus performant ça reste tout de même assez coûteux puisque dans le search+reverse, la quasi-totalité du temps est passé dans le reverse.
"De plus, tu sous-estimes apparemment l'intelligence des développeurs de PHP (...) sont converties en minuscule avant d'être utilisée"
Comparer directement caractère par caractère n'aurait rien eu de mauvais, je ne sous-estime pas les compétences des développeurs de PHP mais je ne lis pas leur source, tu as raison. Je ne suis pas contributeur et je n'ai pas assez de temps pour m'y plonger et découvrir des choses moi-même (c'est pour ça que je lis ce blog d'ailleurs : avoir une idée des évolutions et éventuels changements de comportement à venir).
De toute façon, je pense qu'il très rarement possible de prédire ce qui est le plus performant à la simple lecture du code et de la doc dans un langage de haut niveau. Mon approche est donc plutôt d'envisager plusieurs possibilités devant à priori donner des performances différentes et de les tester. Car il est très dur de savoir exactement comment le code sera retranscrit, s'il y aura des optimisations (par APC par exemple, et je n'ai pas encore eu l'occasion de tester Hip Hop PHP mais ça doit encore être autre chose). Et au final, il y a le code machine, et là encore, les processeurs rajoutent leurs couches d'optimisation.
--
Disons que je trouve que cet exemple est mal choisi et ne méritait pas d'être critiqué d'emblée, puisque mes tests ont montré qu'en pratique, il pouvait être avantageux.
41 De AD - 04/06/2011, 19:21
Tout ceci me semble bien fat ...
Discuter pour dire ma solution est meilleur et d’ailleurs je te le prouve en faisant un test pour le prouver ressemble fort à un concours de cour de récréation ...
Il ne faut pas oublié qu'il y a toujours deux parties en présence : les traitements et les données ... De deux choses l'une, ou on est sur de toujours connaitre la forme que vont prendre les données (leur répartition, c'est rare mais cela arrive) et là on peut espérer dire mon code est potentiellement le meilleur pour traiter ces données, ou bien on n'a aucune idée de la forme que vont prendre ces données et alors il devient difficile pour ne pas dire impossible de déterminer a priori si l'algo va être le meilleur ...
Quelques remarques d'ordre général :
La base du métier me semble être (au niveau technique) l'algorithmie. Donc écrire du code avec des boucles et des structure de test ne peut pas être une mauvaise choses, surtout au niveau de la relecture par un autre développeur.
Utiliser une fonction du langage qui fait la même chose n'est pas inintéressant, mais complique la relecture par quelqu'un qui ne connait pas bien le langage. Il faut aussi se poser la question suivante : Cette fonction est-elle fiable, n'ai-je pas le risque que mon code produise un résultat inattendu si pour une raison inconnue les données fournies à la fonction font réagir celle-ci de manière inattendue ?
Autre question à se poser, vaut il mieux pour un développeur X donné qu'il utilise à peu près correctement des structure de contrôle pour son problème plutôt qu'il utilise mal une fonction parce qu'il n'a pas ou mal compris son utilisation ?
Il est possible dans certains langages de réaliser un traitement donné en une ligne tout comme on pourrait l'écrire en 20 lignes de code. Dans ce cas il faut bien soupeser ce que va devenir ce code. S'il est destiné à être relu et maintenu, je pense que la version 20 lignes est préférable. Maintenant si ce code est un outils que je vais être le seul à utiliser, la version 1 ligne sera peut être plus appropriée et flattera mon ego. Juste, peut être que dans 3 ou 4 ans, étant passé à autre chose, je ne serait plus en mesure de comprendre instantanément de quoi il en retournait !
42 De mageekguy - 05/06/2011, 21:21
@AD : Je suis d'accord avec toi sur le fait que les derniers commentaires sont assez inutiles.
Le débat n'a clairement pas pris la tournure que j'attendais, mais j'ai été obligé de suivre le mouvement et de me justifier.
Concernant le reste de ton commentaire, je suis beaucoup plus réservé.
Si le développeur ne fait pas confiance au langage qu'il utilise, il y a un problème quelque part, soit au niveau du langage, soit au niveau du développeur, même si je suis d'accord qu'un algorithme bien conçu mais mal implémenté est toujours plus intéressant conceptuelllement qu'un algorithme stupide bien implémenté.
Quand à la complexité, elle peut être effectivement un problème, et c'est bien pourquoi je n'ai pas proposé dans mon billet l'alternative basée sur for que j'ai indiqué dans l'un de mes derniers commentaires.
Dans tous les cas, ne pas utiliser les ressources du langage et réinventer la roue n'est pas, et ne sera jamais, une bonne pratique, et cela implique donc de bien connaître le langage, ce qui veut dire lire sa documentation dans le détail et suivre ses évolutions.
43 De kaymak - 21/07/2011, 12:40
Hello,
plutôt qu'un lynchage publique, j'aurais préféré y voir une forme de "you can do it better" dans la lecture de l'article.
a+
44 De mageekguy - 21/07/2011, 18:03
@kaymak :Pour qu'il y ait lynchage, il faut une victime...