Par Pascal MARTIN le mercredi 17 décembre 2014

La semaine dernière, j’ai parlé de Tmux, un Terminal Multiplexer, à mes collègues chez TEA1.


Voici les slides que j’ai utilisés comme support : Tmux, une introduction pratique

Pour compléter ces slides, appuyer sur [S] donne accès aux notes du présentateur, qui contiennent des informations supplémentaires — globalement, ce que j’ai dit à l’oral, qui ne figure pas sur les slides en eux-mêmes.


Pour ceux qui n’auraient jamais entendu parler de tmux, le principal intérêt pour moi est de pouvoir se connecter en SSH à un serveur, lancer une session tmux contenant plusieurs fenêtres exécutant chacune un ou plusieurs programme et retrouver celle-ci même après une coupure de la connexion SSH — sans que les programmes n’aient été interrompus.

Je l’utilise également en local sur mon poste de travail, où il me permet notamment d’héberger plusieurs fenêtres au sein d’une seule application graphique de terminal (sans avoir 36 fenêtres ou onglets graphiques ouverts correspondant chacun à un seul terminal), ainsi que de retrouver mon environnement lorsque je me connecte à ma machine depuis le PC d’un collègue.



  1. J’utilise tmux depuis plusieurs années et plusieurs collègues voulaient commencer à s’y mettre ; c’était une occasion parfaite pour en parler un peu plus en profondeur ! 

Par Pascal MARTIN le lundi 1 décembre 2014 18 commentaires

Il y a quelques années de cela, je me suis un jour retrouvé face à une fonctionnalité inattendue1 d’une application e-commerce : une action, qui n’aurait dû être effectuée que si le montant enregistré sur une commande était différent de la somme des montants des produits la composant2, était déclenchée bien plus souvent que nécessaire.

En fouillant dans les portions de code en rapport avec ces points, voici globalement comment le prix total de la commande était déterminé3 :

$priceShipping = 0.00;
$priceTotal = 35.93 - $priceShipping;

Le prix total des produits figurant sur la commande était calculé comme ceci4 :

$pricesItems = [4.99, 4.99, 4.99, 4.99, 4.99, 5.49, 5.49];
$priceTotalItems = 0;
foreach ($pricesItems as $priceItem) {
    $priceTotalItems += $priceItem;
}

Jusqu’ici, rien de bien gênant.

Par contre, les choses s’enveniment sur la condition suivante :

if ($priceTotal === $priceTotalItems) {
    echo "Prix égaux\n";
}
else {
    echo "Prix différents\n";
}

Naïvement, en écrivant cette condition, quelqu’un s’est dit qu’il allait comparer le contenu de deux variables et que si les nombres correspondant n’étaient pas égaux, une action spécifique5 serait lancée. OK, pourquoi pas ?

À titre de vérification, dumpons le contenu des deux variables contenant les deux montants, avant les quelques lignes reproduites juste au-dessus :

var_dump($priceTotalItems, $priceTotal);

Passons à l’exécution de ces quelques portions de code.
La sortie est reproduite ci-dessous… Et elle est quelque peu surprenante :

$ php test-01.php 
float(35.93)
float(35.93)
Prix différents

Surprise !
De toute évidence, 35.93 et 35.93 sont égaux, non ? Et pourtant, la sortie indique que ces deux montants sont différents !

Pour s’en assurer, ré-exécutons ces quelques lignes de code, en augmentant la précision d’affichage :

$ php -d precision=40 test-01.php 
float(35.93000000000000682121026329696178436279)
float(35.92999999999999971578290569595992565155)
Prix différents

Et voila ! En travaillant avec une précision d’affichage supérieure à celle utilisée par PHP par défaut, nous obtenons plus de décimales dans nos dumps de debug — et libre à nous de constater que nos deux nombres flottants, même s’ils paraissent égaux si l’on s’arrête à deux décimales, ne le sont en réalité pas si on regarde plus loin.

La leçon à retenir est qu’il ne faut pas comparer en égalité deux nombres flottants.
À la place, il est plus sûr de vérifier si l’écart entre eux est inférieur à un seuil qui nous semble acceptable.

Par exemple, dans notre cas où nous manipulons des montants en euro, nous pourrions écrire ceci :

if (abs($priceTotal - $priceTotalItems) <= 0.0001) {
    echo "Prix considérables comme égaux\n";
}
else {
    echo "Prix considérables comme différents\n";
}

Les nombres flottants de PHP sont représentés en interne par le format IEEE 754 double et ne sont donc pas exacts.
Il est impératif de ne pas oublier ce fait lorsqu’on est amené à en manipuler ainsi qu’à effectuer des calculs dessus !


Petite question pour finir :

Est-ce que 0.1 + 0.2 est égal à 0.3 ?


Tout de même, pour aller un peu plus loin, n’oublions pas que PHP, à son habitude, se repose sur les fonctionnalités que C fournit. Nous pourrions donc écrire le programme suivant en C, pour voir ce qu’il en est avec ce langage :

#include <stdio.h>

int main()
{
    double price_shipping = 0;
    double price_total = 35.93 - price_shipping;

    double prices_items[] = {4.99, 4.99, 4.99, 4.99, 4.99, 5.49, 5.49};
    double price_total_items = 0;
    for (int i=0 ; i<7 ; i++) {
        price_total_items += prices_items[i];
    }

    if (price_total == price_total_items) {
        printf("Prix égaux\n");
    }
    else {
        printf("Prix différents\n");
    }

    return 0;
}

Pour compiler (avec gcc, ici) :

$ gcc -W -Wall --std=c99 test-01.c -o test-01

Et à l’exécution, nous obtenons le même type de résultat qu’avec PHP :

$ ./test-01 
Prix différents

Un point intéressant : dans ce cas précis, si nous utilisons des float en simple précision (et pas des doubles en double précision), le programme indiquera que les deux montants totaux sont égaux (la différence qui les sépare doit porter sur plus loin que la précision des floats).


Bien évidemment, nous obtiendrions la même chose avec le même programme ré-écrit en JAVA :

class Test01
{
    public static void main(String[] args) {
        double price_shipping = 0;
        double price_total = 35.93 - price_shipping;

        double prices_items[] = {4.99, 4.99, 4.99, 4.99, 4.99, 5.49, 5.49};
        double price_total_items = 0;
        for (int i=0 ; i<7 ; i++) {
            price_total_items += prices_items[i];
        }

        if (price_total == price_total_items) {
            System.out.println("Prix égaux");
        }
        else {
            System.out.println("Prix différents");
        }
    }
}

Par contre, cette fois-ci, l’affichage par défaut mettrait immédiatement en évidence le fait que ces deux montants ne sont pas égaux, puisque price_total serait affiché comme valant 35.93, alors que price_total_items provoquerait la sortie de 35.93000000000001.


Ne nous arrêtons pas là : nous obtiendrions encore la même chose avec un script en Ruby :

price_shipping = 0.00
price_total = 35.93 - price_shipping

prices_items = [4.99, 4.99, 4.99, 4.99, 4.99, 5.49, 5.49]
price_total_items = 0
prices_items.each do |price_item|
    price_total_items += price_item
end

if price_total == price_total_items
    puts "Prix égaux\n"
else
    puts "Prix différents\n"
end

Afficher (en paramètres par défaut) nos deux montants donnerait le même type de sortie qu’en JAVA.


En somme, vous l’aurez compris, IEEE 754 est utilisé à peu près partout lorsqu’il s’agit de manipuler des nombres flottants — et il nous revient de connaître leurs limitations et de veiller à ne pas nous faire avoir ;-)



  1. Il y a quelques temps, j’ai entendu dire qu’il n’était pas bon de parler de bugs dans les applications sur lesquelles je bossais, que cela faisait peur. Le terme de fonctionnalité inattendue s’est imposé comme une réponse à cette remarque. Et même si celle-ci n’était pas vraiment à prendre au sérieux, j’ai retenu ce fonctionnalité inattendue, que j’affectionne quelque peu ^^ 

  2. Le montant est enregistré au niveau de la commande lors du paiement de celle-ci. Si un produit est annulé plus tard, la somme des montants des produits restant devient différente du montant enregistré sur la commande — c’est un comportement voulu et normal. 

  3. Pour cet exemple, 0.00 correspond aux frais de port et 35.93 au montant enregistré sur la commande — ces deux informations provenant de la base de données. 

  4. Ici encore, les prix individuels des produits composant la commande proviennent en réalité de la base de données. 

  5. Bien évidemment, dans l’application dont cette portion de code quelque peu simplifiée est extraite, l’action spécifique est un peu plus complexe qu’un affichage ;-) 

Par Pascal MARTIN le vendredi 28 novembre 2014

Cet article est aussi disponible en français.

You can follow me @pascal_martin, and there is an RSS feed of the posts I write in English.

809 messages have been exchanged in October 2014 on PHP’s internals@ mailing-list — a bit more than in September.

As a graph representing the number of mails per month for the last three years, we’d get:

First of all, PHP 5.6 has entered its normal cycle of releases, with a first maintenance version at the beginning of the month.


Nikita Popov has written the RFC: Remove deprecated functionality in PHP 7, suggesting to remove from PHP 7 everything that was flagged as deprecated on all 5.x versions including, for example : ext/ereg, ext/mysql, affectation of new by reference, functions to manipulate magic_quotes, # comments in php.ini, … Considering the impact the removal of the first two points might have, this RFC might get voted in three steps (one vote for each of the first two points, and a third one for the remaining ideas).

Kris Craig noted that ext/mysql has been obsolete for a while — and the fact some sites and tutorials are still referencing it should not prevent its removal. Also, Rasmus Lerdorf said most PHP users get their installations and PHP extensions from their distributions and those tend to package PECL extensions as if they were provided directly with PHP.

Johannes Schlüter insisted that, independently of the eventual removal of ext/mysql, educating users is important, to ensure they stop using this extension — and Derick Rethans added that ext/mysql having a procedural interface is not a good enough reason in itself to justify its removal. Zeev Suraski also reminded us that every time a feature is broken of removed, updating becomes a bit harder for users.

On the other hand, as Pierre Joye answered, if deprecated features never get removed, there is no use in flagging them as deprecated and one could just stop doing that.


In the middle of the month, Zeev Suraski announced the RFC: PHP 7.0 timeline, which aims to quickly release PHP 7 (in about one year), even if it means not getting some features. Things that break compatibility should make it for PHP 7.0 (as BC-breaks are only possible for major versions), but other features that don’t cause BC-breaks could arrive with PHP 7.1 or 7.2. Waiting for too long might also lead to a version with too many incompatibilities, which would slow its adoption down.

Xinchen Hui answered indicating he thought one year was a bit long. Others quickly noted it might be better to not go too fast : several ideas could yet be taken into account for PHP 7 — even if only compatibility-breaking stuff must go into the 7.0 version (still, one should not forget anything, to avoid having to wait for another ten years).

Rasmus Lerdorf also indicated the master branch might require a bit of time to get stabilized — even more on a project with its fair share of legacy code, like PHP, where each change can have consequences that are not always very well anticipated.


Variadic functions having been added to PHP 5.6, Marco Pivetta proposed to flag as deprecated, for PHP 5.7, functions call_user_func, call_user_func_array, func_get_args, func_num_args and func_get_arg — in order to remove them later, for PHP 7. They could, if necessary, be re-implemented in user-space, for the compatibility of applications using them.

Andrea Faulds answered this removal would cause a great BC-break for applications, which would no longer work with a basic install of PHP 7 — even if it is possible to re-implement them in user-space. Removing those functions would also not bring any real gain.

Still, the idea of removing (now useless) functions from PHP core to move them to user-space also makes sense… Even if it probably wouldn’t be great when it comes to performances.


After a new XML remote-debugging protocol has been implemented for phpdbg, Pierre Joye noted it could be interesting to check whether it is possible to get closer to the DBGp protocol already used by Xdebug. Joe Watkins explained the implementation of that new protocol took place following discussions with PhpStorm’s developers. Bob Weinand then listed a few differences between those two — which could maybe have been added to DBGp?

Stas Malyshev also said that working outside the PHP project for several weeks before merging an entire feature might not be the best way to go for a component that’s integrated in PHP: more discussions could have taken place if those developments had been done in a feature branch of PHP’s repository (well, it has not necessarily been the case in the past — but it goes the same way for PHP as a whole, where changes are not reviewed much). That being said, it would be great if work done here could lead to a unified debugging protocol for PHP.

David Soria Parra then indicated going with an RFC could have been profitable, to think about setting up a new protocol and the best suited solution. Julien Pauli added having a separate website for phpdbg was odd (it’s not usual for components of PHP) and its content could be moved to php.net (it seems to be planned). As phpdbg is a part of PHP, it should follow PHP’s processes.

A few days later and following suggestions in the previous thread, Ferenc Kovacs explained RMs of PHP 5.6 had decided to revert changes brought to phpdbg and not published yet (remote debugging support): as this component is a part of PHP, its major evolutions might require a stabilisation phase and they should follow the process in place for PHP’s evolutions — mostly, going through RFCs. Those changes have been reverted a few hours later, and will come back in the future.


Andrea Faulds wrote the RFC: Big Integer Support, proposing to set up, at an internal level, two kind of integers: traditional integers (limited to numbers that can fit on 32 or 64 bits) and integers based on GMP, which would allow to manipulate numbers as large as one wants. These two internal types would be exposed to user-space as a single integer type, with no size-limit.

Stas Malyshev answered adding a new internal type would require all extensions to take it into account — which means many of those would have to be updated.

Regarding some license issues with GMP, the RFC has been updated later. A benchmark has also been published to show this proposal doesn’t have any real impact on PHP performances, even if more in-depth tests should be done.

After about two weeks, discussions on this matter have stopped, without any decision being reached. We’ll see in the next few months if this RFC comes back to the front of the stage.


Joe Watkins wrote the RFC: UString, which introduces a new UString class, that would provide features related to Unicode strings manipulations. Basically, this UString class would, in a way, take the place of the existing mbstring extension, which is not perfect, with an implementation based on ICU (already used by Intl), faster than mbstring’s one.

The first answers have been rather positive. Pierre Joye added it would be great if this extension was always enabled, to facilitate its adoption.

Dmitry Stogov noted that, if this RFC doesn’t include using UString objects from the engine or other extension, it is incomplete and doesn’t answer all needs (for example, Unicode strings couldn’t be used as keys of arrays, as they would be objects and not real strings — unless another idea gets accepted). Of course, as Johannes Schlüter indicated, a better approach would be a real adoption of Unicode, but PHP 6 showed this is not that easy.


In the previous thread, Stas Malyshev announced he had begun working on RFC: Objects as hash keys, which proposes to add a new magic method (like __hash() or __toKey()) that would allow us to use objects as array keys.

Joe Watkins suggested __toScalar() could be an appropriated name, closer to what this method would actually do, without limiting one to the currently discussed context — but this name would not explain the usefulness of this method.

Alexander Lisachenko added using an interface for this idea could also be a good idea, instead of adding a new magic method — even if a magic-method would be closer to the PHP way of doing things.

Etienne Kneuss noted this RFC doesn’t actually mean using objects as array keys (it would require a lot of work on re-writing PHP HashTables’ handling), but only simplifies syntax. As such, foreach, key() or array_keys() would not return objects, but only their hashes, as calculated by this new method.


Andrea Faulds wrote the RFC: Readonly Properties, based on the fact it is now hard to define a property that can be read from the outside of a class, while not making it writable in the process: one has to write getters/setters and/or play with __get/__set (in any case, we have to write code and its not really efficient). To solve this, the RFC proposes to add a new readonly keyword, that could be used on class properties, to indicate which ones should be readable from the outside of that class.

Rowan Collins noted it would make user-space objects closer to those exported by some extensions (which can have read-only properties) — and it would indeed be great not to have to write numerous lines of code to get this feature. Others suggested to add more precise access-rules, with a syntax like var $callback as rwxrw---x;.

Still, as Jordi Boggiano indicated, another possibility would be to talk again about RFC: Property Accessors Syntax, which was going farther while allowing what’s proposed here — which only answers a portion of the different needs. Nikita Popov also noted the readonly keyword is not necessarily explicit and, contrary to getter methods, properties can’t be defined in an interface. Maybe one could already reserve the syntax for accessors, while only implementing a small part for now?

In the end, Andrea Faulds removed this RFC, as it was a bit confusing and only answered a portion of what was needed.


Kris Craig asked why PHP has $_GET and $_POST super-globals but no $_PUT nor $_DELETE, which could be useful when it comes to developing REST APIs.

Andrea Faulds noted this two variables are poorly named: $_GET corresponds to parameters received from the query-string, while $_POST contains data from the request’s body — another way of seeing things is they correspond to form methods, and not to HTTP primitives. Still, switching to variables like $_QUERY, $_BODY and $_REQUEST could have some sense, but would completely destroy compatibility. On the other hand, Rasmus Lerdorf indicated users know how to use $_GET and $_POST and adding aliases might be going a bit far: of all that might be confusing in PHP, this specific point would be near the bottom he the list.

Michael Wallner then said looking at the pecl_http extension and the RFC: Add pecl_http to core could be a good idea.

The discussion has been intense, with almost one hundred mails in a few days, but I don’t feel like it lead to a decision. In any case, $_GET and $_POST are here to stay — but we might see some other aliases appear in the future…


A few days later, Sherif Ramadan announced he had begun working on RFC: Standardized PHP Http Interface.

Florian Margaine answered PHP should focus on providing implementations more than interfaces: up to user-space to decide how the code should look like. Removing the super-globals ($_GET, $_POST, …) would also break pretty much all existing applications and adoption of PHP 7 would greatly suffer — even if they are not the most perfect interface that could be.

On the other hand, GPC variables are not quite perfect and an interface provided by PHP might unify a bit the way each framework now comes with its own HttpRequest class.

Larry Garfield also indicated there were discussions around that matter on the FIG’s mailing-list and user-space is probably more appropriate for this kind of experimentations.


Andrea Faulds wrote the RFC: Safe Casting Functions, because the existing explicit transtyping operators never fail and never raise any kind of error — which can be dangerous (especially if used on user-supplied data), as they can return pretty much anything if used on garbage-data.

This RFC aims to add three functions, that would validate their input instead of blindly transtype it:

  • to_int() : would only accept integers, floats containing integer values that can fit in integers, or strings containing a textual representation of integers.
  • to_float() : would only accept floats, integers and strings representing floats.
  • and to_string() : would only accept strings, integers, floats and objects that can be transtyped to strings.

The question of the return-value of these functions has quickly been asked (typically, is false a value?), as well as the idea of having them throw exceptions — which could depend on an optional parameter.

Stas Malyshev noted some validation rules already exist in the ext/filter extension and completing them could be more interesting that adding yet another set of rules somewhere else. Using names such as to_int() could cause some confusion for users, as the behavior would not be the same as (int) and a name like lossless_int() might be more appropriate.

Discussions where not finished at the end of the month, and I’m guessing they will go one next month ;-)


Nikita Popov re-launched the RFC: Exceptions in the engine, which was originally targeting 5.6 — not all errors will be turned into exceptions, but a majority of them could be. As before, answers have been rather positive.

Thomas Gossmann asked whether it is possible to remove the function keyword from methods declarations. Levi Morrison quickly indicated this idea had been rejected before, mostly because it would make searching for definitions and code reading harder — while not bringing much to the table. He is not the only one who thinks that.

Votes have begun on RFC: loop + or control structure. With 4 “yes” and 11 “no” votes, it didn’t pass — Leigh, author of this RFC, explained why he, himself, voted “no”. We’ll see if someone else brings back this idea in the future.

Leigh announced the RFC: 64 bit format codes for pack() and unpack() had passed, with 100% “yes” votes.

Changes corresponding to the RFC: Catchable “call to a member function of a non-object”, which passed this summer, have been merged.

Davey Shafik reported an E_DERECATED warning is always raised, with PHP 5.6, if always_populate_raw_post_data is set to something else than -1 — and the default value is 0. It is yet the best possible compromise, with a default configuration value that doesn’t break compatibility, but also warns users this is a feature that will be removed in the future.

Following a question asked by Sebastian Bergmann, Adam Harvey set up the new Supported Versions page on php.net: it shows which versions of PHP are currently supported — and until when.

Stas Malyshev brought the RFC: Filtered unserialize() back on the stage. It aims to change the unserialize() function, so we can forbid objects unserialization, or limit them to a set of listed classes.

Miloslav Hůla wrote the RFC: Access to aliases definition by reflection, suggesting to expose namespaces aliases definitions (set up with use) to user-space, through the Reflection API.

In the middle of the month, Levi Morrison indicated he has a working implementation for RFC: Return Type Declarations and a few changes had been made to the RFC. Which means it’s likely votes will begin on this RFC soon.



internals@lists.php.net is the mailing-list of the developers of PHP; it is used to discuss the next evolutions of the language and to talk about enhancement suggestions or bug reports.
This mailing-list is public and anyone can subscribe from the page Mailing Lists, or read its archives using HTTP from php.internals or through the news server news://news.php.net/php.internals.


Par Pascal MARTIN le mardi 25 novembre 2014 4 commentaires

This post is also available in English.


809 messages ont échangés en octobre 2014 sur la mailing-list internals@ de PHP, soit un peu plus qu’en septembre.

Sous forme d’un graphique représentant le nombre de mails par mois sur les trois dernières années, on obtient :

Pour commencer, soulignons que PHP 5.6 est entrée dans son cycle de vie normal, avec la sortie de la première version de maintenance au début du mois.


Nikita Popov a rédigé la RFC: Remove deprecated functionality in PHP 7, qui propose de supprimer de PHP 7 tout ce qui a été marqué comme obsolète sur les différentes versions 5.x dont, notamment : ext/ereg, ext/mysql, l’affectation de new par référence, les fonctions de manipulation des magic_quotes, les commentaires # dans php.ini, … Du fait de l’impact que pourrait avoir la suppression des deux premiers points, il se pourrait que la RFC soit votée en trois fois (un vote pour chacun des deux premiers points et un troisième pour tout le reste).

Comme l’a souligné Kris Craig, ext/mysql, en particulier, est obsolète depuis un bon moment — et le fait que certains sites et tutoriaux continuent à y faire référence ne doit pas empêcher sa suppression. Toutefois, Rasmus Lerdorf a noté que la plupart des utilisateurs obtiennent leurs installations et extensions PHP depuis leurs distributions et que celles-ci ont tendance à packager des extensions PECL comme si elles étaient fournies directement avec PHP.

Johannes Schlüter a fait remarquer que, indépendamment de la suppression ou non de ext/mysql, il était important d’éduquer les utilisateurs pour qu’ils arrêtent d’utiliser cette extension — et Derick Rethans a ajouté que le fait que ext/mysql ait une interface procédurale n’était pas une raison suffisante pour justifier son retrait. Zeev Suraski a quant lui rappelé qu’à chaque fois qu’une fonctionnalité était cassée ou supprimée, il était un peu plus difficile pour les utilisateurs d’effectuer une mise à jour.

D’un autre côté, comme l’a indiqué Pierre Joye, si les fonctionnalités obsolètes ne sont jamais supprimées, il n’y a pas d’intérêt à les marquer comme obsolètes et on pourrait tout aussi bien cesser de le faire.


En milieu de mois, Zeev Suraski a annoncé la RFC: PHP 7.0 timeline, qui proposait de sortir PHP 7 assez rapidement (d’ici un an), quitte à se limiter un peu sur les fonctionnalités : les points cassant la compatibilité devraient nécessairement arriver pour PHP 7.0 (puisque les BC-breaks ne sont permis que pour des versions majeures), mais d’autres fonctionnalités, n’entraînant pas de BC-break, pourraient ne viser que PHP 7.1 ou 7.2. Attendre trop longtemps risquerait aussi de mener à une version apportant un grand nombre d’incompatibilités, qui nuiraient à son adoption.

Xinchen Hui a enchainé en indiquant qu’il trouvait que un an était un peu long. D’autres ont rapidement noté qu’il valait mieux ne pas aller trop vite : pas mal d’idées pourraient encore être prises en compte pour PHP 7 — même si seuls les points cassant la compatibilité doivent impérativement aller dans la version 7.0 (par contre, il ne faudrait pas en oublier, pour éviter de devoir à nouveau ré-attendre dix ans).

Comme l’a noté Rasmus Lerdorf, la branche master peut aussi demander un peu de temps avant d’être stabilisée — encore plus sur un projet avec pas mal de code legacy, comme PHP, où chaque changement peut avoir des conséquences qui ne sont pas toujours bien anticipées.


Avec l’ajout des fonctions variadiques en PHP 5.6, Marco Pivetta a proposé de marquer comme obsolètes pour PHP 5.7 les fonctions call_user_func, call_user_func_array, func_get_args, func_num_args et func_get_arg — en vue de les supprimer ensuite, pour PHP 7. Elles pourraient, au besoin, être ré-implementées en espace utilisateur, pour aide au niveau de la compatibilité des applications les utilisant.

Andrea Faulds a répondu que la possibilité de ré-implémenter ces fonctions en espace utilisateur ne signifiait pas une grosse cassure au niveau de la compatibilité des applications, qui ne fonctionneraient plus de base sous PHP 7. Supprimer ces fonctions n’apporterait d’ailleurs aucun réel gain.

D’un autre côté, l’idée de supprimer des fonctions (désormais inutiles) du cœur de PHP pour les déplacer vers l’espace utilisateur a aussi du sens… Même si ça ne serait pas nécessairement optimal niveau performances.


Après la mise en place pour phpdbg d’un nouveau protocole XML de debuggage distant, Pierre Joye a noté qu’il pourrait être intéressant de voir s’il était possible de se rapprocher du protocole DBGp déjà utilisé par Xdebug. Joe Watkins a expliqué que ce nouveau protocole avait été mis en place suite à des échanges avec les développeurs de PhpStorm. Bob Weinand a ensuite listé quelques différences entre ces deux protocoles — qui auraient peut-être pu être ajoutés à DBGp ?

Stas Malyshev a également souligné que travailler hors du projet PHP pendant plusieurs semaines avant de merger une fonctionnalité entière n’était peut-être pas la meilleure façon de procéder pour un composant intégré à PHP : plus d’échanges auraient pu avoir lieu si les développements avaient été effectués sur une branche du repository de PHP même (bon, ça n’a pas forcément été le cas par le passé — mais il en va de même pour tout PHP, dont les modifications ne sont que peu revues). Cela dit, il serait intéressant que le travail produit ici puisse servir de base au développement d’un protocole unifié de débuggage pour PHP.

David Soria Parra a ensuite fait remarquer qu’il aurait pu être profitable de passer par une RFC, pour réfléchir à l’éventuelle mise en place d’un nouveau protocole et à la solution la plus adaptée. Julien Pauli a ajouté qu’il était étrange d’avoir un site distinct pour phpdbg (ça n’est pas une habitude pour les composants de PHP) et que son contenu pourrait être déplacé vers php.net (il semblerait que ce soit prévu). phpdbg faisant partie de PHP, il devrait suivre les processus de PHP.

Quelques jours plus tard et suite à des suggestions dans le sujet de discussion précédent, Ferenc Kovacs a expliqué que les RM de PHP 5.6 avaient décidé d’annuler des modifications apportées récemment à phpdbg (support du debuggage à distance) et pas encore publiées : à partir du moment où ce composant fait partie de PHP, ses évolutions majeures peuvent demander une phase de stabilisation et elles devraient suivre le processus mis en place pour les évolutions de PHP — notamment, en passant par des RFCs. Les modifications en question ont été annulées quelques heures plus tard, en vue de revenir dans le futur de façon plus posée.


Andrea Faulds a rédigé la RFC: Big Integer Support, qui propose de mettre en place, en interne, deux types d’entiers : les entiers traditionnels (limités aux nombres pouvant tenir sur 32 ou 64 bits) et des entiers basés sur GMP, qui permettraient de manipuler des nombres aussi grands que souhaité. Ces deux types internes seraient perçus par l’utilisateur comme un unique type entier, sans limite de taille.

Stas Malyshev a fait remarquer qu’ajouter un nouveau type interne demanderait à ce qu’il soit pris en compte par toutes les extensions PHP, qui devraient donc, pour beaucoup, être adaptées.

La RFC a été mise à jour un peu plus tard pour tenir compte de problématiques de licence éventuellement posées par l’utilisation de GMP. Un benchmark a aussi été publié pour montrer que cette proposition n’avait a priori pas d’impact réel sur les performances de PHP, même si des tests plus approfondis devraient être menés.

Après environ deux semaines, les échanges sur ce sujet se sont arrêtés, sans qu’une décision ait été prise. À voir dans les prochains mois si cette RFC reviendra sur l’avant de la scène.


Joe Watkins a annoncé la RFC: UString, qui vise à mettre en place, dans PHP, une nouvelle classe UString, qui disposerait du gros de ce qui est nécessaire pour manipuler des chaînes Unicode. En somme, cette classe UString viendrait en quelque sorte prendre la place de l’extension mbstring existante, qui n’est pas parfaite, avec une implémentation basée sur ICU (déjà utilisée par Intl), plus rapide que celle de mbstring.

Les premiers retours ont été plutôt positifs. Pierre Joye a ajouté qu’il serait bon que cette extension soit systématiquement activée, de manière à faciliter son adoption.

Dmitry Stogov a noté que si cette proposition n’incluait pas l’utilisation d’objets UString au sein du moteur ou pour d’autres extensions, elle était incomplète et ne répondrait pas à tous les besoins (par exemple, des chaînes unicode ne pourraient pas être utilisées comme clefs de tableaux, puisqu’il s’agirait d’objets et pas réellement de chaînes de caractères — sauf si une autre idée évoquée il y a quelques temps était acceptée). Bien sûr, comme l’a souligné Johannes Schlüter, une meilleure approche serait un véritable Unicode, mais PHP 6 a montré que ce n’était pas si facile.


Dans le fil de discussion précédent, Stas Malyshev a annoncé qu’il avait commencé à travailler sur la RFC: Objects as hash keys, qui propose qu’une nouvelle méthode magique (__hash() ou __toKey() par exemple) permette à des objets d’être utilisés comme clefs de tableaux.

Joe Watkins a répondu en suggérant que __toScalar() pourrait être un nom adapté, plus proche de ce que ferait effectivement cette méthode, sans se limiter au contexte actuellement discuté — mais ce nom n’expliquerait pas l’utilité de cette méthode.

Alexander Lisachenko a suggéré qu’utiliser une interface pour cela pourrait également être une bonne idée, au lieu d’ajouter une nouvelle méthode magique — même si la méthode magique serait plus dans la façon de faire de PHP.

Etienne Kneuss a fait remarquer que cette proposition ne visait en fait pas à véritablement utiliser des objets comme clefs de tableaux (ce qui demanderait de ré-écrire toute la gestion de HashTables de PHP), mais uniquement à simplifier quelques écritures. Et donc, foreach, key() ou array_keys() ne retourneraient pas un objet, mais uniquement son hash, tel que calculé par cette nouvelle méthode.


Andrea Faulds a rédigé la RFC: Readonly Properties, qui part du constat qu’il est aujourd’hui difficile de rendre une propriété lisible depuis l’extérieur d’une classe, sans pour autant la rendre accessible en écriture en même temps : il faut mettre en place des getters/setters et/ou jouer avec __get/__set (dans les deux cas, ça demande d’écrire du code, c’est peu efficace, … ). Pour répondre à cette problématique, il est proposé d’ajouter un nouveau mot-clef readonly, qui pourrait être employé sur les propriétés de classes, pour indiquer qu’elles doivent être accessibles depuis l’extérieur de celles-ci.

Rowan Collins a noté que cela permettrait de rapprocher les objets en espace-utilisateur de ceux exportés par certaines extensions (qui peuvent avoir des propriétés en lecture-seule) — et il serait effectivement agréable de ne plus avoir à écrire de nombreuses lignes de codes pour obtenir cette fonctionnalité. D’autres sont allés jusqu’à suggérer une gestion d’accès plus fine, avec une syntaxe du style var $callback as rwxrw---x;.

D’un autre côté, comme l’a fait remarquer Jordi Boggiano, il pourrait être préférable de re-débattre de la RFC: Property Accessors Syntax, qui allait plus loin, tout en permettant ce qui est proposé ici — qui ne répond qu’à une partie des besoins. Nikita Popov a aussi noté que le mot-clef readonly n’était pas forcément clair et que là où des méthodes getters pouvaient faire partie d’une interface, ce ne serait pas possible pour des propriétés. Peut-être qu’une possibilité serait de réserver dès maintenant la syntaxe permettant de mettre en place des accesseurs, tout en n’en implémentant qu’une partie pour l’instant ?

Finalement, Andrea Faulds a retiré cette RFC, qui était un peu confusante et ne répondait qu’à une partie des besoins.


Kris Craig a demandé pourquoi PHP disposait des variables super-globales $_GET et $_POST mais pas de $_PUT ni $_DELETE, qui pourraient être utiles dans le cas de développement d’APIs REST.

Comme l’a rapidement signalé Andrea Faulds, ces deux premières variables sont déjà mal nommées : $_GET correspond aux paramètres reçus par le biais de la query-string et $_POST contient les données du corps de la requête — ou alors, il faut considérer qu’elles correspondent aux méthodes de formulaires et non aux primitives HTTP. En pratique, passer à des variables comme $_QUERY, $_BODY et $_REQUEST pourrait avoir du sens, mais briserait complétement la compatibilité. D’un autre côté, Rasmus Lerdorf a fait remarquer que les utilisateurs savaient comment utiliser $_GET et $_POST et que vouloir ajouter des alias était peut-être aller un peu loin : de tout ce qui peut être source de confusion en PHP, ce point serait vers le bas de la liste.

Michael Wallner a alors souligné qu’il pouvait être intéressant de jeter à un coup d’œil à l’extension pecl_http ainsi qu’à la RFC: Add pecl_http to core.

La discussion a été intense, avec pas loin d’une centaine de mails en quelques jours, mais je n’ai pas le sentiment qu’elle ait mené à une décision. En tout cas, $_GET et $_POST ne sont pas prêt de disparaître — mais nous verrons peut-être apparaître de nouveaux alias dans le futur…


Quelques jours plus tard, Sherif Ramadan a annoncé avoir commencé à travailler sur la RFC: Standardized PHP Http Interface.

Florian Margaine a commencé par répondre que PHP devrait plus fournir des implémentations que des interfaces : libre à l’espace utilisateur de déterminer à quoi le code devrait ressembler. Supprimer les super-globales ($_GET, $_POST, …) casserait aussi quasiment toutes les applications existantes et nuirait fortement à l’adoption de PHP 7 — même si elles ne sont pas l’interface la plus parfaite qui soit.

D’un autre côté, les variables GPC ne sont pas réellement parfaites et une interface intégrée à PHP pourrait unifier un peu la façon dont chaque framework fournit une classe HttpRequest différente de celle des autres frameworks.

Larry Garfield a en parallèle rappelé qu’il y avait pas mal de discussions autour de ce sujet sur la mailing-list du FIG et que l’espace utilisateur était probablement plus adapté à ce type d’expérimentations.


Andrea Faulds a annoncé la RFC: Safe Casting Functions, qui partait du constat que les opérateurs de transtypage existant, explicites, n’échouent jamais et ne lèvent jamais d’erreur — ce qui peut être dangereux (surtout s’ils sont utilisés sur des saisies utilisateurs), puisqu’ils retourneront un peu n’importe quoi si les données sur lesquelles on les utilise correspondent elles-mêmes à un peu n’importe quoi.

Cette RFC proposait donc d’ajouter trois fonctions, qui valideraient leur entrée, au lieu de transtyper aveuglément :

  • to_int() : n’accepterait que des entiers, des flottants contenant des entiers et pouvant être représentés par des entiers, ou des chaînes contenant la représentation textuelle d’entiers.
  • to_float() : n’accepterait que des flottants, des entiers et des chaînes représentant des flottants.
  • et to_string() : n’accepterait que des chaînes, des entiers, des flottants et des objets transtypables en chaînes.

La question de la valeur de retour de ces fonctions s’est rapidement posée (typiquement, est-ce que false est une valeur ?), de même que l’idée de leur faire lever des exceptions — ce qui pourrait dépendre d’un paramètre optionnel.

Stas Malyshev a souligné que des règles de validation existaient déjà dans l’extension ext/filter et qu’il faudrait peut-être enrichir celle-ci plutôt que d’ajouter un autre jeu de règles ailleurs. Utiliser des noms comme to_int() pourrait être source de confusion pour les utilisateurs, puisque le comportement ne serait pas le même que celui de (int) et un nom comme lossless_int() pourrait être plus adapté.

Les discussions n’étaient pas terminés en fin de mois et j’imagine que le sujet continuera sur le mois prochain ;-)


Nikita Popov a relancé la RFC: Exceptions in the engine, qui avait initialement été proposée pour PHP 5.6 — toutes les erreurs ne seront pas transformées en exceptions, mais une majorité le pourrait. Comme précédemment, les retours ont été plutôt positifis.

Thomas Gossmann a demandé s’il était possible de supprimer le mot-clef function des déclarations de méthodes. Levi Morrison a rapidement indiqué que cette idée avait été rejetée par le passé, typiquement parce qu’elle rendrait plus difficile la lecture du code et la recherche de définitions — sans pour autant apporter grand chose au langage. Il n’est d’ailleurs pas le seul de cet avis.

Les votes ont été ouvert sur la RFC: loop + or control structure. Avec 4 votes “pour” et 11 votes “contre”, elle n’est pas passée — Leigh, auteur de cette RFC, a expliqué pourquoi lui-même avait fini par voter contre. À voir si le sujet mérite que quelqu’un prenne la suite dans quelques temps.

Leigh a annoncé que la RFC: 64 bit format codes for pack() and unpack() était passée, avec 100% de votes “pour”.

Les modifications liées à la RFC: Catchable “call to a member function of a non-object”, qui était passée cet été, ont été mergées.

Davey Shafik a fait remarquer qu’une E_DERECATED était systématiquement levée, avec PHP 5.6, si always_populate_raw_post_data était configuré à une autre valeur que -1 — et la valeur par défaut est 0. Il s’agit cependant du meilleur compromis possible, avec une valeur de configuration par défaut qui ne casse pas la compatibilité, tout en avertissant les utilisateurs qu’elle correspond à une fonctionnalité qui sera supprimée dans le futur.

Suite à une question de Sebastian Bergmann, Adam Harvey a mis en place la nouvelle page Supported Versions sur php.net, qui indique quelles sont les versions actuellement supportées de PHP — et jusqu’à quand.

Stas Malyshev a remis en avant la RFC: Filtered unserialize() qui proposait de modifier la fonction unserialize() de PHP pour permettre d’interdire la dé-sérialisation d’objets ou de limiter celle-ci à un ensemble de classes listées.

Miloslav Hůla a rédigé la RFC: Access to aliases definition by reflection, qui propose d’exposer à l’espace utilisateur les définitions d’alias d’espaces de noms (obtenus avec use), par le biais de l’API de Reflection.

En milieu de mois, Levi Morrison a annoncé qu’il disposait d’une implémentation fonctionnelle pour la RFC: Return Type Declarations et que quelques petites modifications y avaient été apportées. Il est donc probable que les votes soient bientôt ouverts sur cette RFC.



internals@lists.php.net est la mailing-list des développeurs de PHP ; elle est utilisée pour discuter des prochaines évolutions du langage, ainsi que pour échanger autour de suggestions d’améliorations ou de rapports de bugs.
Elle est publique, et tout le monde peut s’y inscrire depuis la page Mailing Lists, ou consulter ses archives en HTTP depuis php.internals ou depuis le serveur de news news://news.php.net/php.internals.


Par Pascal MARTIN le mercredi 12 novembre 2014

J’ai posté il y a quelques jours les notes que j’ai prises lors des conférences auxquelles j’ai assisté pendant le premier jour du ForumPHP 2014 à Paris.

Dans la suite de ce premier article, voici, encore dans l’ordre chronologique, mes notes du second jour. Notez encore une fois qu’il s’agit de mes notes, soumises à mon interprétation de chaque intervention.

Les slides de la quasi-totalité des conférences sont disponibles en ligne (sur joind.in ou ce gist) et les vidéos captées lors de l’événement vont peu à peu être diffusées par l’AFUP sur youtube.


Frameworks: A History of Violence

François ZANINOTTORésumé, Slides, Vidéo

Pour nous mettre dans l’ambiance dès le départ, François a rappelé que symfony, en 2006, c’était bien… Alors qu’en 2011, plus autant que ça : les besoins des applications web se sont complexifiés. En somme :

  • En 2000, tout le monde voulait son framework : c’était une vraie maladie dans notre communauté ! En même temps, c’était un peu le moment de PHP 4, où personne n’utilisait autre chose que C++ ou JAVA. À ce moment là, un framework jouait un peu un rôle de cadriciel et d’ensemble de classes : PEAR était ce qui s’approchait le plus d’un framework PHP.
  • 2005 : arrivée des design patterns : on arrête de ré-inventer la roue. L’open-source commence à monter.
  • 2007 : PHP contre attaque, avec des logiciels (drupal, wikimedia, …), le début d’applications en PHP du type de celles qu’on développait auparavant avec d’autres technos (symfony et zend framework jouant), débuts d’Ajax (et prototype.js pour sa démocratisation)
  • 2010 : les entreprises disent “oui” : injection de dépendances, meilleur niveau d’abstraction, y compris pour les frameworks. Amélioration de l’interopérabilité avec PSR-0, composer et l’autoloading qui permettent de prendre des morceaux ici et là. Les entreprises ont validé l’utilisation de PHP. Et c’est aussi le moment où le geek est devenu sexy.
  • 2012 : l’arrivée du cloud change la donne de l’hébergement. Il faut répondre au quoi plus qu’au comment. Le gros du développement se fait sur mobile (Objective C ou JAVA) avec du typage fort. Apache / PHP / MySQL ne sont plus trop adaptés et les développeurs regardent ailleurs. Les frameworks ont souffert des manques du langage.
  • 2017 : phpng, Hack et Zephyr ont apporté, entre autres, de l’asynchrone. L’innovation se fait sur d’autres langages qui ont une plus grande vitesse de développement. La logique est déportée côté navigateur.
  • 2020 “aujourd’hui” : Go ou JS, micro-frameworks et services, plus d’approche full-stack.

En somme, les frameworks, c’est bien quand ils sont petits ! L’approche full-stack est utile seulement le temps que la communauté devienne mature — et quand une application grandit, il devient temps de découpler. Au final, le langage s’enrichit de primitives qui permettent de se passer des frameworks.

En même temps, les frameworks ne meurent jamais. Vu le nombre d’applications qui les utilisent, il faudra 10 ans pour qu’ils disparaissent et il faudra toujours des développeurs PHP comme il faut aujourd’hui des développeurs COBOL. Les frameworks subissent aussi la sélection naturelle : ils reprennent les idées des autres, s’affrontent (si un framework n’est plus adapté, il ne sera pas utilisé sur un nouveau projet). Dans cinq ans, nous n’utiliserons plus les frameworks actuels et le framework qui sera le plus utilisé dans cinq ans n’est pas encore né. Les frameworks innovent de façon incrémentale, avec des innovations de rupture qui mènent à un rythme de croisière plus rapide. Mais les frameworks les plus populaires sont ceux qui évoluent le moins vite, puisque les utilisateurs veulent garder la compatibilité !

Les frameworks sont là pour pallier les manques des langages… qui, au bout d’un moment, intègrent les fonctionnalités initialement proposées par ceux-ci. Par exemple, HTML 5 a intégré des points de jQuery. Cela dit, les frameworks un peu anciens se basent sur des vieilles versions du langage. Finalement, pourquoi ne pas développer en node, plutôt que de passer par ReactPHP ?

À prendre aussi en compte : les frameworks pro, avec une entreprise derrière, ont une forme de vendor lock-in. Même si la communauté intervient, il y a une entreprise, qui fait du support, de la formation. Et, finalement, la simplicité d’utilisation peur être contraire aux intérêts de l’éditeur.

En conclusion, le programme du parti de l’innovation :

  • Le domaine d’abord. Arrêter de structurer le code en fonction d’un framework !
  • Non au full-stack. Privilégier les micro-frameworks.
  • Applications plurielles. Mélanger les langages et les frameworks, être à l’écoute.
  • Repenser le temps. Apprendre plein de langages, passer un jour par mois pour se former. C’est le plein emploi, c’est le moment de négocier avec les patrons !

Mon avis : Commencer cette seconde journée par une conférence animée, un peu en mode discours politique, était parfait pour le réveil après l’apéro communautaire de la veille ! L’idée que les frameworks (en particulier full-stack) sont là pour pallier les manques du langage en attendant que celui-ci les rattrape est intéressante — même si le langage, comme les frameworks, va subir la logique du plus il est populaire moins il évolue vite pour éviter de casser la compatibilité.


Bringing Sculpin to Life

Beau SIMENSENRésumé, Slides, Vidéo

Pour cette conférence, Beau nous a raconté l’histoire de comment un projet open-source (Sculpin, un générateur de site statique) est né, from-scratch.

Tout est parti des beer & code Seattle, qui ont permi à Beau de rencontrer des membres de la communauté, de sortir de sa bulle. Cet événement avait besoin d’un site web, dont la première version a été mise en place sous Jekyll, rapidement suivie d’une question “est-ce qu’il existe pareil en PHP ?”.

Ensuite, pas mal de temps a été passé à recoder des trucs, y compris un peu comme une couche de framework (NIH), au lieu de bosser sur des applications en elles-mêmes. Utilisation de symfony2 et de composants prometteurs, PHP 5.3 et espaces de noms aidant pour l’organisation du code, malgré le \ qui a causé quelques hésitations quand à l’avenir avec PHP.

Après deux ou trois sites sous Jekyll mettant en évidence une expérience de développement pas top (Ruby et trucs bizarres des développeurs Ruby), essai d’Octopress et contributions sur Jekyll et Octopress — en appréciant l’idée que le code n’a pas besoin d’être exécuté pour chaque requête (vu que sites statiques).

Pour ce qui est de PHP, sur d’autres projets, utilisation de Silex (symfony ayant un peu trop d’overhead et demandant d’apprendre trop de choses) distribué en Phar, sans avoir à se soucier de dépendances. Puis écriture d’un vendor.sh pour récupérer les dépendances, rapidement remplacé par Composer, en notant que c’est l’avenir de PHP !

Finalement, avec un sentiment de meh sous Jekyll et Octopress (incluant des absences de réponses pendant longtemps sur des PR pour finalement les voir être closes), s’est posée la question de pourquoi ne pas faire un générateur de site statique en PHP ? (il en existait quelques uns, mais basés sur PEAR ou avec une architecture bizarre). Une fois passée la difficulté de trouver un nom, 1er commit sur Sculpin le 21/12/2011 : basé sur Composer et publiant des bibliothèques, utilisation de composant symfony, intégration de React pour disposer d’un serveur web intégré.

Au niveau de la communauté : rencontre de gens (y compris rencontre IRL de développeurs précédemment vus uniquement en ligne), participation à des hack-days… Pour aller jusqu’à déménager depuis le milieu de nulle part vers une zone plus propice aux rencontres. Ensuite, participation à des conférences (avec plein de rejets lors de la première soumission de sujets). Important aussi de parler du projet, malgré les réactions parfois peu encourageantes du type “tu refais juste un CMS, y’a pas de raison d’en parler”.

En conclusion, créer un projet open-source, ce n’est que le début ; après, il y a la maintenance ! Et quelques enseignements :

  • Ré-inventer la roue, ce n’est pas toujours mal,
  • La crainte du rejet par la communauté freine les choses ; beaucoup. Il est important d’essayer ce qui existe, mais il ne faut pas se sentir mal de refaire si l’existant n’est pas OK.
  • Il faut trouver et connaître ses raisons pour justifier ce qu’on fait.
  • Il est primordial de faire ce qui est fun pour nous ! Et de build what you can use.
  • Communauté ! Parler ! En face, sur Twitter, sur IRC, …
  • PHP est flexible. Voir par exemple React. Ce n’est pas parce qu’un autre langage fait bien quelque chose que PHP ne peut pas le faire.
  • Et pour finir : faites les choses !

Mon avis : Je pensais, avant le Forum, que cette conférence présenterait Sculpin. Ayant discuté la veille au soir du sujet avec Beau, je n’ai finalement pas été surpris ni déçu de plutôt entendre l’histoire derrière le projet. Un retour intéressant pour ceux qui se demanderaient comment un projet open-source peut se lancer. La notion de crainte du rejet me semble également importante, dans une communauté où les retours et jugements sont parfois un peu brutaux et pas toujours très diplomates (sans compter qu’ils sont parfois exprimés sans que leurs auteurs n’aient toujours pris la peine de bien comprendre le sujet…)


VDM, DevOp malgré moi

Maxime VALETTERésumé, Vidéo

Maxime a commencé par se présenter, en indiquant qu’il avait débuté en BASIC à 7 ans, pour faire comme papa, à grand coups de RTFM, avant d’obtenir son premier boulot chez Team AAA après avoir trouvé une faille dans leur site.

VDM est né un peu par hasard, sous la forme d’un blog perso — et ses deux utilisateurs recevaient occasionnellement des mails de gens qui voulaient ajouter leurs histoires, ce qui a entraîné l’ajout d’un formulaire de soumission. Au bout de quelques temps, à 10k visites par jour et un passage dans TéléMatin, ça a été le début de la fin : le site est tombé. Ça a été l’occasion de le revoir un peu, de passer au design en deux colonnes qu’il a encore aujourd’hui… Et avec 3000 à 4000 VDM proposées par jour, les week-ends étaient passés à modérer.

Passage dans le Grand Journal ⇒ 185k visites/jour. Travail sur FML en parallèle ⇒ succès à l’américaine avec 1M visites/jour. Plus le livre en français, qui a fait 1M ventes. Avec 250k visites de plus toutes les semaines, la question qui se pose rapidement est “comment gérer ça sans que ça s’écroule” — et la réponse “comme on peut !”

En termes système, hébergement chez OVH (rapide pour obtenir de nouvelle machines — et on prend ce qu’on sait faire), avec un round-robin DNS et du cache. Ajout ensuite de nouveaux serveurs Web et DB (réplication) et NFS et DNS pour arriver jusqu’à 7 serveurs MySQL. Puis mise en place d’un CDN, surtout pour les US (puisque les serveurs sont en France). Pour le monitoring, ça a commencé par des scripts qui pingaient pour voir si tout était up et qui téléphonaient à Maxime en cas de problème.

Au niveau du code, beaucoup de legacy en programmation procédurale, plusieurs années sont passées avant de basculer de mysql_*() vers PDO. L’internationalisation, au début, n’avait pas été prévue et le site était copié en entier pour chaque traduction. Le déploiement s’est pendant un bon moment fait par webdrive, avec montage de disque réseau et édition comme ça (ce qui entraînait des disparitions de fichiers, des fichiers écrits à moitié, …). Et le framework utilisé était l’adrénaline ! Aux moments avec un peu moins de rush, quelques améliorations ont été apportées, comme passer par des fichiers de langue ou un routeur PHP.

Finalement, une série d’évolutions ont été apportées, dont, notamment :

  • Passage à Git et mise en place d’un environnement de staging.
  • Apparition de code objet
  • MySQL en master / slave (au lieu de réplication circulaire).
  • Mais aussi : HAProxy, Heartbeat, Nagios, statsd, Sentry, utilisation de nginx pour le plus gros des requêtes, Redis au lieu de memcached pour les caches (x2 sur les perfs), CDN chez OVH

Aujourd’hui, les différents sites, cumulés, en sont à 3M visites/jour et 20,000 requêtes MySQL par seconde.

En conclusion, quelques points :

  • Du bon code rapporte de l’argent et tient la charge : il s’agit d’un équilibre entre les deux.
  • Un bon devops équilibre ses tâches et reste pragmatique.
  • Un bon entrepreneur voit le futur.
  • Est-ce qu’une refactorisation globale du code est prévue pour l’avenir ? Il est probable que ce ne soit jamais fait, pas besoin.

Mon avis : J’ai beaucoup aimé l’approche très terre-à-terre on fait avec les moyens du bord, qui reflète plutôt bien l’histoire de PHP, ainsi que l’idée que le bon code représente un équilibre — et pas du code parfait !


An introduction to the Laravel Framework for PHP.

Dayle REESRésumé, Slides, Vidéo

En 2011, Dayle a commencé par utiliser Code Igniter, à l’intégrer sur de petits projets, ainsi qu’à y contribuer. Il a ensuite basculé sur Laravel 2.x, pour ses aspects clean, simple, qui changeaient de beaucoup d’existant en PHP. En parallèle, implication dans la communauté, sur IRC, ainsi qu’à travers l’écriture de tutoriaux.

Au moment de Laravel 3, il a commencé à participer plus activement au niveau du framework, malgré quelques problèmes au niveau du testing et l’extensibilité. Rappel : OSS = friendship.

La fin de la conférence à très rapidement évoqué quelques points intéressant de Laravel 4, initialement basé sur Silex, utilisant Composer et basé sur des composants. Cette version du framework effectue de la résolution automatique de composant, notamment par le biais de type-hinting — et on y retrouve bien sûr toute une série de fonctionnalités classiques existant dans d’autres frameworks.

Mon avis : J’espèrais avoir un aperçu technique de Laravel, qui a pas mal de succès aux US et UK et que je n’ai pas pris le temps de découvrir par moi-même… Mais trop de temps a été consacré à l’introduction de la conférence, pour ne finalement passer que beaucoup trop rapidement sur le framework.


Design how your objects talk to each other through mocking

Konstantin KUDRYASHOVRésumé, Slides, Vidéo

Konstantin a commencé sa présentation en soulignant que les tests que l’on utilise parfois comme exemples (comme tester le résultat d’une multiplication) sont souvent simples et pas forcément proches du monde réel : dans monde réel, il existe des interactions et des dépendances entre plusieurs composants. De plus, en général, on teste le résultat final et pas la façon dont on y est arrivé — en conséquence, que se passe-t-il si le comment impacte le design ?

On arrive donc à une question : est-ce que c’est le message qui est important ? Ou l’état ? Considérant que l’idée derrière la programmation objet est de cacher l’état autant que possible, ce qui compte, ce sont les échanges !

En fonction des besoins, on peut mettre en place plusieurs formes de test doubles (qui constituent des solutions permettant d’isoler des choses — et même s’ils rendent souvent plus rapide l’exécution des tests, ce n’est absolument pas leur but premier) :

  • Dummy : uniquement pour passer les type-hints, ne fait rien.
  • Stub : une méthode avec des paramètres retourne une résultat pré-défini. Pas de vérification sur le fait qu’elle soit ou non appelée.
  • Spy : on vérifie que l’appel ait effectivement été effectué.
  • Mock : forme de Spy avec un délai.
  • Fake : implémentation réelle de la classe.

Souvent, les développeurs ne mettent pas en place de test unitaire sur les contrôleurs. L’exemple de test sur contrôleur présenté à ce moment montre qu’on a plus de 10 objets différents utilisés par celui-ci, ce qui n’est pas idéal pour le Single Responsibility Principle. En ré-écrivant le test, on arrive à deux fois moins de classes et de lignes de code — en enlevant la complexité qui se trouvait dans le contrôleur et en la déplaçant vers le Model, le Repository, …

Viennent ensuite une série de principes :

  • Open-Closed Principle : typiquement, sur un test de panier, lorsqu’on ajoute un mode de paiement, on ne devrait pas avoir à modifier le code du panier.
  • Liskov substitution principle : on veut pouvoir remplacer une classe par une autre et que ça marche (passer par des classes différente avec un adapteur pour les utiliser).
  • Interface segregation principle
  • Dependency injection principle

Il est important de ne pas mocker de composants dont on n’est pas propriétaire. Et exposer les communications !

Et quelques notes pour terminer :

  • Ne pas utiliser d’outil de mock cassé : passer par Mockery ou Prophecy
  • Ne pas faker de Value Object ou de Collection : les utiliser. Pareil pour les parties d’objets, en les découplant.
  • Ne pas utiliser de mock pour isoler.
  • Le TDD centré sur l’état n’est pas la seule possibilité.
  • Les messages sont plus importants que l’état : ils définissent le comportement des objets. Et en se focalisant sur les échanges de messages, on expose des problèmes de messages.

Mon avis : L’idée de tester les messages et les échanges plus que les états est intéressante (surtout considérant qu’on fait bien trop souvent l’inverse) et demande d’être creusée — je regarderai probablement quelques passages de la vidéo un de ces jours pour me remettre dedans (je commençais à penser à la table ronde que j’allais animer même pas deux heures après et, conséquence, j’ai décroché plusieurs fois pendant cette conférence :-( ).


Cohabitation de PHP et Node au Monde, pourquoi et comment

Olivier GRANGE-LABATRésumé, Slides, Vidéo

Olivier a commencé par rappeler que nodejs permet de développer en Javascript côté serveur, que ce soit pour du scripting (bower, grunt, …) ou pour mettre en place des serveurs (statsd, …).

Deux besoins chez Le Monde :

  • Refonte des alertes sur applications mobiles (+ de 1M de devices), qui étaient en PHP avec quelques problèmes de performances — et puisque les média veulent tous être le 1er sur les alertes, un rework était nécessaire.
  • Refonte du CMS interne (utilisé par les journalistes pour écrire leurs articles) : les outils éditoriaux existant étaient vétustes, il fallait rapprocher le print et le web (avec un outil unique pour toute la rédaction) et les performances étaient à améliorer ⇒ architecture SPA, angular, postgresql, PR pour tout.

Pourquoi nodejs sur le projet CMS ?

  • Même paradigme côté client et serveur
  • Temps réel → notifications, collaboration, chat, …
  • Bien pour fabriquer une API
  • Compétences existantes en interne + techno sympa qui aide à recruter.

Avantages :

  • Javascript partout, y compris pour le déploiement
  • Partage de quelques bibliothèques entre client et serveur (quelques unes — pas tant que ça non plus)
  • npm = excellent packager
  • modules simples, qui ne font qu’une seule chose
  • stabilité
  • déploiement très simple : nvm + npm (avec déploiement de node qui se fait automatiquement)
  • documentation complète et à jour

Quelques aspects moins sympa :

  • Asynchrone = difficile à appréhender (même avec async pour éviter le callback-hell)
  • Approche serveur plutôt que requête qui impose de redémarrer pendant les livraisons ou de gérer les exceptions pour éviter que l’application ne s’arrête
  • superviser la mémoire (risques de fuites)
  • écosystème immature (même si ça s’améliore)
  • problématiques bas niveau (fork)

Prochaine question qui va se poser : quid de la prochaine version du site web ? En SPA ? Problématiques de performances sur les navigateurs mobiles ? Ou sous forme d’applications ? Peut-être une API d’accès aux données en node avec du PHP et des web components. Dans tous les cas, pivoter autour des données pour mettre en place une nouvelle stack.

En conclusion : on est développeur avant d’être développeur PHP : les technos ne sont que des outils et il faut apprendre d’autres technos.

Mon avis : Un rapide tour sur les points que node aborde différemment que PHP et une illustration du fait qu’un langage n’est pas la solution à tous les problèmes, mais juste un outil. J’ai toutefois plus eu le sentiment d’une bascule d’une techno vers une autre que d’une réelle cohabitation ?


Table ronde “État des lieux et avenir de PHP”

Pierre JOYE, Julien PAULI et Jordi BOGGIANORésumé, Vidéo

Étant animateur de cette table ronde, je n’ai pas été en mesure de prendre de note.

Jordi, Julien et Pierre ont eut l’occasion de répondre à plusieurs questions posées par des membres du public, sur l’état de PHP aujourd’hui, sur la communauté au sens large et ses besoins, ainsi que sur les possibles évolutions du langage et la manière dont celles-ci pourraient arriver.

Mon avis : C’était la première table ronde que j’animais, j’étais assez curieux de voir comment ça allait se passer — et j’ai le sentiment que nous avons réussi à répondre à pas mal d’interrogations. 45 minutes à trois intervenants, par contre, ça passe vraiment vite !


Pour conclure, ces deux jours de Forum PHP ont été pour moi l’occasion d’assister à une petite quinzaine de conférences, d’avoir le plaisir de rencontrer ou de revoir pas mal de monde, de discuter de PHP, de sa communauté, de différents projets, ou même de mon livre, ainsi que d’animer ma première table ronde — deux journées bien chargées, donc !

Encore une fois, merci à l’AFUP, à tous les membres de l’orga, aux conférenciers et au public — et à l’année prochaine !