Cum aș putea trata Dependency Injection în Backbone

De câteva zile fac refactor la o aplicație Backbone, scriu teste acolo unde nu sunt șamd. Și făcând asta, m-am lovit de următoarea problemă:

var Book = Backbone.Model.extend();

var Books = Backbone.Collection.extend({
  model : Book
});

var BookView = Backbone.View.extend({ render: function(){ return this; } });

var BooksView = Backbone.View.extend({
  initialize: function(){
    this.collection.on('add', this.addItem, this );
  },

  addItem: function(){
    var book = new BookView(); //<<<<<<<<<<<<<<<<
    this.$el.append( book.render().$el );
  },
});

var boox = new BookView({ collection: new Books() });

Am pus tot codul pentru context; problema apare aici: var book = new BookView();. Cum s-ar putea optimiza acest aspect din punct de vedere al unui cod SOLID dar și din punct de vedere al testării?

Aș fi interesat de o abordare ce nu implică alte biblioteci (e.g. require, browserify etc). Plecăm de la premisa că este vorba de un cod ce nu are nevoie de o „compilare” înaintea rulării.

Nu stiu cum ai codul structurat dar poti incerca: https://github.com/togakangaroo/simple-modules

Nu contează cum e structurat restul; mă interesează cum aș putea rezolva problema în exemplul dat mai sus fără module, require etc).

O soluție la care m-am gândit ar fi să fac un nou obiect („clasă”) care s-ar ocupa de instanțierea lui BookView:

function BookViewFactory() {
  this.getBook = new BookView();
}

Astfel încât trimit new BookViewFactory() ca parametru la instanțierea lui BookView, după care, în metoda addItem pot chema ceva de genul var book = this.bookViewFactory.getBook() (în loc de new BookView()).


De ce nu vreau resurse externe (require, amd etc)? Foarte simplu: întâi vreau să înțeleg cum funcționează, nu să adaug un black box layer în aplicație, care nu știu ce face. În final însă, da, voi folosi un sistem de module (mă gândesc serios la browserify).

@iamntz : abordarea ta mi se pare foarte corecta (doar ca functia in afara). Practic acel BookView este un instrument/serviciu de rendare. Pentru ca tu in BooksView nu testezi cum se rendeaza run Bookview, atunci el trebuie astractizat. Astfel pe el il vei primi dintru service provider ( sau factory cum ii spui tu).

Atunci cand vei testa BooksView vei crea un service de provider gol ( cu un render fara side efects) si vei testa doar ca metoda render se apeleaza ( eventual testezi ca se apeleaza o singura data.

Eventual, daca modifici implementarea, Poti pune un test ca daca adaugi un obiect null, nu se executa deloc render.

https://github.com/togakangaroo/simple-modules este destul de simplu de inteles, uita-te pe sursa.

define('BookView', function () {
  return new BookView();
})

var book = require('BookView')



// when testing
define('BookView', function () {
  return FakeBookView
})

var book = require('BookView') // <- FakeBookView

Nu ai nevoie de browserify / require.

2 Likes