Interfaces
Источник данных — это объект с CRUD + архитектурой, предоставляющий доступ к типовым операциям (create, read, update, delete, ...), применяемым к объекту предметной области (сущности).
Задачи источников:
- обеспечение получения данных с широкого спектра хранилищ;
- порождение сущностей Model и DataSet, содержащих данные из хранилища.
Интерфейс источника данных
Интерфейс источника данных определяет набор операций, выполняемых с данными.
Реализован в Types/source:ICrud и Interface Types/source:ICrudPlus — интерфейс источника данных, поддерживающего расширенный контракт CRUD — операции merge
, copy
и move
.
Список операций:
create
— создать модель (при этом она не сохраняется в хранилище);read
— прочитать модель по первичному ключу;update
— обновить модель;destroy
— удалить модель по первичному ключу;merge
— объединить две модели;copy
— скопировать модель;query
— получить список моделей по запросу;call
— вызвать метод (только для RPC источников).
Термины
- провайдер — объект, предоставляющий доступ к хранилищу данных определенного вида. Зачастую это реализация стандартной технологии и/или протокола (например, HTTP, RESTful, JSON-RPC, XML-RPC, SOAP);
- хранилище данных — программно-аппаратный комплекс, предоставляющий API для удаленного получения данных. Должен работать по протоколу, используемому провайдером;
- endpoint (конечная точка) — настройка, обеспечивающая доступ клиента к функциональным возможностям источника данных. Минимальными настройками конечной точки являются адрес подключения и имя (или адрес) сущности. Если протокол взаимодействия требует дополнительных настроек (например, идентификации клиента при подключении), то спецификация конечной точки расширяется;
- binding (привязка) — настройка, определяющая соответствие методов CRUD+ контракту. Определяет, как именно конкретный источник реализует каждый метод CRUD+.
Типовые виды хранилищ:
- обертка вокруг СУБД, например LAMP;
- специализированный веб-сервис;
- локальный сервис, например localStorage.
Если хранилище данных находится за уровнем приложения, то провайдер должен использовать различные варианты стека протоколов OSI для передачи данных (например, HTTP (XHR), WebSocket).
Все операции, связанные с обращением в хранилище, источник данных выполняет асинхронно.
Уровни абстракции
Интерфейс включает в себя следующие виды абстракций:
- абстракция доступа к хранилищу;
- абстракция подключения;
- абстракция привязки.
Диаграмма уровней абстракции доступа
- Data Source — источник данных;
- Provider — провайдер доступа к хранилищу;
- Storage — хранилище данных, предоставляющее определенное API.
Абстракция доступа позволяет работать с разными видами хранилищ, находящихся на разных уровнях сетевой модели (либо доступными без сетевого подключения).
Диаграмма уровней абстракции подключения
- Data Source — источник данных;
- Endpoint — конечная точка.
Абстракция подключения позволяет одинаково конфигурировать хранилища разного API и архитектуры:
- для key-value хранилища — сформировать префиксы ключей;
- для простого веб-сервиса — сформировать базовый URL для обращения;
- для RPC-сервиса — сформировать адрес подключения и пространство имен методов (либо их префикс);
- для SOAP — сформировать адрес WSDL и пространство имен методов;
- для реляционной базы данных — сформировать адрес подключения, имя базы данных и имя основной таблицы сущности;
- для ORM — сформировать адрес подключения, имя сущности.
Диаграмма уровней абстракции привязки
- Data Source — источник данных;
- Binding — привязка.
Абстракция привязки позволяет одинаково работать с любой инфраструктурой сущностей в формате CRUD+:
- для простого веб-сервиса — сформировать URL для каждой операции CRUD+;
- для RPC-сервиса — вызвать конкретный метод;
- для реляционной базы данных — сформировать SQL запрос;
- для ORM — вызвать метод сущности.
Примеры
Подключим абстрактный источник, работающий c сущностью "Пользователь" через HTTP:
const dataSource = new HttpSource({
endpoint: {
address: '//api.server.name/',
contract: 'user/'
},
binding: {
create: 'add/', // dataSource.create() вызовет //api.server.name/user/add/
read: 'load/', // dataSource.read() вызовет //api.server.name/user/load/
update: 'save/', // dataSource.update() вызовет //sapi.server.name/user/save/
destroy: 'delete/', // dataSource.destroy() вызовет //api.server.name/user/delete/
query: 'list/' // dataSource.query() вызовет //api.server.name/user/list/
}
});
Подключим абстрактный источник, работающий c сущностью "Пользователь" через RPC:
const dataSource = new RpcSource({
endpoint: {
address: '//api.server.name/',
contract: 'User'
},
binding: {
create: 'Add', // dataSource.create() вызовет UserAdd()
read: 'Load', // dataSource.read() вызовет UserLoad()
update: 'Save', // dataSource.update() вызовет UserSave()
destroy: 'Delete', // dataSource.destroy() вызовет UserDelete()
query: 'List' // dataSource.query() вызовет UserList()
}
});
Types/source:Memory
Memory
— источник данных, получающий данные из оперативной памяти.
Ограничения
- не требует настройки endpoint и binding;
- не хранит данные между перезапусками приложения (перезагрузка страницы).
Важно
По умолчанию используется адаптер для данных в формате JSON.
Если вы используете данные в каком-либо другом формате (СБИС-JSON, XML), то нужно подключить соответствующий адаптер.
Примеры
Создадим источник с данными объектов солнечной системы:
const solarSystem = new MemorySource({
data: [
{id: 1, name: 'Sun', kind: 'Star'},
{id: 2, name: 'Mercury', kind: 'Planet'},
{id: 3, name: 'Venus', kind: 'Planet'},
{id: 4, name: 'Earth', kind: 'Planet'},
{id: 5, name: 'Mars', kind: 'Planet'},
{id: 6, name: 'Jupiter', kind: 'Planet'},
{id: 7, name: 'Saturn', kind: 'Planet'},
{id: 8, name: 'Uranus', kind: 'Planet'},
{id: 9, name: 'Neptune', kind: 'Planet'},
{id: 10, name: 'Pluto', kind: 'Dwarf planet'}
],
keyProperty: 'id'
});
Получим данные о Земле:
solarSystem.read(4).then((planet) => {
planet.get('name'); // 'Earth'
});
Получим список планет:
import { Query } from 'Types/source';
const query = new Query();
query.where({
kind: 'Planet'
});
solarSystem.query(query).then((dataSet) => {
const planets = dataSet.getAll();
planets.getCount(); // 8
planets.each((planet) => {
console.log(planet.get('name'));
});
// output: Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
});
Types/source:SbisService
SbisService
— источник данных, работающий с БЛ СБИС.
Использует адаптер для данных в формате СБИС-JSON.
Примеры
Создадим источник для объекта БЛ "Сотрудники":
import { SbisService } from 'Types/source';
const dataSource = new SbisService({
endpoint: 'Staff',
keyProperty: '@СвязиПользователя'
});
Создадим источник для объекта БЛ "Сотрудники" c отдельной точкой входа:
import { SbisService } from 'Types/source';
const dataSource = new SbisService({
endpoint: {
address: '/service/staff/',
contract: 'Staff'
},
keyProperty: '@СвязиПользователя'
});
Создадим источник для объекта БЛ "Сотрудники" с указанием нестандартного метода получения выборки:
import { SbisService } from 'Types/source';
const dataSource = new SbisService({
endpoint: 'Staff',
binding: {
query: 'List'
},
keyProperty: '@СвязиПользователя'
});
Получим данные о сотруднике:
dataSource.read([123454321]).then((employee) => {
employee.get('Фамилия');
});
Получим список сотрудников с фамилией Иванов:
import { Query } from 'Types/source';
const query = new Query();
query.where({
Фамилия: 'Иванов'
});
dataSource.query(query).then((dataSet) => {
const employees = dataSet.getAll();
employees.getCount();
employees.each((employee) => {
console.log(employee.get('Имя'));
});
});