$30 off During Our Annual Pro Sale. View Details »

Refactoring with Backbone.js

Refactoring with Backbone.js

JSDC 2012

大澤木小鐵

May 19, 2012
Tweet

More Decks by 大澤木小鐵

Other Decks in Programming

Transcript

  1. efactoring
    with
    Backbone.js
    R

    View Slide

  2. JSDC 2012
    Jace Ju
    大澤木小鐵
    http://plurk.com/jaceju
    http://twitter.com/jaceju
    http://www.jaceju.net

    View Slide

  3. 擦屁股達人
    如何成為專業的

    View Slide

  4. jQuery DOM 基礎
    underscore.js 的使用方法
    Backebone.js 原理
    力有未逮之處

    View Slide

  5. 好好的沒事
    跟人家學什麼重構
    If it ain’t broke, don’t fix it.

    View Slide

  6. 那一年
    我們學的 jQuery
    Write Once & runs everywhere.

    View Slide

  7. 那一年
    我們學的 jQuery
    Write Once & runs everywhere.
    萬屎 亂

    View Slide

  8. 身為工程師
    都有摳別人屁股程式的時候
    Programmers love copy

    View Slide

  9. 擦舊專案的屁股
    Old project kills me

    View Slide

  10. 屎出不窮
    Bug Happens

    View Slide

  11. Time is all We need.
    時間就像衛生紙

    View Slide

  12. No Magic
    沒有魔術

    View Slide

  13. Keep the DOM structure stable.
    儘可能不更動
    DOM 結構

    View Slide

  14. Same JavaScript Logic.
    JavaScript 邏輯
    改動越少越好

    View Slide

  15. Just do one thing at a time.
    一次只做一件事

    View Slide

  16. Step
    Ӊ᜷
    by Step

    View Slide

  17. 0މ೻ό൯ࡈڭᎈ
    Version Control

    View Slide

  18. View Slide

  19. 0 Іਗʷ಻༊
    Automated Testing

    View Slide

  20. View Slide

  21. 0 ࠠ࿴ృᐑ
    Cycle of refactoring

    View Slide

  22. ࠠ࿴ృᐑ
    ੽வ༁ක֐
    重構
    程式
    測試
    加入
    版本
    刪除
    舊碼
    測試

    View Slide

  23. 1ʱؓᔚϞ೻όᇁ
    Legacy code analysis

    View Slide

  24. $(function () {
    $.get('json.php', function (json) {
    var dataList = json;
    var $input = $('#input').empty();
    var $output = $('#output');
    for(idx in dataList) {
    var dataItem = dataList[idx];
    $input.append('' + dataItem.title + '');
    }
    $('a', $input).bind('click', function (e) {
    e.preventDefault();
    var id = this.id.replace(/^item-/, '');
    var dataItem = _.find(dataList, function(p) {
    return p.id == id;
    });
    $('h1', $output).text(dataItem.title);
    $('p.desc', $output).text(dataItem.desc);
    }).eq(0).click();
    }, 'json');
    });
    ੬ԈٙK2VFSZᄳج

    View Slide

  25. Data
    Input
    Init
    Output
    ̋ɝᕙЍਜ෯ᗆй
    $(function () {
    $.get('json.php', function (json) {
    var dataList = json;
    var $input = $('#input').empty();
    var $output = $('#output');
    for(idx in dataList) {
    var dataItem = dataList[idx];
    $input.append('' + dataItem.title + '');
    }
    $('a', $input).bind('click', function (e) {
    e.preventDefault();
    var id = this.id.replace(/^item-/, '');
    var dataItem = _.find(dataList, function(p) {
    return p.id == id;
    });
    $('h1', $output).text(dataItem.title);
    $('p.desc', $output).text(dataItem.desc);
    }).eq(0).click();
    }, 'json');
    });

    View Slide

  26. 2 ˾౬༟ࣘᜊᅰ
    Replace Data Variables
    with Model/Collection

    View Slide

  27. [
    { "id": 1, "title": "...", "desc": "..." },
    { "id": 2, "title": "...", "desc": "..." },
    { "id": 3, "title": "...", "desc": "..." },
    { "id": 4, "title": "...", "desc": "..." },
    { "id": 5, "title": "...", "desc": "..." }
    ]
    У؂ኜ၌הΫෂٙ+40/ࣸό

    View Slide

  28. [
    { "id": 1, "title": "...", "desc": "..." },
    { "id": 2, "title": "...", "desc": "..." },
    { "id": 3, "title": "...", "desc": "..." },
    { "id": 4, "title": "...", "desc": "..." },
    { "id": 5, "title": "...", "desc": "..." }
    ]
    У؂ኜ၌הΫෂٙ+40/ࣸό
    重要

    View Slide

  29. var Model = Backbone.Model.extend({
    defaults: {
    title: '',
    desc: ''
    }
    });
    var Collection = Backbone.Collection.extend({
    model: Model
    });
    ່֛.PEFM$PMMFDUJPOᗳй

    View Slide

  30. var Model = Backbone.Model.extend({
    defaults: {
    title: '',
    desc: ''
    }
    });
    var Collection = Backbone.Collection.extend({
    model: Model
    });
    ່֛.PEFM$PMMFDUJPOᗳй

    View Slide

  31. var dataList = json;
    for(idx in dataList) {
    var dataItem = dataList[idx];
    // ...
    }
    var id = ...;
    var dataItem = _.find(dataList, function(d) {
    return d.id == id;
    });
    $('h1').text(dataItem.title);
    $('p').text(dataItem.desc);
    ੬Ԉٙ༟ࣘஈଣᜌ፨

    View Slide

  32. var dataList = json;
    ͜$PMMFDUJPO̍ༀ+40/ᜊᅰ
    [
    { "id": 1, "title": "...", "desc": "..." },
    { "id": 2, "title": "...", "desc": "..." },
    { "id": 3, "title": "...", "desc": "..." },
    { "id": 4, "title": "...", "desc": "..." },
    { "id": 5, "title": "...", "desc": "..." }
    ]

    View Slide

  33. var dataList = new Collection(json);
    ͜$PMMFDUJPO̍ༀ+40/ᜊᅰ
    Collection
    Model
    Model
    Model
    Model

    View Slide

  34. for(idx in dataList) {
    var dataItem = dataList[idx];
    // ...
    }
    ͜$PMMFDUJPOGPS&BDI՟˾༟ࣘࠖ˾
    [
    { "id": 1, "title": "...", "desc": "..." },
    { "id": 2, "title": "...", "desc": "..." },
    { "id": 3, "title": "...", "desc": "..." },
    { "id": 4, "title": "...", "desc": "..." },
    { "id": 5, "title": "...", "desc": "..." }
    ]

    View Slide

  35. dataList.forEach(function (dataItem) {
    // ...
    });
    ͜$PMMFDUJPOGPS&BDI՟˾༟ࣘࠖ˾
    dataList : Collection
    dataItem : Model
    dataItem : Model
    dataItem : Model
    dataItem : Model

    View Slide

  36. [
    { "id": 1, "title": "...", "desc": "..." },
    { "id": 2, "title": "...", "desc": "..." },
    { "id": 4, "title": "...", "desc": "..." },
    { "id": 5, "title": "...", "desc": "..." }
    ]
    var id = ...;
    var dataItem = _.find(dataList, function(d) {
    return d.id == id;
    });
    ҷ͜$PMMFDUJPOHFU
    ՟੻ఊഅ༟ࣘ
    { "id": 3, "title": "...", "desc": "..." }

    View Slide

  37. [
    { "id": 1, "title": "...", "desc": "..." },
    { "id": 2, "title": "...", "desc": "..." },
    { "id": 4, "title": "...", "desc": "..." },
    { "id": 5, "title": "...", "desc": "..." }
    ]
    var id = ...;
    var dataItem = _.find(dataList, function(d) {
    return d.id == id;
    });
    ҷ͜$PMMFDUJPOHFU
    ՟੻ఊഅ༟ࣘ
    { "id": 3, "title": "...", "desc": "..." }

    View Slide

  38. var id = ...;
    var dataItem = dataList.get(id);
    ҷ͜$PMMFDUJPOHFU
    ՟੻ఊഅ༟ࣘ
    dataList : Collection
    dataItem : Model
    dataItem : Model
    dataItem : Model

    View Slide

  39. { "id": 3, "title": "...", "desc": "..." }
    $('h1').text(dataItem.title);
    $('p').text(dataItem.desc);
    ҷ͜.PEFMHFU
    ՟੻᙮׌࠽

    View Slide

  40. $('h1').text(dataItem.get('title'));
    $('p').text(dataItem.get('desc'));
    ҷ͜.PEFMHFU
    ՟੻᙮׌࠽
    dataItem : Model get
    title
    desc

    View Slide

  41. 3 ˏ͜ᅵو
    Introduce
    JavaScript Template

    View Slide

  42. var $dom = $('#view');
    $dom.html('' + dataItem.get('title') + '');
    ੬Ԉٙ೥ࠦяତᜌ፨

    View Slide

  43. var $dom = $('#view');
    $dom.html('' + dataItem.get('title') + '');
    ੬Ԉٙ೥ࠦяତᜌ፨
    這個叫 HTML

    View Slide

  44. var $dom = $('#view');
    $dom.html('' + dataItem.get('title') + '');
    <br/>
    ່֛ᅵو

    View Slide

  45. var $dom = $('#view');
    $dom.html('' + dataItem.get('title') + '');
    <br/>
    ່֛ᅵو

    View Slide

  46. var $dom = $('#view');
    $dom.html('' + dataItem.get('title') + '');
    <br/><h1>' + dataItem.get('title') + '</h1><br/>
    ່֛ᅵو

    View Slide

  47. var $dom = $('#view');
    $dom.html('' + dataItem.get('title') + '');
    <br/><h1>' + dataItem.get('title') + '</h1><br/>
    ່֛ᅵو

    View Slide

  48. var $dom = $('#view');
    $dom.html('' + dataItem.get('title') + '');
    <br/><h1><%= title %></h1><br/>
    ່֛ᅵو

    View Slide

  49. var $dom = $('#view');
    var template = _.template($('#view-template').html());
    $dom.html('' + dataItem.get('title') + '');
    <br/><h1><%= title %></h1><br/>
    ່֛ᅵو˙ج

    View Slide

  50. var $dom = $('#view');
    var template = _.template($('#view-template').html());
    $dom.html('' + dataItem.get('title') + '');
    <br/><h1><%= title %></h1><br/>
    ͜ᅵو˙ج՟˾)5.-οЕ

    View Slide

  51. var $dom = $('#view');
    var template = _.template($('#view-template').html());
    $dom.html(template(dataItem.toJSON()));
    <br/><h1><%= title %></h1><br/>
    ͜ᅵو˙ج՟˾)5.-οЕ

    View Slide

  52. 4ˏɝ7JFXᗳй
    Introduce View Class

    View Slide

  53. var $dom = $('#view');
    var template = _.template($('#view-template').html());
    $dom.html(template(dataItem.toJSON()));
    ່֛7JFXᗳй

    View Slide

  54. var $dom = $('#view');
    var template = _.template($('#view-template').html());
    $dom.html(template(dataItem.toJSON()));
    ່֛7JFXᗳй
    template

    View Slide

  55. var $dom = $('#view');
    var template = _.template($('#view-template').html());
    $dom.html(template(dataItem.toJSON()));
    ່֛7JFXᗳй
    template
    display

    View Slide

  56. var View = Backbone.View.extend({
    render: function () {
    return this;
    }
    });
    var $dom = $('#view');
    var template = _.template($('#view-template').html());
    $dom.html(template(dataItem.toJSON()));
    ່֛7JFXᗳй

    View Slide

  57. var View = Backbone.View.extend({
    render: function () {
    return this;
    }
    });
    var $dom = $('#view');
    var template = _.template($('#view-template').html());
    $dom.html(template(dataItem.toJSON()));
    ย୅ᅵو˙ج

    View Slide

  58. var View = Backbone.View.extend({
    template: _.template($('#view-template').html()),
    render: function () {
    return this;
    }
    });
    var $dom = $('#view');
    var template = _.template($('#view-template').html());
    $dom.html(template(dataItem.toJSON()));
    ย୅ᅵو˙ج

    View Slide

  59. var View = Backbone.View.extend({
    template: _.template($('#view-template').html()),
    render: function () {
    return this;
    }
    });
    var $dom = $('#view');
    $dom.html(template(dataItem.toJSON()));
    ย୅ᅵو˙ج

    View Slide

  60. var View = Backbone.View.extend({
    template: _.template($('#view-template').html()),
    render: function () {
    return this;
    }
    });
    var $dom = $('#view');
    $dom.html(template(dataItem.toJSON()));
    ย୅ᜑͪᜌ፨

    View Slide

  61. var View = Backbone.View.extend({
    template: _.template($('#view-template').html()),
    render: function () {
    $dom.html(template(this.model.toJSON()));
    return this;
    }
    });
    var $dom = $('#view');
    $dom.html(template(dataItem.toJSON()));
    ย୅ᜑͪᜌ፨

    View Slide

  62. var View = Backbone.View.extend({
    template: _.template($('#view-template').html()),
    render: function () {
    $dom.html(this.template(this.model.toJSON()));
    return this;
    }
    });
    var $dom = $('#view');
    $dom.html(template(dataItem.toJSON()));
    ҷ͜7JFXٙᅵو˙ج

    View Slide

  63. var View = Backbone.View.extend({
    template: _.template($('#view-template').html()),
    render: function () {
    this.$el.html(this.template(this.model.toJSON()));
    return this;
    }
    });
    var $dom = $('#view');
    $dom.html(template(dataItem.toJSON()));
    ҷ͜7JFXٙFM᙮׌

    View Slide

  64. var View = Backbone.View.extend({
    template: _.template($('#view-template').html()),
    render: function () {
    this.$el.html(this.template(this.model.toJSON()));
    return this;
    }
    });
    var $dom = $('#view');
    $dom.html(template(dataItem.toJSON()));
    ୅ৰᔚٙяତᜌ፨

    View Slide

  65. var View = Backbone.View.extend({
    template: _.template($('#view-template').html()),
    render: function () {
    this.$el.html(this.template(this.model.toJSON()));
    return this;
    }
    });
    var $dom = $('#view');
    ୅ৰᔚٙяତᜌ፨

    View Slide

  66. var View = Backbone.View.extend({
    template: _.template($('#view-template').html()),
    render: function () {
    this.$el.html(this.template(this.model.toJSON()));
    return this;
    }
    });
    var $dom = $('#view');
    var view = new View({
    });
    ᜑͪ೥ࠦ

    View Slide

  67. var View = Backbone.View.extend({
    template: _.template($('#view-template').html()),
    render: function () {
    this.$el.html(this.template(this.model.toJSON()));
    return this;
    }
    });
    var $dom = $('#view');
    var view = new View({
    el: '#view'
    });
    ᜑͪ೥ࠦ

    View Slide

  68. var View = Backbone.View.extend({
    template: _.template($('#view-template').html()),
    render: function () {
    this.$el.html(this.template(this.model.toJSON()));
    return this;
    }
    });
    var $dom = $('#view');
    var view = new View({
    el: '#view',
    model: dataItem
    });
    ᜑͪ೥ࠦ

    View Slide

  69. var View = Backbone.View.extend({
    template: _.template($('#view-template').html()),
    render: function () {
    this.$el.html(this.template(this.model.toJSON()));
    return this;
    }
    });
    var $dom = $('#view');
    var view = new View({
    el: '#view',
    model: dataItem
    });
    ᜑͪ೥ࠦ

    View Slide

  70. var View = Backbone.View.extend({
    template: _.template($('#view-template').html()),
    render: function () {
    this.$el.html(this.template(this.model.toJSON()));
    return this;
    }
    });
    var view = new View({
    el: '#view',
    model: dataItem
    });
    ᜑͪ೥ࠦ

    View Slide

  71. var View = Backbone.View.extend({
    template: _.template($('#view-template').html()),
    render: function () {
    this.$el.html(this.template(this.model.toJSON()));
    return this;
    }
    });
    var view = new View({
    el: '#view',
    model: dataItem
    });
    view.render();
    ᜑͪ೥ࠦ

    View Slide

  72. 5ˏɝً࿒ي΁
    Introduce Status Object

    View Slide

  73. Input Event Handler
    Output View
    ً࿒ي΁༶Ъࡡଣ

    View Slide

  74. Input Event Handler
    Output View
    ً࿒ي΁༶Ъࡡଣ

    View Slide

  75. Input Event Handler
    Output View
    Status
    ً࿒ي΁༶Ъࡡଣ

    View Slide

  76. var $input = $('#input');
    var outputView = new OutputView({
    el: '#output'
    });
    $('a', $input).bind('click', function (e) {
    e.preventDefault();
    var id = /* ... */;
    var dataItem = dataList.get(id);
    outputView.model = dataItem;
    outputView.render();
    });
    ̋ɝً࿒ي΁

    View Slide

  77. var status = new DataItem();
    var $input = $('#input');
    var outputView = new OutputView({
    el: '#output'
    });
    $('a', $input).bind('click', function (e) {
    e.preventDefault();
    var id = /* ... */;
    var dataItem = dataList.get(id);
    outputView.model = dataItem;
    outputView.render();
    });
    ̋ɝً࿒ي΁

    View Slide

  78. var status = new DataItem();
    var $input = $('#input');
    var outputView = new OutputView({
    el: '#output',
    model: status
    });
    $('a', $input).bind('click', function (e) {
    e.preventDefault();
    var id = /* ... */;
    var dataItem = dataList.get(id);
    outputView.model = dataItem;
    outputView.render();
    });
    ਗ਼ً࿒ي΁ഐΥՑ7JFXي΁ɪ

    View Slide

  79. var status = new DataItem();
    var $input = $('#input');
    var outputView = new OutputView({
    el: '#output',
    model: status
    });
    status.on('change', outputView.render, outputView);
    $('a', $input).bind('click', function (e) {
    e.preventDefault();
    var id = /* ... */;
    var dataItem = dataList.get(id);
    outputView.model = dataItem;
    outputView.render();
    });
    ً່֛࿒ي΁ၾ7JFXي΁ٙʝਗ

    View Slide

  80. var status = new DataItem();
    var $input = $('#input');
    var outputView = new OutputView({
    el: '#output',
    model: status
    });
    status.on('change', outputView.render, outputView);
    $('a', $input).bind('click', function (e) {
    e.preventDefault();
    var id = /* ... */;
    var dataItem = dataList.get(id);
    status.set(dataItem.toJSON());
    outputView.model = dataItem;
    outputView.render();
    });
    ً͜࿒ي΁՟˾7JFXي΁ٙᜑͪᜌ፨

    View Slide

  81. var status = new DataItem();
    var $input = $('#input');
    var outputView = new OutputView({
    el: '#output',
    model: status
    });
    status.on('change', outputView.render, outputView);
    $('a', $input).bind('click', function (e) {
    e.preventDefault();
    var id = /* ... */;
    var dataItem = dataList.get(id);
    status.set(dataItem.toJSON());
    outputView.model = dataItem;
    outputView.render();
    });
    ً͜࿒ي΁՟˾7JFXي΁ٙᜑͪᜌ፨

    View Slide

  82. var status = new DataItem();
    var $input = $('#input');
    var outputView = new OutputView({
    el: '#output',
    model: status
    });
    status.on('change', outputView.render, outputView);
    $('a', $input).bind('click', function (e) {
    e.preventDefault();
    var id = /* ... */;
    var dataItem = dataList.get(id);
    status.set(dataItem.toJSON());
    });
    ً͜࿒ي΁՟˾7JFXي΁ٙᜑͪᜌ፨

    View Slide

  83. 6዆Υࠫࠦԫ΁ᜌ፨
    Move DOM event handlers

    View Slide

  84. var InputView = Backbone.View.extend({
    // ...
    });
    var $input = $('#input');
    $('a', $input).bind('click', function (e) {
    var dataItem = dataList.get(id);
    status.set(dataItem.toJSON());
    });
    ย୅ԫ΁ஈଣዚՓ

    View Slide

  85. var InputView = Backbone.View.extend({
    // ...
    });
    var $input = $('#input');
    $('a', $input).bind('click', function (e) {
    var dataItem = dataList.get(id);
    status.set(dataItem.toJSON());
    });
    ย୅ԫ΁ஈଣዚՓ

    View Slide

  86. var InputView = Backbone.View.extend({
    // ...
    events: {
    'click a': 'changeOutput'
    },
    changeOutput: function (e) {
    }
    });
    var $input = $('#input');
    $('a', $input).bind('click', function (e) {
    var dataItem = dataList.get(id);
    status.set(dataItem.toJSON());
    });
    ย୅ԫ΁ஈଣዚՓ

    View Slide

  87. var InputView = Backbone.View.extend({
    // ...
    events: {
    'click a': 'changeOutput'
    },
    changeOutput: function (e) {
    }
    });
    var $input = $('#input');
    $('a', $input).bind('click', function (e) {
    var dataItem = dataList.get(id);
    status.set(dataItem.toJSON());
    });
    ย୅ԫ΁ஈଣዚՓ

    View Slide

  88. var InputView = Backbone.View.extend({
    // ...
    events: {
    'click a': 'changeOutput'
    },
    changeOutput: function (e) {
    var dataItem = dataList.get(id);
    status.set(dataItem.toJSON());
    }
    });
    var $input = $('#input');
    $('a', $input).bind('click', function (e) {
    var dataItem = dataList.get(id);
    status.set(dataItem.toJSON());
    });
    ย୅ԫ΁ஈଣዚՓ

    View Slide

  89. var InputView = Backbone.View.extend({
    // ...
    events: {
    'click a': 'changeOutput'
    },
    changeOutput: function (e) {
    var dataItem = dataList.get(id);
    status.set(dataItem.toJSON());
    }
    });
    var $input = $('#input');
    $('a', $input).bind('click', function (e) {
    var dataItem = dataList.get(id);
    status.set(dataItem.toJSON());
    });
    ย୅ԫ΁ஈଣዚՓ

    View Slide

  90. var InputView = Backbone.View.extend({
    // ...
    events: {
    'click a': 'changeOutput'
    },
    changeOutput: function (e) {
    var dataItem = dataList.get(id);
    status.set(dataItem.toJSON());
    }
    });
    ࡌ͍ਞϽᜊᅰ

    View Slide

  91. var InputView = Backbone.View.extend({
    // ...
    events: {
    'click a': 'changeOutput'
    },
    changeOutput: function (e) {
    var dataItem = dataList.get(id);
    status.set(dataItem.toJSON());
    }
    });
    var inputView = new InputView({
    el: '#input'
    });
    ࡌ͍ਞϽᜊᅰ

    View Slide

  92. var InputView = Backbone.View.extend({
    // ...
    events: {
    'click a': 'changeOutput'
    },
    changeOutput: function (e) {
    var dataItem = dataList.get(id);
    status.set(dataItem.toJSON());
    }
    });
    var inputView = new InputView({
    el: '#input',
    collection: dataList
    });
    ࡌ͍ਞϽᜊᅰ

    View Slide

  93. var InputView = Backbone.View.extend({
    // ...
    events: {
    'click a': 'changeOutput'
    },
    changeOutput: function (e) {
    var dataItem = this.collection.get(id);
    status.set(dataItem.toJSON());
    }
    });
    var inputView = new InputView({
    el: '#input',
    collection: dataList
    });
    ࡌ͍ਞϽᜊᅰ

    View Slide

  94. var InputView = Backbone.View.extend({
    // ...
    events: {
    'click a': 'changeOutput'
    },
    changeOutput: function (e) {
    var dataItem = this.collection.get(id);
    status.set(dataItem.toJSON());
    }
    });
    var inputView = new InputView({
    el: '#input',
    collection: dataList,
    model: status
    });
    ࡌ͍ਞϽᜊᅰ

    View Slide

  95. var InputView = Backbone.View.extend({
    // ...
    events: {
    'click a': 'changeOutput'
    },
    changeOutput: function (e) {
    var dataItem = this.collection.get(id);
    this.model.set(dataItem.toJSON());
    }
    });
    var inputView = new InputView({
    el: '#input',
    collection: dataList,
    model: status
    });
    ࡌ͍ਞϽᜊᅰ

    View Slide

  96. ̍ༀ"+"9
    Replace $.ajax
    with Backbone.sync
    7

    View Slide

  97. var DataList = Backbone.Collection.extend({
    model: DataItem
    });
    $(function () {
    $.get('json.php', function (json) {
    var dataList = new DataList(json);
    // ...
    status.on('change', outputView.render, outputView);
    inputView.render();
    }, 'json');
    });
    ย୅4FSWFS၌"1*ٙխ̣Зໄ

    View Slide

  98. var DataList = Backbone.Collection.extend({
    model: DataItem
    });
    $(function () {
    $.get('json.php', function (json) {
    var dataList = new DataList(json);
    // ...
    status.on('change', outputView.render, outputView);
    inputView.render();
    }, 'json');
    });
    ย୅4FSWFS၌"1*ٙխ̣Зໄ

    View Slide

  99. var DataList = Backbone.Collection.extend({
    model: DataItem,
    url: 'json.php'
    });
    $(function () {
    $.get('json.php', function (json) {
    var dataList = new DataList(json);
    // ...
    status.on('change', outputView.render, outputView);
    inputView.render();
    }, 'json');
    });
    ย୅4FSWFS၌"1*ٙխ̣Зໄ

    View Slide

  100. var DataList = Backbone.Collection.extend({
    model: DataItem,
    url: 'json.php'
    });
    $(function () {
    var dataList = new DataList(json);
    // ...
    status.on('change', outputView.render, outputView);
    inputView.render();
    });
    ย୅4FSWFS၌"1*ٙխ̣Зໄ

    View Slide

  101. var DataList = Backbone.Collection.extend({
    model: DataItem,
    url: 'json.php'
    });
    $(function () {
    var dataList = new DataList(json);
    // ...
    status.on('change', outputView.render, outputView);
    inputView.render();
    });
    ୅ৰʔ̀ࠅٙᜊᅰ

    View Slide

  102. var DataList = Backbone.Collection.extend({
    model: DataItem,
    url: 'json.php'
    });
    $(function () {
    var dataList = new DataList();
    // ...
    status.on('change', outputView.render, outputView);
    inputView.render();
    });
    ୅ৰʔ̀ࠅٙᜊᅰ

    View Slide

  103. var DataList = Backbone.Collection.extend({
    model: DataItem,
    url: 'json.php'
    });
    $(function () {
    var dataList = new DataList();
    // ...
    status.on('change', outputView.render, outputView);
    inputView.render();
    });
    ່֛༟ࣘΝӉܝٙᙃ೯ԫ΁

    View Slide

  104. var DataList = Backbone.Collection.extend({
    model: DataItem,
    url: 'json.php'
    });
    $(function () {
    var dataList = new DataList();
    // ...
    status.on('change', outputView.render, outputView);
    inputView.render();
    dataList.on('all', inputView.render, inputView);
    });
    ່֛༟ࣘΝӉܝٙᙃ೯ԫ΁

    View Slide

  105. var DataList = Backbone.Collection.extend({
    model: DataItem,
    url: 'json.php'
    });
    $(function () {
    var dataList = new DataList();
    // ...
    status.on('change', outputView.render, outputView);
    dataList.on('all', inputView.render, inputView);
    });
    ່֛༟ࣘΝӉܝٙᙃ೯ԫ΁

    View Slide

  106. var DataList = Backbone.Collection.extend({
    model: DataItem,
    url: 'json.php'
    });
    $(function () {
    var dataList = new DataList();
    // ...
    status.on('change', outputView.render, outputView);
    dataList.on('all', inputView.render, inputView);
    dataList.fetch();
    });
    ່֛༟ࣘΝӉܝٙᙃ೯ԫ΁

    View Slide

  107. var DataItem = Backbone.Model.extend({ ... });
    var DataList = Backbone.Collection.extend({ ... });
    var InputView = Backbone.View.extend({ ... });
    var OutputView = Backbone.View.extend({ ... });
    $(function () {
    var dataList = new DataList();
    var status = new DataItem();
    var inputView = new InputView({
    el: '#input',
    collection: dataList,
    model: status
    });
    var outputView = new OutputView({
    el: '#output',
    model: status
    });
    status.on('change', outputView.render, outputView);
    dataList.on('all', inputView.render, inputView);
    dataList.fetch();
    });
    最後的成果

    View Slide

  108. 這就是
    重構!

    View Slide


  109. GitHub



    https://github.com/jaceju/refactoring_with_backbone.js

    View Slide

  110. 總結
    Conclusion

    View Slide

  111. 小步前進
    Refactoring for next step.

    View Slide

  112. 精益求精
    Refactoring always.

    View Slide

  113. 職責與解耦
    SRP & Decoupling.

    View Slide

  114. 克服惰性
    Do it right now!

    View Slide

  115. 謝謝大家
    Thank you.
    投影片網址: http://goo.gl/ivDuz

    View Slide