comment organiser un gros projet backbone

Post on 29-Nov-2014

292 Views

Category:

Presentations & Public Speaking

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

This talk was built in French (for now), at the occasion of Backbone.js Meetup #2 hold in Paris. http://www.meetup.com/backbone-paris/events/189771252 Online presentation : http://metidia.com/talk-enlarge-your-backbone-project/ GitHub source : https://github.com/metidia/talk-enlarge-your-backbone-project

TRANSCRIPT

ENLARGE YOURBACKBONE PROJECT

COMMENT ORGANISER SON PROJET DE FAÇON MODULAIRE ?

Présenté par Nicolas CARLO ( ) et Fabien BERNARD ( )@nicoespeon @fabien0102

KIKON EST ?

NICOLAS CARLOVP of Engineering

FABIEN BERNARDCTO

SAYKOIKON FAIT ?

Jeu social sur le thème du vin dans lequel on peutacheter en vrai les bouteilles que l'on produit virtuellement

En HTML 5… ‘‘full-stack JavaScript’’Backbone.js + MarionetteNode.js + MongoDBGrunt, Mocha, Yeoman, …

LES GARS, CE SOIR ON FAIT UN PROTO !- UN MANAGER UN PEU TROP CONFIANT

// Probablement à l'arrache, dans un ̀main.js̀ FTW// Note - pas besoin de routage pour nous donc on fait sans =)$(function() { // (…)

// On prépare nos bouteilles var bottlesModel = Backbone.Model.extend({ ... }); var bottlesCollection = Backbone.Collection.extend({ ... }); var bottlesView = Backbone.View.extend({ ... }); var bottlesCollectionView = Backbone.View.extend({ ... });

// (…)

// Et on initialise tout le monde ! var myBottlesList = new bottlesCollection(); myBottlesList.fetch();

var myBottlesListView = new bottlesCollectionView({

LE LENDEMAIN- AKA THE HANGOVER

$(function() { // (…)

// On prépare nos bouteilles var bottlesModel = Backbone.Model.extend({ ... }); var bottlesCollection = Backbone.Collection.extend({ ... }); var bottlesView = Backbone.View.extend({ ... }); var bottlesCollectionView = Backbone.View.extend({ ... });

// On prépare nos bâtiments var buildingsModel = Backbone.Model.extend({ ... }); var buildingsCollection = Backbone.Collection.extend({ ... }); var buildingsView = Backbone.View.extend({ ... }); var buildingsCollectionView = Backbone.View.extend({ ... });

// On prépare nos cépages var cepagesModel = Backbone.Model.extend({ ... }); var cepagesCollection = Backbone.Collection.extend({ ... });

TIENS, C'EST DRÔLE...parfois ça plante, parfois ça passe…quand j'enlève ce bout de code y'a tout qui plante !je retrouve plus où on a codé cette boite de dialogue ?!faudrait p'têtr qu'on mette des tests unit... oh wait!le soleil se lève dehors =)

IL FAUT S'ORGANISER!

YAKA SÉPARER LESFICHIERS PAR TYPES

CONCRÈTEMENT, ÇA DONNE QUOI ?app/

main.jsmodels/

bottles.jsbuildings.js

collections/views/tests/ (parce-qu'il faut pas déconner non plus)

THE GOOD PARTS =)On y voit plus clair quand même !Les tests sont isolésFacile de trouver des exemples pour cette archi

THE BOF PARTS =/L'achitecture du code ne reflète pas vraiment nos ‘‘modules’’Et mon style, il est pas modulaire mon style ?

Pis faudra pas oublier :

beware la dépendance entre les ‘‘modules’’

LES QUESTIONS À SE POSER- MERCI ADDY OSMANI \O/

A quel point ce module est instantanément ré-utilisable ?Mes modules peuvent-ils exister indépendamment ?Mes modules peuvent-ils être testés indépendamment ?Mon application n'est-elle pas trop étroitement liée ?Si une partie de mon appli fail, est-ce-que tout s'écroule ?

NOTRE SOLUTION(PROPOSÉE)

LA THÉORIE

Source - (inspired by N. Zakas)http://scaleapp.org/

UN DOSSIER = UN MODULE- ETPICÉTOUT !

app/main.jsmain.lessmodules/

bottles/bottles.jsbottles.lessmodels/collections/views/

bottles.views.composite.jsbottles.views.item.js

templates/tests/

EN PRATIQUELES ÉLÉMENTS DE BOTTLES

// bottles.model.js// Une seule dépendance -> Application Coredefine( [ "app" ], function( app ) {

return Backbone.Model.extend({ ... });

});

// bottles.views.item.js// Une seule dépendance -> Application Coredefine( [ "app" ], function( app ) {

return Backbone.Marionette.ItemView.extend({ ... });

});

EN PRATIQUELE MODULE BOTTLES

// bottles.jsdefine( [ "app",

// Le modèle "bottles/models/bottles",

// Les vues "bottles/views/bottles.views.item"], function( app, Model, ItemView ) {

// Initialise le module avec les méthodes de base. var Bottles = app.module();

// On spécifie nos API Bottles.Model = Model.extend( { ... }); Bottles.Views.Item = ItemView.extend( { ... });

EN PRATIQUELE MAIN.JS

// main.jsdefine( [ "app",

// Les modules "bottles/bottles.js"], function( app, Bottles ) {

// Initialise le module avec les méthodes de base. var myBottlesList = new Bottles.Collection(); myBottlesList.fetch();

var myBottlesListView = new Bottles.Views.Collection( { collection: myBottlesList } ); myBottlesListView.appendTo( "#bottom-bar" );

});

UN MODULE C'EST COMME UN ENFANT- MERCI MONSIEUR ZAKAS \O/

Les modules doivent garder les mains dans leurs pochesOn ne touche pas au DOM des autresOn ne touche pas aux méthodes des autres

Les modules demandent, ils ne prennent pasLes modules ne laissent pas traîner leurs jouets : pas devariables globales, encapsulationLes modules ne parlent pas à des étrangers : on ne parle pasdirectement aux autres modules

NOS OUTILS

REQUIRE.JSGESTION DE DÉPENDANCES + OPTIMIZER AVEC R.JS

Détermine les dépendances de chaque bout de codeRe-compile ces dépendances en un seul fichier JS optimisé

NOM DE CODE BRAIN.JSNOTRE PATTERN MEDIATOR À NOUS

Tour de contrôle des modulesCentralise la communication = découplage des modulesÉcoute les événements intéressants - Backbone.EventTrigger d'autres événements pour déclencher des actions

MARIONETTE.JSENTRE AUTRES UTILITAIRES

Boite à outil indispensable pour gérer des vues de plus en pluscomplexesAbstraction + cache de l'UISimplifier la conf.Enregistrer de requests pour découpler son codeSinon y'a Chaplin aussi si besoin d'aller plus loin

ABSTRACTION + CACHE DE L'UI<div class="builds__menu"> <ul class="builds__menu__tabs"> <li data-ui="tab">Bâtiments</li> <li data-ui="tab">Décorations</li> </ul></div>

<!-- (…) -->

return Backbone.Marionette.ItemView.extend({

ui: { "tab": "[data-ui~=tab]" },

events: { "click @ui.tab": "switchTab" }

// (…)

highlightTabs: function() {

this.ui.tab.each(function() { // Do something awesome! });

SIMPLIFICATION DE LA CONF.return Backbone.Collection.extend({

events: { "click": "displayName" }

appEvents: { "bottles:do:setName": "setName" }

// (…)

initialize: function() { Marionette.bindEntityEvents( this, app, Marionette.getOption( this, "appEvents" ) ); }

setName: function( appellation, name ) {

ENREGISTRER DES REQUESTSreturn Backbone.Collection.extend({

requests: {

getCategories: function() { // Retrieve categories… return categories; }

},

// (…)

initialize: function() { app.reqres.setHandler( "builds:getCategories", this.requests.getCategories, this ); }

// Pendant ce temps, ailleurs dans le code

var buildsCategories = app.request( "builds:getCategories" );

// (…)

AXES D'AMÉLIORATIONAméliorer l'init. des modules dans le mainMultiples Brain.js, parce-que ça grossit viteDifférents ‘‘channels’’ pour les événements

Des suggestions ?

top related