X

Les petits goodies souvent méconnus de Laravel


Je parlais d’un problème d’architecture particulier avec Taylor Otwell et je lui ai montré un code sans rapport à titre d’exemple. Il a interrompu notre conversation pour qu’il puisse me montrer une refonte rapide, et m’a carrément embarrassé, alors j’ai dû le partager avec vous, chers lecteurs.

Voici mon code. J’écris ces petits microservices tout le temps – ils s’assoient simplement devant un autre service et le mettent en cache. C’est ça. Parfois, je modifie la sortie ou les en-têtes, parfois je croque certaines choses ou mutile d’autres. Mais la forme la plus simple consiste simplement à mettre en cache un service lent ou peu fiable.

<?php // routes.php

class fakeApiCaller
{
    public function getResultsForPath($path)
    {
        return [
            'status' => 200,
            'body' => json_encode([
                'title' => "Results for path [$path]"
            ]),
            'headers' => [
                "Content-Type" => "application/json"
            ]
        ];
    }
}

Route::get('{path?}', function($path)
{
    $cacheLengthInMinutes = 60;
    $headersToPassThrough = [
        'Content-Type',
        'X-Pagination'
    ];

    if (Cache::has($path)) {
        $result = Cache::get($path);

    } else {
        $myCaller = new fakeApiCaller;

        $result = $myCaller->getResultsForPath($path);

        Cache::put($path, $result, $cacheLengthInMinutes);
    }

    // Pass through specified headers
    $headers = [];

    foreach ($headersToPassThrough as $header_name) {
        if (array_key_exists($header_name, $result['headers'])) {
            $headers[$header_name] = $result['headers'][$header_name];
        }
    }

    return response($result['body'], $result['status'], $headers);
})->where('path', '.*');

C’est clair, et je me sentais plutôt bien de ne pas perdre trop de temps ou de code. Un peu long, oui, mais peu importe.

Et puis Taylor a renvoyé ceci :

<?php // routes.php

class fakeApiCaller
{
    public function getResultsForPath($path)
    {
        return [
            'status' => 200,
            'body' => json_encode([
                'title' => "Results for path [$path]"
            ]),
            'headers' => [
                "Content-Type" => "application/json"
            ]
        ];
    }
}

$app->get('{path?}', function($path)
{
    $result = Cache::remember($path, 60, function() use ($path) {
        return (new fakeApiCaller)->getResultsForPath($path);
    });

    return response($result['body'], $result['status'], array_only(
        $result['headers'], ['Content-Type', 'X-Pagination']
    ));
})->where('path', '.*');

Cela profite de plusieurs choses que la mienne n’a pas fait.

Il a d’abord utilisé $cache->remember(), qui était une fonctionnalité de Laravel dont je ne connaissais même pas l’existence. Rappelez-vous est pour exactement ce que je fais, donc cela simplifie le processus de dire “Donnez-moi la valeur de X, et si cela n’a pas encore été défini, récupérez-le de Y, puis cachez-le à X et renvoyez-le.”

Deuxièmement, il a découvert le fakeApiCaller en ligne, ce qui signifie qu’il n’avait pas besoin d’une ligne de rechange pour cela alors que nous ne l’utilisions qu’une seule fois.

Troisièmement, il a passé le $cacheLengthInMinutes directement à Cache::remember. L’utiliser ou non dépend de la familiarité de votre équipe (et des futurs développeurs potentiels) avec Laravel. Le simple fait d’avoir un nombre là-bas pourrait être déroutant, donc si vous anticipez des problèmes là-bas, extrayez simplement le 60 en tant que variable comme $cacheLengthInMinutes.

Quatrièmement, il a utilisé Laravel’s array_only syntaxe pour extraire facilement uniquement les éléments du tableau de $result['headers'] qui correspondait à mon tableau “pass-through souhaité”. Encore une fois, si vous avez des gens qui ne sont pas habitués à array_onlyvous pouvez extraire le deuxième paramètre vers un $headersToPassThrough variable.

Concludadore

Donc, vous regardez peut-être ce dicton : “Matt, vraiment ? Ce n’est pas si différent !” Et vous avez raison. Mais pour moi, profiter de petits outils et aides – par exemple, j’ai été absolument amoureux de array_walk ces derniers temps – dans vos plus petites lignes de code est un aspect énorme d’être un programmeur clair et concis. Si vous êtes fidèle dans les petites choses…

Je passe tellement de temps au plus haut niveau que je rate beaucoup d’occasions de m’améliorer en tant que programmeur ligne par ligne dans les tranchées. Ça me manque et j’en ai besoin, c’est (en partie) pourquoi j’ai tant de projets parallèles. Et de petites occasions comme celle-ci pour améliorer la qualité et la concision (mais pas l’intelligence !) de mon code me procurent une grande joie.

En passant, mon ami Zack Kitzmiller a re-partagé le Zen of Python, que j’ai lu plusieurs fois mais que j’ai l’impression de devoir tatouer sur mes avant-bras.