Clean architecture principles

Backbone.js — это легковесный JavaScript-фреймворк, предназначенный для создания структурированных веб-приложений. Основная цель Backbone — отделение логики приложения от пользовательского интерфейса, что облегчает поддержку и расширение кода. Фреймворк предоставляет минимальный набор инструментов: модели, коллекции, представления и маршрутизаторы, позволяя разработчику строить архитектуру приложения по собственным правилам.


Модели (Models)

Модель в Backbone.js представляет собой объект данных с логикой. Она инкапсулирует состояние и обеспечивает работу с изменениями через события.

Создание модели:

var Task = Backbone.Model.extend({
    defaults: {
        title: '',
        completed: false
    },
    toggleCompleted: function() {
        this.set('completed', !this.get('completed'));
    }
});

var task = new Task({title: 'Изучить Backbone.js'});

Ключевые возможности моделей:

  • defaults — задаёт начальные значения атрибутов.
  • get() / set() — методы для чтения и записи атрибутов.
  • events — модели могут генерировать события при изменении состояния.

События модели:

task.on('change:completed', function(model, value) {
    console.log('Статус задачи изменён на', value);
});
task.toggleCompleted(); // Выведет: Статус задачи изменён на true

Коллекции (Collections)

Коллекция — это упорядоченный набор моделей одного типа. Она упрощает работу с группами данных, обеспечивая фильтрацию, сортировку и массовые операции.

Создание коллекции:

var TaskList = Backbone.Collection.extend({
    model: Task
});

var tasks = new TaskList([
    {title: 'Изучить Backbone.js'},
    {title: 'Написать учебную статью'}
]);

Методы коллекций:

  • add() и remove() — добавление и удаление моделей.
  • fetch() — получение данных с сервера.
  • sort() — сортировка по заданному атрибуту.
  • filter() и map() — работа с подмножествами данных.

Коллекции также генерируют события, аналогично моделям, позволяя отслеживать изменения во всей группе объектов.


Представления (Views)

Представления отвечают за отображение данных модели или коллекции и обработку пользовательских действий. Backbone поощряет разделение логики и UI, оставляя разработчику свободу в организации DOM.

Пример представления:

var TaskView = Backbone.View.extend({
    tagName: 'li',
    template: _.template('<%= title %> <% if(completed){ %>✓<% } %>'),
    events: {
        'click': 'toggleCompleted'
    },
    initialize: function() {
        this.listenTo(this.model, 'change', this.render);
    },
    render: function() {
        this.$el.html(this.template(this.model.toJSON()));
        return this;
    },
    toggleCompleted: function() {
        this.model.toggleCompleted();
    }
});

var taskView = new TaskView({model: task});
$('#tasks').append(taskView.render().el);

Особенности представлений:

  • Связывают модель или коллекцию с DOM.
  • Реагируют на события модели через listenTo.
  • Содержат обработчики событий пользователя через events.

Маршрутизаторы (Routers)

Маршрутизатор Backbone.js управляет состоянием приложения и URL, позволяя реализовать клиентскую навигацию без перезагрузки страницы.

Пример маршрутизатора:

var AppRouter = Backbone.Router.extend({
    routes: {
        'tasks/:id': 'viewTask',
        '*actions': 'defaultRoute'
    },
    viewTask: function(id) {
        console.log('Просмотр задачи с id:', id);
    },
    defaultRoute: function() {
        console.log('Главная страница приложения');
    }
});

var router = new AppRouter();
Backbone.history.start();

Важные моменты работы маршрутизаторов:

  • routes связывает URL с методами.
  • Backbone.history.start() запускает отслеживание изменений в адресной строке.
  • Маршрутизаторы упрощают реализацию SPA (Single Page Application).

Событийная система Backbone.js

Фреймворк предоставляет мощный механизм событий, позволяющий моделям, коллекциям и представлениям общаться между собой.

Пример использования событий:

var obj = _.extend({}, Backbone.Events);
obj.on('alert', function(msg) {
    console.log('Сообщение:', msg);
});
obj.trigger('alert', 'Backbone работает');

События позволяют создавать реактивные интерфейсы, где любое изменение данных автоматически отражается в представлении.


Синхронизация с сервером

Backbone.js поддерживает работу с RESTful API. Метод fetch() загружает данные, а save() отправляет изменения на сервер.

Пример сохранения модели:

task.save({completed: true}, {
    success: function(model, response) {
        console.log('Данные успешно сохранены', response);
    },
    error: function(model, response) {
        console.error('Ошибка при сохранении', response);
    }
});

Особенности:

  • Используется формат JSON.
  • Поддерживаются стандартные HTTP-методы: GET, POST, PUT, DELETE.
  • Можно переопределять метод sync для кастомных запросов.

Интеграция с шаблонизаторами

Backbone.js не навязывает конкретный способ работы с HTML. Часто используются Underscore.js или Handlebars для шаблонизации.

Пример шаблона с Underscore.js:

var template = _.template('<h2><%= title %></h2><p><%= description %></p>');
$('#content').html(template({title: 'Backbone.js', description: 'Фреймворк для SPA'}));

Шаблоны обеспечивают гибкость и повторное использование HTML-разметки, отделяя логику от представления.


Принципы построения архитектуры

Backbone.js поощряет чистую архитектуру:

  • Разделение обязанностей: модели управляют данными, представления — UI, маршрутизаторы — навигацией.
  • Реактивность: изменения модели автоматически обновляют представление через события.
  • Минимализм: фреймворк предоставляет только каркас, позволяя строить архитектуру под задачи приложения.
  • Тестируемость: отдельные компоненты легко тестировать благодаря независимости моделей, коллекций и представлений.

Использование этих принципов позволяет создавать масштабируемые и поддерживаемые веб-приложения на Backbone.js, сохраняя структуру кода чистой и логичной.