Mise en production agile de la V2 d'une application
Pourquoi faire une V2 de son application ?
Refonte UX
Migration technique
Pourquoi mettre en production son application rapidement est crucial ?
Utilisable à chaque étape de la production
Les retours utilisateurs !
Retours maquette ou sur prototype
+ Itérable rapidement
+ Peu coûteux à développer
+ Maquettes indispensables
Retours sur produit
en production
+ Satisfaction de l'équipe technique
+ Parcours complets
+ Utilisation en cas réel
+ Détection des incohérences UX
+ Détection des bugs
From Scratch
Progressive
Situation A (actuelle) ---> Situation A' (améliorée) ---> Situation B (désirée)
Situation A (actuelle) ---> Situation B (désirée)
La Situation A' :
- Se rapproche de B
- Permet de mesurer l'amélioration désirée
- Permet de mettre en production le produit (standards de qualité + valeur conservée pour l'utilisateur)
Migration progressive
Retour d'expérience : Ajouter React dans une application Symfony
Site Medium like pour bloggeur professionels
Doit pouvoir itérer rapidement pour prendre en compte les retours utilisateurs
1/2 journée
ArticleCreation.prototype.changeTab = function(element) {
if (!element.hasClass('lock') && !element.hasClass('on'))
{
if (element.hasClass('third'))
{
element.off();
window.open(
element.find('a').attr('href'),
'_blank'
);
return;
}
if (element.hasClass('second'))
{
_articleCreation.openMoveModule();
}
else
{
_articleCreation.closeMoveModule();
}
$('.tabs li').removeClass('on');
$('.ctab').removeClass('on');
$(element).addClass('on');
$('#' + $(element)
.find('a')
.attr('href')
).addClass('on');
_articleCreation.launchAutowidth();
}
}
ArticleCreation.prototype.changeTabEvents = function() {
$('.tabs-second li a').click(function(e){
e.preventDefault();
var parentLi = $(this).parents('li');
if (parentLi.hasClass('lock'))
{
return;
}
if (parentLi.hasClass('first'))
{
$('.tabs li.first a').click();
}
if (parentLi.hasClass('second'))
{
$('.tabs li.second a').click();
}
$('.tabs-second li').each(function(){
$(this).removeClass('active');
});
parentLi.addClass('active');
});
$('.tabs li a').click(function(e){
if (!$(this).hasClass('notab'))
{
e.preventDefault();
_articleCreation.changeTab(
$(this).parent('li')
);
}
});
}
Javascript
<ul class="tabs-second"><!--
--><li class="first
{% if app.request.get('tab') != 'second-tab' %}active{% endif %}
">
<a href="first-tab">{{ "Info"|trans({}) }}</a>
</li><!--
--><li class="second
{% if app.request.get('tab') == 'second-tab' %}active{% endif %}
">
<a href="second-tab">{{ "Média"|trans({}) }}</a>
</li>
</ul>
...
<ul class="tabs" style="display:none;">
<li class="first
{% if app.request.get('tab') != 'second-tab' %}active{% endif %}
">
<a href="first-tab">{{ "Les informations"|trans({}) }}</a>
</li><!--
--><li class="second
{% if app.request.get('tab') == 'second-tab' %}active{% endif %}
">
<a href="second-tab">{{ "La story"|trans({}) }}</a>
</li><!--
--><li class="third">
<a href="">{{ "Voir la story"|trans({}) }}</a>
</li>
</ul>
Twig
Ce qui rend le code non réutilisable
Code Spaghetti
Logique dans le template Twig et le JS
Process de build pas clair et pas documenté
Situation A = Symfony Twig + Jquery
Situation B = Symfony as API + React front
Cette situation B demande que l'on refasse beaucoup de choses en front qui existent déjà en back : le routing, les traductions, la gestion des utilisateurs, la gestion du state de l'application...
Il va falloir rendre accessible par API beaucoup de contenus qui pour le moment ne le sont que depuis des controllers Symfony.
Situation A' = Symfony Twig + React sur la page d'édition de l'article
Cette situation est bien plus simple à atteindre, elle permet en plus de tester des choses :
- Est-ce que toutes les pages doivent être refaites ou est-ce qu'une simple partie du produit doit être migrée vers une SPA ?
- Est-ce que le téléchargement d'un bundle React à chaque chargement de page est acceptable ?
- Comment estimer le coût de cette migration ?
Comment est-ce que nous avons fait :
- Détermination d'un point d'entrée Webpack par page migrée de l'application
- Dans les templates Twig, on importe le script qui va rendre le contenu
Avantages :
- Le header qui contient la navigation reste à la main de Symfony (ainsi que le controle du user, l'accès au Menu etc...)
Inconvénients :
- Temps de chargement sur la page Article anormalement long du point de vue de l'utilisateur.
- Peut-être corrigé par du server side rendering, ce qui permet de continuer à partager le contenu entre les articles et l'éditeur
UGC viens nous voir et nous dit qu'ils veulent créer une V2 de l'application. Ils ont déjà refait leur site web mobile en accord avec le nouveau design qui correspondra plus ou moins à celui l'application mobile.
Situation A = Application native V1 en PROD
Situation B = Application native V2 en PROD avec les mêmes features que la V1
Parmi ces features, les features standards pour consulter les films en salle, les salles où les films sont diffusés, les cinémas et les films favoris.
Certaines features semblent plus longues : le tunnel de paiement avec le 3D secure, l'utilisation de cartes de fidélités pour payer, l'affichage et la gestion de ses cartes de fidélité.
Situation A' = Application Native V2 affichant le site mobile pour la plupart des pages
Cela permet de mettre l'application rapidement en production sans tout recoder et de remplacer les features faites par des webviews au fur et à mesure sans détruire de valeur pour l'utilisateur
Comment est-ce que nous avons fait :
- Utilisation de Webviews pour afficher le site dans une page de notre routing
- Passage via un paramètre d'URL que nous visionnons le site depuis une webview ce qui cache le header et le footer ainsi que tous les boutons permettant de naviguer dans le site.
Inconvénients :
- Débuggage complexe (avoir le site ouvert en parallèle de l'application)
- Le routing de la webview ne fonctionnait pas (pas possible de cliquer sur back)
- Look and feel natif pas présent
Mise en production agile de la V2 d'une application
By Nicolas Ngô-Maï
Mise en production agile de la V2 d'une application
- 290