Mieux collaborer avec l’équipe passe par multitude de petites choses, commençons par s’intéresser aux « todo ».

Cet article est un partage d'expérience qui met en avant l'utilisation des « todo » dans un projet Sylius.
Sylius est une solution e-commerce Open Source basée sur Symfony.

Le passage de relais aux travers des diverses étapes d’un projet web est toujours délicat. Une communication efficace et de bons process sont essentiels pour une réalisation réussie.
L’idéal est d’exploiter au mieux les compétences et forces de chacun tout au long du projet. C’est ce dont on va parler dans cet article, avec un focus sur la relation de travail entre développeurs front et back.

Récemment je lisais un article que vous conseille : The Hot Potato Process dans lequel il est expliqué que le travail entre le designer et développeur devrait suivre un schéma collaboratif plutôt qu’un passage de relais.

Waterfall vs Hot Potato © Dan Mall

Si selon la nature du projet cette approche est plus ou moins évidente, elle est très facilement transposable à une équipe de développeurs et notamment dans le cas d’un échange entre développeurs front et back.

Dans le thème de cette relation entre développeurs front et back, je vais spécifiquement vous parler d’un petit détail qui nous aide bien chez Monsieur Biz : les « todo visuelles ».

Exemple de todo visuelle

Lors de l’écriture de code d’un projet PHP, si l’ensemble des fonctionnalités ne sont pas couvertes dans l’immédiat, l’on va recourir à un @todo [description] en commentaire du bloc de code. Cela permet de documenter au mieux le projet directement au coeur de ce dernier.

Les « todo visuelles » reposent sur un principe similaire, mais s’appliquent au code HTML et permettent de visualiser ces dernières directement depuis le navigateur. Non seulement le développeur back pourra visualiser simplement le travail restant, mais également l’ensemble de l’équipe si un espace de pré-production est déployé régulièrement.

Prenons le cas d’un développement d’un site e-commerce reposant sur Sylius. Le développeur front va pouvoir construire l’interface depuis les fichiers de thème Twig et s’appuyer sur un certains nombre de fonctionnalités que l’outil offre de base. Pour les développements spécifiques, lorsque le développement front est effectué en amont du développement back, on pourra signaler une todo via le markup HTML en utilisant l’attribut data-todo="La description de la tâche". Cela ne correspond pas à un standard et donc ce ne pourra pas être automatiquement indexé par l’IDE, mais une simple recherche de l’attribut dans les fichiers du projet va vite en faire le listing. C’est surtout que on va associer à cet attribut un script assez simple qui va proposer de les afficher visuellement dans le navigateur.

//
// Todo component
// --------------------------------------------------------------------------

export default function todo () {
    const todos = document.querySelectorAll('[data-todo]');
    const todosCookie = getCookie('dev-todo');

    const addStyles = function () {
        const head = document.getElementsByTagName('head')[0];
        const styleTag = document.createElement('style');
        const styles = `
            .todo-toggle {
                position: fixed;
                bottom: 36px;
                left: 0;
                z-index: 1000;
                padding: 7px 10px 8px 60px;
                color: #fff;
                font-size: 14px;
                background: #333;
                border: 0;
                border-radius: 0 4px 4px 0;
                cursor: pointer;
            }

            .todo-toggle::before,
            .todo-toggle::after {
                position: absolute;
                top: 50%;
                left: 10px;
                transform: translate(0, -50%);
                content: "";
            }

            .todo-toggle::before {
                width: 40px;
                height: 20px;
                background: #ccc;
                border: 1px solid #fff;
                border-radius: 10px;
                transition: background-color .1s ease-in-out, border-color .1s ease-in-out;
            }

            .todo-toggle::after {
                left: 12px;
                width: 16px;
                height: 16px;
                background: #fff;
                border-radius: 50%;
                box-shadow: 0 2px 6px rgba(0, 0, 0, .25);
                transition: transform .3s cubic-bezier(.45, -.15, .1, 1.15);
            }

            .todo-toggle.is-active::before {
                background-color: #f00;
                border-color: #f00;
            }

            .todo-toggle.is-active::after {
                transform: translate(20px, -50%);
            }

            .has-todo {
                position: relative;
                outline: 1px dashed #f00;
                outline-offset: .15em;
            }

            .has-todo::before {
                position: absolute;
                top: 0;
                left: 0;
                z-index: 1000;
                max-width: 100%;
                padding: 2px 4px;
                color: #fff;
                font-size: 12px;
                background: #f00;
                content: "TODO: " attr(data-todo);
            }
        `;

        styleTag.setAttribute('type', 'text/css');
        styleTag.appendChild(document.createTextNode(styles));

        head.appendChild(styleTag);
    }

    const displayTodos = function () {
        todos.forEach(todo => {
            todo.classList.toggle('has-todo');
        });
    }

    const addToggle = function () {
        const body = document.getElementsByTagName('body')[0];
        const toggleButton = document.createElement('button');

        toggleButton.type = 'button';
        toggleButton.classList.add('todo-toggle');
        if (todosCookie === '1') {
            toggleButton.classList.add('is-active');
        }
        toggleButton.appendChild(document.createTextNode('TODO'));

        body.appendChild(toggleButton);

        toggleButton.addEventListener('click', function (event) {
            const todosCookie = getCookie('dev-todo');

            event.preventDefault();
            toggleButton.classList.toggle('is-active');
            displayTodos();

            if (todosCookie === '1') {
                setCookie('dev-todo', '0', 7);
            } else {
                setCookie('dev-todo', '1', 7);
            }
        });
    }

    if (todos.length) {
        addStyles();
        addToggle();

        if (todosCookie === '1') {
            displayTodos();
        }
    }
}

const setCookie = function (name, value, days) {
    let expires = "";

    if (days) {
        const date = new Date();
        date.setTime(date.getTime() + (days*24*60*60*1000));
        expires = "; expires=" + date.toUTCString();
    }

    document.cookie = name + "=" + (value || "") + expires + "; path=/";
}

const getCookie = function (name) {
    const nameEQ = name + "=";
    const cookieList = document.cookie.split(';');

    for (let i = 0; i < cookieList.length; i++) {
        const c = cookieList[i];
        while (c.charAt(0) == ' ') c = c.substring(1, c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
    }

    return null;
}

Le script va lister les attributs data-todo dans la page et va afficher un toggle permettant la bascule de l’affichage des textes placés en tant que valeur de l’attribut en surimpression de l’élément dans le navigateur.

Animation de l'affichage des todos visuelles

Bien sûr, ce script est destiné à n’être inclus que sur l’environnement de développement et non en production. Exemple avec un bloc Twig pour un Sylius :

{% if app.debug %}
    {% include '@SyliusUi/_javascripts.html.twig' with {'path': 'bundles/syliusshop/js/todo.js'} %}
{% endif %}

Pour en revenir à l’aspect collaboratif : le développeur back pourra travailler plus efficacement si le markup HTML est déjà renseigné dans le template. De plus, cela permet au projet de se construire visuellement plus rapidement.

Les développeurs peuvent alors avoir en commun une approche orientée composants où chacun va travailler son coeur de métier et passer le relais au fur et à mesure à ses collègues.

Comme évoqué plus tôt, dans le cadre d’un environnement de pré-production mis en place, le travail de review va être facilité. Voir même de permettre de présenter le travail en cours plus régulièrement au client.