
Chaque semaine, nous partageons les actualités tech qui ont retenues notre attention.
UX / UI, développement frontend & backend, gestion de projet, Agile, DevOps, IA, IoT ou encore AR/VR, font parti des sujets qui nous intéressent.
Chaque semaine, nous partageons les actualités tech qui ont retenues notre attention.
UX / UI, développement frontend & backend, gestion de projet, Agile, DevOps, IA, IoT ou encore AR/VR, font parti des sujets qui nous intéressent.
Habituellement quand on demande à un développeur de faire du scroll jacking sur mobile nous avons tendance à dire NON. Mais pour une expérience de navigation pleine page, le fait d’être positionné parfaitement sur chaque page rend l’expérience plus esthétique.
Nous allons voir comment faire cela simplement, sans que l’expérience utilisateur ne soit altérée. Pour ça, il est important de conserver le mode contracté du navigateur mobile.
Le JS13K est un concours annuel de développement organisé sur un mois. Le but est de développer un jeu faisant moins de 13kb une fois zippé sur un thème donné. J’avais participé à l’édition de 2015 avec Super peach world, et j’ai réitéré en septembre dernier pour la 6ème édition portant sur le thème « lost ».
Je souhaitais partager ici comment j’en suis arrivé au résultat final: « Lonely soul » . Je vous invite d’abord à tester le jeu (http://js13kgames.com/entries/lonely-soul), à le liker et partager si vous avez aimé.
Depuis quelques années, nous guettons la convergence entre conception / design et intégration / développement front.
Avec la fin de Flash, les designers et les développeurs front ont perdu un outil commun pour concevoir et même développer des projets web dynamiques. Alors que des outils et méthodes permettent de factoriser, mutualiser et consolider le travail d’une équipe de développeurs, la phase de conception est restée artisanale.
Hélène, développeur frontend, a déjà abordé ce sujet il y a quelques mois. Elle y restituait les difficultés liées au manque de communication et aux outils non compatibles entre designers et devs front.
L’UX faisait des zonings et des wireframes sur Axure ou Balsamiq et les faisait passer au DA.
Le DA recommençait un tout nouveau projet sur Photoshop, pas du tout fait pour accueillir l’ensemble des pages, déclinaisons responsive et animations. Il livrait aux développeurs front un ou plusieurs fichiers psd plus ou moins bien organisés, dans lequel l’intégrateur devait chercher les assets et déduire ses feuilles de style.
Le chef de projet écrivait pendant ce temps les spécifications fonctionnelles sur un autre outil, Confluence d’Atlassian par exemple, et devait alors arbitrer entre des specs complètes et très verbeuses que personne ne lirait ou des specs succinctes mais pouvant être source d’interprétation, par les développeurs comme par le client.
Le responsive web design et l’adoption massive de Sketch par les designers ont changé la donne, beaucoup d’outils sont désormais à la disposition des designers pour les différentes phase de conception.
Voici un exemple de comparatif récent : https://uxtools.co/tools/design
L’enjeu aujourd’hui est de connecter ces différents métiers :
Voici un petit aperçu de ce qui se met en place et de ce que l’on peut espérer dans les années à venir.
Combien de fois un développeur s’est retrouvé sur un projet avec des CSS énormes et mal structurées ? Il essaie de modifier quelques styles et finit par casser un autre élément, le temps presse, et il n’a pas le temps de regarder dans un millier de lignes de codes.
Il s’en veut, il rougit et croise les doigts pour que personne ne remarque les !important;
dans ses commits, avant de pouvoir se pencher sur un autre problème.
Rien n’est plus compliqué en informatique que de nommer des objets. Il faut réussir à être succinct, explicite, pas trop générique, pas trop compliqué, tout en restant compréhensible.
Si une autre personne lit votre code, elle doit directement comprendre à quoi servent tels ou tels éléments. Il est très important que le code soit clair, parce que cette personne peut très bien être vous dans quelques mois.
Lors de la troisième édition de dotCSS (conférence dédiée aux CSS), Kevin Mandeville (@KevinMandeville) était venu défendre son amour de l’emailing.
Je vais remettre en avant son speak en tant que dévelopeur chez litmus
La réalisation d’un jeu (web ou autre) n’est pas plus complexe que celle d’une web app : elle aussi requiert en amont une conception particulière pour la gestion de son cycle de vie.
Que le jeu soit très basique (un simple quizz) ou au contraire très complexe, il y aura très souvent un système d’écrans et d’étapes qui se suivent les unes après les autres.
Prenons un exemple d’écrans se succédant :
Cette liste est non exhaustive car nous pourrions en ajouter / supprimer en fonction de la demande. La particularité de ces écrans est qu’ils sont indépendants les uns des autres : ils doivent s’enchaîner, passer de l’un à l’autre sans tenir compte de l’écran qui le précède et de celui qui suivra.
Nous utiliserons un émetteur d’événements pour la communication entre nos objets javascript : on.js est une petite librairie qui fait très bien le travail. Le code javascript sera écrit en ES6.
Voici la structure du projet :
Pour gérer l’état de nos écrans il va nous falloir mettre en place un Game manager qui sera chargé de gérer le passage d’une étape à l’autre.
// import de nos différentes scène import Intro from './0_intro' import Tuto from './1_tuto' import Play from './2_play' import End from './3_end' export default class GameManager { constructor(type = 'default') { this.scene = Intro this._container = document.querySelector('.game-container') } startScene() { this._container.innerHTML = this._scene.html this._scene.start() } // Lorsqu’une scène enverra un événement de fin // notre game manager aura la responsabilité de // choisir quel sera la scène suivante sceneEnd(evt) { switch (evt.step) { case Intro.STEP: this.scene = Tuto break case Tuto.STEP: this.scene = Play break case Play.STEP: this.scene = End break case End.STEP: console.log('the game is over') break } } get scene() { return this._scene } set scene(scene) { this._scene = scene this._step = this._scene.step // nous verrons plus tard comment //la scène va émettre l’évènement de fin de scène this._scene.onEvent(evt => this.sceneEnd(evt)) } }
Tous nos écrans de jeu vont avoir en commun différentes actions, c’est pourquoi il est intéressant de faire un objet de scène de jeu qui sera hérité par toutes nos scènes :
// import de notre bibliothèque d'émetteur d'événement import on from 'on' export default class GameScene { constructor(step = 'default') { this.step = step // on transforme notre scène en émetteur d'événement this.onEvent = on(this) } start() { console.log(`scene ${this.step} started`) } end() { // lorsque l’écran se termine //nous envoyons l'événement de fin this.onEvent._fire({ event: 'sceneEnd', step: this.step }) } // Voici le contenu par défaut d'une scène get html() { return `<div>Je suis l'étape : ${this.step}</div>` } }
Les deux actions communes à toutes les scènes sont la méthode start (début du jeu) et end (fin du jeu) qui a pour objectif d’envoyer l’événement de fin de jeu qui pourra être écouté par notre game manager. De plus, chaque scène aura un type enregistré dans la variable this.step, qui sera accessible par notre manager pour qu’il sache quelle étape vient de se finir.
Ensuite voyons comment une scène va hériter de notre objet GameScene et l’utiliser :
import GameScene from '../GameScene' const STEP_VALUE = 'intro' class Scene extends GameScene { get STEP() { return STEP_VALUE } constructor() { super(STEP_VALUE) } // Nous pouvons overrid les méthodes // de GameScene si besoin // get html() {} }
Notre scène d’intro étend GameScene pour profiter des méthodes start et end, de plus elle est typé avec le valeur de STEP qui est égale a intro pour que le manager sache a quel étape en est le déroulement des différents écrans.
L’étape d’intro pourrait charger les assets de notre jeu, afficher un loader puis une animation / cinématique, pour se terminer et appeler la méthode end()
Pour l’exemple nous allons seulement voir l’écran intro
import GameScene from '../GameScene' const STEP_VALUE = 'intro' class Scene extends GameScene { get STEP() { return STEP_VALUE } constructor() { super(STEP_VALUE) } start() { let btn = document.querySelector('.btn') // lors du click sur notre bouton //nous envoyons l'evenement de fin de scène btn.addEventListener('click', () => this.end()) super.start() } get html() { return `<button class="btn">fin de l'intro</button>` } } export default new Scene()
Une fois le bouton cliqué notre méthode sceneEnd() du fichier GameManager.js sera appelé et il s’occupera de passer à la scène d’intro, puis ainsi de suite pour chacune des scènes.
Cette exemple est plutôt réduit mais il offre une bonne base pour un cycle de vie des différents écrans d’un jeu.
Dans notre scène d’intro, nous aurions par exemple pu overrider la méthode end(), sans oublier d’appeler super.end(), pour retirer l’écouteur d’événement clique sur notre bouton. En effet il est important qu’une scène gère sa création et sa destruction pour des raison de performances.
Vous pouvez retrouver le code complet ici sur github et n’hésitez pas à commenter cet article si vous des questions !
Dans un précédent article, je vous parlais de la relation entre designers et développeurs frontend, de leurs métiers respectifs, ainsi que des possibles frictions que pouvaient rencontrer ces deux métiers au quotidien. Dans cette deuxième partie, je vais vous présenter quelques outils que j’utilise au quotidien pour faciliter les échanges avec les designers.
En tant que développeur frontend, j’aimerai vous parler de la relation, ou plutôt, de la « non-relation » entre les designers et les développeurs frontend en agence, avec ses problèmes, ses conséquences et ses solutions possibles (que j’énoncerai dans un second article).
Un mock est un objet fictif qui permet de simuler un comportement réel.
Ce concept a été inventé pour tester des bouts de code en isolant des objets inaccessibles ou non implémentés.
Source : https://fr.wikipedia.org/wiki/Mock_(programmation_orient%C3%A9e_objet)
Une librairie géniale et assez peu connue existe, il s’agit de kakapo.js.
Cette librairie permet d’intercepter les requêtes HTTP et renvoyer la réponse de son choix, le tout via une API déclarative très élégante.
Il est possible d’intercepter les principales méthodes HTTP d’une API (get, post, put, delete), générer des fausses données grâce à un système d’entité, et de faire des traitements avant de renvoyer les réponses.
La documentation est très bien faite et vous serez séduits par la simplicité d’utilisation.
A noter également, cette librairie est disponible pour SWIFT : https://github.com/devlucky/Kakapo
Il y a plusieurs avantages à utiliser des mocks dans votre projet :
En quelques lignes, on met en place Kakapo et on peut intercepter les requêtes GET vers une route /users
.
Ces exemples sont tirés du site officiel.
import {Router, Server} from 'Kakapo'; const router = new Router(); router.get('/users', _ => { return [{ id: 1, name: 'Hector' }, { id: 2, name: 'Zarco' }] }); router.get('/users/:user_id', request => { const userId = request.params.user_id; return [{ id: userId, name: 'PA' }]; }); const server = new Server(); server.use(router);
Ces quelques lignes nous montrent la puissance et la facilité d’écriture de Kakapo.
En effet, une requête fetch('/users')
sera donc interceptée par le Router
et renverra un tableau de deux utilisateurs.
Si on rajoute l’id de l’utilisateur fetch('/users/3')
, on obtient une réponse qui ne contient qu’un seul utilisateur.
Database
Kakapo fournit un outil très pratique pour générer des données (grâce à Faker.js). On peut non seulement générer des données lors de l’initialisation, mais également en rajouter au fur et à mesure de l’utilisation de notre application.
import {Database} from 'Kakapo'; const database = new Database(); database.register('user', faker => { return { firstName: faker.name.firstName, lastName: faker.name.lastName, age: faker.random.number }; }); database.create('user', 5); --- router.get('/users', (request, db) => { return db.all('user'); });
Ce code permet de créer 5 utilisateurs avec des données aléatoires, le routeur renverra un tableau contenant nos nouvelles données.
Pour ajouter un nouvel utilisateur, rien de plus simple
router.post('/users', (request, db) => { const user = JSON.parse(request.body); db.push('user', user); return user; });
On peut également s’amuser à modifier un utilisateur lors d’une requête PUT
ou en supprimer lors d’une requête DELETE
.
router.put('/users/:user_id', (request, db) => { const newLastName = JSON.parse(request.body).lastName; const user = db.findOne('user', request.params.user_id); user.lastName = newLastName; user.save(); return user; }); router.delete('/users/:user_id', (request, db) => { const user = db.findOne('user', request.params.user_id); const code = user ? 200 : 400; const body = {code}; user && user.delete(); return new KakapoResponse(code, body); });
Pour terminer, je vous propose un exemple d’utilisation plus complet et prêt à être intégré dans votre projet.
Crédit photo : Mark Carwardine/NPL/Minden