SlideShare a Scribd company logo
1
На примере текстового редактора ASPxRichEdit
Опыт разработки сложных
клиент-серверных приложений на
TypeScript и ASP.NET
Developer Express Inc.
Роман Решетников
Ведущий разработчик команды ASP.NET
2
Go#Conferences
Продукты DevExpress - для множества платформ
3
Go#Conferences
Продукты DevExpress - для всех устройств
4
Go#Conferences
Продукты команды ASP.NET
5
Go#Conferences
Офисные контролы ASP.NET - ASPxSpreadSheet
6
Go#Conferences
ASPxRichEdit – процессор rich-text документов
 Работа со всеми популярными rich-text форматами
(DOCX, DOC, RTF, TXT, MHT, ODT, EPUB и т.д.)
 Нативная работа с rich-text документами без потери
содержимого
 Поддержка стилей, настроек секций, форматирования
текста и параграфов
 Печать, экспорт в PDF
 Знакомый UI вдохновленный продуктами MS Office
7
Go#Conferences
ASPxRichEdit – не очередной HTML редактор
Rich-Text Editor HTML Editor
Постраничная разбивка
Настраиваемые поля
Поддержка колонок
Header и Footer
Поддержка содержания
Стили документа
Форматирование текста
Поддержка параграфов
Принцип работы Полный контроль над
документом
Нативная браузерная
функциональность
Формат документа RTF, DOCX, DOC, ODT… HTML
8
Go#Conferences
RichEdit для десктопных платформ: WinForms, WPF
 30+MB исходного кода (базового для всех платформ)
 9000+ тестов базового кода
 Более 8 лет разработки
 Язык разработки C#
9
Go#Conferences
Выбираем инструменты
 TypeScript
 Jasmine + Chutzpah
Перенос логики на
клиент
Синхронизация с
сервером
Integration тесты
 Генерация кода
 Асинхронность в JS
 Сервис/хандлер вместо привычных
ASP.NET коллбеков
 Синхронизируем реквесты, версионность
 Тестируем синхронизацию
Как перенести код с сервера на клиент?
10
Инструменты
TypeScript – язык, позволяющий работать со сложной типизированной моделью
Тестирование клиентского кода
11
Go#Conferences
TypeScript для .NET разработчика
 Строгая типизация – необходимость для приложений со
сложными моделями
 700+ классов в TS проекте
 5000+ классов в .NET библиотеке
 Компиляция в «чистый» .JS
 Размер скомпиленного .js кода на 15% больше размера .ts.
 Простая отладка js кода даже без .map файлов
 Хорошая поддержка Visual Studio
 Простой синтаксис подобный C#
public class CharacterFormattingInfo {
public string FontName { get; set; }
public int Size { get; set; }
public bool Bold { get; set; }
public bool Italic { get; set; }
public StrikeoutType StrikeoutType { get; set; }
public UnderlineType UnderlineType { get; set; }
public bool AllCaps { get; set; }
…
export class CharacterFormattingInfo {
fontName: string;
size: number;
bold: boolean;
italic: boolean;
strikeoutType: StrikeoutType;
underlineType: UnderlineType;
allCaps: boolean;
…
C# код
TypeScript код
12
Go#Conferences
Но не все идеально в TypeScript 
 Отсутствует автоматическая линковка .ts файлов.
Компилятору надо подсказывать в каком порядке их
склеивать
 Сложно выделить .ts файлы с тестами за пределы
основного TypeScript кода
 TS классы не линкуются между проектами Visual Studio
 Медленный и не всегда корректный анализ ошибок
компиляции в VS (на больших проектах)
 Как вынести тесты в отдельный проект и не потерять связь
между типами:
<TypeScriptCompile Include="{Путь-до-базового-проекта}***.ts">
<Link>_referencesTS%(RecursiveDir)%(FileName)</Link>
</TypeScriptCompile>
13
Go#Conferences
Покрываем клиентский код тестами
 Jasmine – удобный framework для BDD unit тестирования
 Встроенный framework для быстрого создание mock функций
 Простое тестирование timeout функций
 «Читабельный» синтаксис
 Совместим с TypeScript
 Chutzpah – runner тестов в Visual Studio
 Простой запуск тестов прямо в VS
 Сам создает необходимое окружение для запуска теста в
браузере
 Поддерживает тесты написанные на TypeScript и Jasmine
14
Перенос логики на клиент
Перенос серверных типов на клиент
Очереди процессов вместо асинхронности
15
Go#Conferences
Быстрый отклик – когда все на клиенте
 Клиент работает независимо от сервера. Сервер только
уведомляется о новом состоянии модели
 Для продолжения работы с документом клиенту не нужен
ответ сервера
 UI не блокируется на время request/response
 Модель отправляется на клиент частями
 Вся модель разбивается на небольшие части – chunks
 Вместе с рендером страницы отправляется первый chunk
 Остальные chunks отсылаются на клиент асинхронно
16
Go#Conferences
Передача модели между сервером и клиентом
Сервер
Model→JSON
Response
JSON→Model
Клиент
Model→JSON
Request
JSON→Model
17
Go#Conferences
TextTemplates для генерации JSON конвертеров
RichEdit.Core DLL
TextTemplate Engine
• Type FindType(string
typeName)
• PropertyInfo[]
GetProperties()
Converters
• .NET type to JSON
• TS type to .NET
public class ParagraphFormattingInfo {
[JSONEnum(JSONParagraphFormattingProperty.Alignment)]
public ParagraphAlignment Alignment { get; set; }
[JSONEnum(JSONParagraphFormattingProperty.BackColor)]
public Color BackColor { get; set; }
[JSONEnum(JSONParagraphFormattingProperty.LeftIndent)]
public int LeftIndent { get; set; }
…
public class ParagraphFormattingInfoExporter : IExporter<ParagraphFormattingInfo> {
public void FillHashtable(Hashtable result, ParagraphFormattingInfo info) {
result.Add(0, (int)info.Alignment);
result.Add(1, info.BackColor.ToArgb());
result.Add(2, info.LeftIndent);
…
public void RestoreInfo(Hashtable source, ParagraphFormattingInfo info) {
info.Alignment = (ParagraphAlignment)source[0];
info.BackColor = Color.FromArgb(source[1]);
info.LeftIndent = Convert.ToInt32(source[2]);
…
18
Go#Conferences
Асинхронное выполнение длительных функций
 Длительные операции выполняются «асинхронно»
 Цикличные алгоритмы упаковываются в вызовы множества
«быстрых» примитивных функций
 Быстрые функции вызываются поочередно из setTimeout
функции с нулевым интервалом
runFormating() {
if(this.timerID)
return;
var asyncCalculating = () => {
if(this.formatter.formatNext())
this.timerID = setTimeout(asyncCalculating, 0);
else
this.timerID = null;
};
this.timerID = setTimeout(asyncCalculating, 0);
}
runFormatting() {
while(this.formatter.formatNext()) { }
}
19
Синхронизация с сервером
Модель стейтов и реквестов
Синхронизация изменений от нескольких пользователей
20
Go#Conferences
Сессионная модель сервера
 Реквесты делаются к HttpHandler, но не к странице
 Инстанс пользовательской сессии хранится в статичном
Dictionary. Ключ отсылается на клиент
 Сессия идентифицирует конкретную модель (документ), а
не пользователя
 Пользователя идентифицирует его ClientGuid (создается
на открытии страницы)
 Несколько человек могут открыть один и тот же документ
и работать с одной сессией
Клиент
• Тело реквеста
• ID рабочей сессии
• ID клиента
HttpHandler
• Поиск рабочей сессии по ID
• Передача ей ID клиента и
тела реквеста
Сессия
• Обработка реквеста
• Формирование
ответа
21
Go#Conferences
Очередь реквестов
 Реквесты на сервер не блокируют UI контрола
 Формирование очереди реквестов
 Сформированные реквесты добавляются очередь
 Очередь накапливается в течение N секунд
 Защита от коллизий
 Один и тот же реквест может быть отправлен несколько раз,
пока сервер не подтвердит его принятие
 Каждый реквест помечен своим идентификатором (версией
документа)
 Сервер не выполнит реквест с одним и тем же ID дважды
22
Go#Conferences
Путь к collaboration
 Две роли клиентов – Editor и Viewer
 Роли клиентов распределяет сервер
 Editor – клиент, последний изменивший актуальную
модель
 Viewer может стать редактором, если у него была
последняя версия модели и он ее поменял
 Viewer с устаревшей моделью – менять ее не может
 Рассинхронизация возможна только на коротком
интервале времени или при потере связи
23
Integration тестирование
Как протестировать корректную инициализацию клиента
Тестирование синхронизации клиента и сервера
PhantomJS
24
Go#Conferences
Клиентская часть повторяет серверную
Server-side
Client-side
25
Go#Conferences
Тестируем клиент и сервер одновременно
 Инициализация стартового состояния
 Тестирование применения изменений клиента на
сервере
 Тестирование применения изменений состояния
серверной модели к клиентской модели
 Тестирование возможных коллизий при синхронизации
состояний
26
Go#Conferences
Цикл интеграционного тестирования
Серверный код теста
Assert полученного состояния
клиентской модели
Применение клиентского
JSON к серверной модели
Assert нового состояния
серверной модели
PhantomJS с клиентским инстансом
Чтение инициализационного
JSON
Выполнение клиентских
операций
Запись в console клиентского
состояния модели
Серверный код теста
Создание серверного инстанса Заполнение модели
27
Go#Conferences
Пример интеграционного теста
[Test]
public void TestParagraphProperties() {
ChangeDocumentModel(); // предварительная настройка серверной модели
string[] clientResults = RunClientSide(
GetClientModelStateAction(), // записать Model в Output
ExecuteClientCommandAction() // выполнить клиентскую команду, записать
реквест в Output
);
// clientResults[0] – JSON с клиентским состоянием модели (инициализация)
// clientResults[1] – JSON с реквестом на изменение серверной модели
AssertClientModelState(clientResults[0]);
ApplyClientRequestToServerModel(clientResults[1]);
AssertServerModelState(DocumentModel);
}
28
Go#Conferences
Выбор инструментов
Синхронизация и
интеграционное тестирование
Миграция кода на клиент
 TypeScript – отличный
инструмент для сложных
клиентских проектов
 Jasmine+Chutzpah –
покрывают все задачи по
тестированию клиентского
кода
 PhantomJS – помогает
написать интеграционные
тесты
 Для переноса серверных
типов на клиент можно
использовать TextTemplates
 Сложные вычисления можно
разделить на атомарные
операции и выполнять
очередью из таймаутов
 Строгая типизация TypeScript
позволяет довольно просто
портировать логику на клиент
 Реквесты на сервер не
должны блокировать UI
 Контрол не должен зависеть
от ответов сервера
 Интеграционные тесты
позволяют протестировать
стартовую инициализацию
 Применение клиентских
изменений на сервере также
покрывается тестами
ASPxRichEdit – «толстые» клиент и сервер
29
Go#Conferences
Синхронизация моделей без коллизий
30
Go#Conferences
Спасибо за внимание!
Продукты DevExpress можно попробовать на нашем
стенде и на http://devexpress.com
Ведущий разработчик команды ASP.NET
Решетников Роман
Developer Express Inc.
Roman.Reshetnikov@devexpress.com

More Related Content

What's hot (20)

PDF
лек11 4
Anastasia Snegina
 
PDF
API design in java project
chashnikov
 
PDF
C++ осень 2013 лекция 7
Technopark
 
PPT
Опыт тестирования API САПР платформы
SQALab
 
PPT
Selenium RC + python: история одного проекта
Konstantin Prishchenko
 
PPTX
Microsoft Visual Studio 2010
Alexander Babich
 
PDF
лек12
Anastasia Snegina
 
PDF
C++ осень 2013 лекция 8
Technopark
 
PPSX
лекция 3
Надежда Бровко
 
PPTX
Html лаб 2
Vladimir Burdaev
 
PDF
C# Desktop. Занятие 04.
Igor Shkulipa
 
PPTX
Евгений Зуев, С++ в России: Стандарт языка и его реализация
Platonov Sergey
 
PDF
Отладка и оптимизация многопоточных OpenMP-программ
Tatyanazaxarova
 
PDF
C++ весна 2014 лекция 2
Technopark
 
PPTX
Step 1
DmitryTrushkin
 
PDF
Погружение в SObjectizer 5.5. Вводная часть
Yauheni Akhotnikau
 
PDF
C# Desktop. Занятие 02.
Igor Shkulipa
 
PDF
лек11 5
Anastasia Snegina
 
PDF
Лекция 1. Основы объектно-ориентированного программирования
Виталий Емельянов
 
PPTX
Roslyn API : SyntaxTree vs CodeDom, SemanticModel vs Reflection
Denis Tsvettsih
 
лек11 4
Anastasia Snegina
 
API design in java project
chashnikov
 
C++ осень 2013 лекция 7
Technopark
 
Опыт тестирования API САПР платформы
SQALab
 
Selenium RC + python: история одного проекта
Konstantin Prishchenko
 
Microsoft Visual Studio 2010
Alexander Babich
 
C++ осень 2013 лекция 8
Technopark
 
Html лаб 2
Vladimir Burdaev
 
C# Desktop. Занятие 04.
Igor Shkulipa
 
Евгений Зуев, С++ в России: Стандарт языка и его реализация
Platonov Sergey
 
Отладка и оптимизация многопоточных OpenMP-программ
Tatyanazaxarova
 
C++ весна 2014 лекция 2
Technopark
 
Погружение в SObjectizer 5.5. Вводная часть
Yauheni Akhotnikau
 
C# Desktop. Занятие 02.
Igor Shkulipa
 
лек11 5
Anastasia Snegina
 
Лекция 1. Основы объектно-ориентированного программирования
Виталий Емельянов
 
Roslyn API : SyntaxTree vs CodeDom, SemanticModel vs Reflection
Denis Tsvettsih
 

Similar to Опыт разработки сложных клиент-серверных приложений на TypeScript и ASP.NET (20)

PPT
Open Source Testing Framework: real project example and best practices
Aliaksandr Ikhelis
 
PPT
Реализация тестового фреймворка на основе OPEN-SOURCE инструментов
SQALab
 
PDF
«Пуленепробиваемый фронтенд: разработка под React на TypeScript», Станислав П...
MoscowJS
 
PPTX
Описание и архитектура TFS 2008
Александр Шамрай
 
PDF
TDD: когда нужно и, самое главное, когда не нужно / Павел Калашников (SimbirS...
Ontico
 
PPT
паттерны программирования
guestfc8ae0
 
PDF
GraphQL API: Patterns | Андрей Чиж | Zlit Tech
Zlit
 
PPTX
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
Yandex
 
PPT
Net 3.0 & Linq
Constantin Kichinsky
 
PPTX
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Sergey Platonov
 
PPTX
Обзор и архитектура MS Visual Studio Team System 2008
Александр Шамрай
 
PPTX
Silverlight 5
Eugene Zharkov
 
PPTX
Паттерны проектирования источников данных
Alex Polorotov
 
PPTX
паттерны проектирования источников данных
Vitaliy Trenkenshu
 
PDF
Экскурс в мир WEB разработки
IT-Доминанта
 
PPTX
Расширение библиотеки Slick
Арсений Жижелев
 
PPTX
Вячеслав Смирнов - Инструменты нагрузочного тестирования
Elias Fofanov
 
PDF
C# Desktop. Занятие 16.
Igor Shkulipa
 
PPT
Tfs Overview And Architecture (www.cmcons.com)
Alexander Novichkov
 
PDF
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Sergey Platonov
 
Open Source Testing Framework: real project example and best practices
Aliaksandr Ikhelis
 
Реализация тестового фреймворка на основе OPEN-SOURCE инструментов
SQALab
 
«Пуленепробиваемый фронтенд: разработка под React на TypeScript», Станислав П...
MoscowJS
 
Описание и архитектура TFS 2008
Александр Шамрай
 
TDD: когда нужно и, самое главное, когда не нужно / Павел Калашников (SimbirS...
Ontico
 
паттерны программирования
guestfc8ae0
 
GraphQL API: Patterns | Андрей Чиж | Zlit Tech
Zlit
 
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
Yandex
 
Net 3.0 & Linq
Constantin Kichinsky
 
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Sergey Platonov
 
Обзор и архитектура MS Visual Studio Team System 2008
Александр Шамрай
 
Silverlight 5
Eugene Zharkov
 
Паттерны проектирования источников данных
Alex Polorotov
 
паттерны проектирования источников данных
Vitaliy Trenkenshu
 
Экскурс в мир WEB разработки
IT-Доминанта
 
Расширение библиотеки Slick
Арсений Жижелев
 
Вячеслав Смирнов - Инструменты нагрузочного тестирования
Elias Fofanov
 
C# Desktop. Занятие 16.
Igor Shkulipa
 
Tfs Overview And Architecture (www.cmcons.com)
Alexander Novichkov
 
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Sergey Platonov
 
Ad

More from GoSharp (20)

PDF
TPL Dataflow – зачем и для кого?
GoSharp
 
PDF
Живые приложения с Rx
GoSharp
 
PDF
Anemic Domain Model - антипаттерн или SOLID?
GoSharp
 
PDF
Эволюция пользовательского интерфейса бизнес-приложений: от DOSa через окна в...
GoSharp
 
PDF
UniversalApp "убийца" WPF или же это WPF+ ?
GoSharp
 
PDF
UI тестирование WPF приложений в Дойче Банке
GoSharp
 
PDF
Практика применения Enterprise Architect и T4-шаблонов для разработки системы...
GoSharp
 
PDF
За что не любить EF и чем его заменить
GoSharp
 
PDF
MVVM в WinForms – DevExpress Way (теория и практика)
GoSharp
 
PDF
Паттерны быстрой разработки WPF MVVM бизнес-приложений
GoSharp
 
PPTX
Gosharp Intro
GoSharp
 
PDF
Проектирование сетевой инфраструктуры под SOA проекты ASP.NET
GoSharp
 
PDF
Мониторинг приложений ASP.NET на основе сервиса Application Insights
GoSharp
 
PDF
ASP.NET Internals
GoSharp
 
PDF
Кросплатформенная разработка на ASP.NET vNext
GoSharp
 
PDF
Внедрение зависимостей в ASP.NET MVС и ASP.NET vNext
GoSharp
 
PDF
Будущее ASP.NET
GoSharp
 
PDF
Коучинг команд разработки и коучинговые инструменты в работе тимлида
GoSharp
 
PDF
Взаимное влияние Source Code Management и других средств организации разработки
GoSharp
 
PDF
DevOPS инструменты для .NET проектов
GoSharp
 
TPL Dataflow – зачем и для кого?
GoSharp
 
Живые приложения с Rx
GoSharp
 
Anemic Domain Model - антипаттерн или SOLID?
GoSharp
 
Эволюция пользовательского интерфейса бизнес-приложений: от DOSa через окна в...
GoSharp
 
UniversalApp "убийца" WPF или же это WPF+ ?
GoSharp
 
UI тестирование WPF приложений в Дойче Банке
GoSharp
 
Практика применения Enterprise Architect и T4-шаблонов для разработки системы...
GoSharp
 
За что не любить EF и чем его заменить
GoSharp
 
MVVM в WinForms – DevExpress Way (теория и практика)
GoSharp
 
Паттерны быстрой разработки WPF MVVM бизнес-приложений
GoSharp
 
Gosharp Intro
GoSharp
 
Проектирование сетевой инфраструктуры под SOA проекты ASP.NET
GoSharp
 
Мониторинг приложений ASP.NET на основе сервиса Application Insights
GoSharp
 
ASP.NET Internals
GoSharp
 
Кросплатформенная разработка на ASP.NET vNext
GoSharp
 
Внедрение зависимостей в ASP.NET MVС и ASP.NET vNext
GoSharp
 
Будущее ASP.NET
GoSharp
 
Коучинг команд разработки и коучинговые инструменты в работе тимлида
GoSharp
 
Взаимное влияние Source Code Management и других средств организации разработки
GoSharp
 
DevOPS инструменты для .NET проектов
GoSharp
 
Ad

Опыт разработки сложных клиент-серверных приложений на TypeScript и ASP.NET

  • 1. 1 На примере текстового редактора ASPxRichEdit Опыт разработки сложных клиент-серверных приложений на TypeScript и ASP.NET Developer Express Inc. Роман Решетников Ведущий разработчик команды ASP.NET
  • 2. 2 Go#Conferences Продукты DevExpress - для множества платформ
  • 3. 3 Go#Conferences Продукты DevExpress - для всех устройств
  • 6. 6 Go#Conferences ASPxRichEdit – процессор rich-text документов  Работа со всеми популярными rich-text форматами (DOCX, DOC, RTF, TXT, MHT, ODT, EPUB и т.д.)  Нативная работа с rich-text документами без потери содержимого  Поддержка стилей, настроек секций, форматирования текста и параграфов  Печать, экспорт в PDF  Знакомый UI вдохновленный продуктами MS Office
  • 7. 7 Go#Conferences ASPxRichEdit – не очередной HTML редактор Rich-Text Editor HTML Editor Постраничная разбивка Настраиваемые поля Поддержка колонок Header и Footer Поддержка содержания Стили документа Форматирование текста Поддержка параграфов Принцип работы Полный контроль над документом Нативная браузерная функциональность Формат документа RTF, DOCX, DOC, ODT… HTML
  • 8. 8 Go#Conferences RichEdit для десктопных платформ: WinForms, WPF  30+MB исходного кода (базового для всех платформ)  9000+ тестов базового кода  Более 8 лет разработки  Язык разработки C#
  • 9. 9 Go#Conferences Выбираем инструменты  TypeScript  Jasmine + Chutzpah Перенос логики на клиент Синхронизация с сервером Integration тесты  Генерация кода  Асинхронность в JS  Сервис/хандлер вместо привычных ASP.NET коллбеков  Синхронизируем реквесты, версионность  Тестируем синхронизацию Как перенести код с сервера на клиент?
  • 10. 10 Инструменты TypeScript – язык, позволяющий работать со сложной типизированной моделью Тестирование клиентского кода
  • 11. 11 Go#Conferences TypeScript для .NET разработчика  Строгая типизация – необходимость для приложений со сложными моделями  700+ классов в TS проекте  5000+ классов в .NET библиотеке  Компиляция в «чистый» .JS  Размер скомпиленного .js кода на 15% больше размера .ts.  Простая отладка js кода даже без .map файлов  Хорошая поддержка Visual Studio  Простой синтаксис подобный C# public class CharacterFormattingInfo { public string FontName { get; set; } public int Size { get; set; } public bool Bold { get; set; } public bool Italic { get; set; } public StrikeoutType StrikeoutType { get; set; } public UnderlineType UnderlineType { get; set; } public bool AllCaps { get; set; } … export class CharacterFormattingInfo { fontName: string; size: number; bold: boolean; italic: boolean; strikeoutType: StrikeoutType; underlineType: UnderlineType; allCaps: boolean; … C# код TypeScript код
  • 12. 12 Go#Conferences Но не все идеально в TypeScript   Отсутствует автоматическая линковка .ts файлов. Компилятору надо подсказывать в каком порядке их склеивать  Сложно выделить .ts файлы с тестами за пределы основного TypeScript кода  TS классы не линкуются между проектами Visual Studio  Медленный и не всегда корректный анализ ошибок компиляции в VS (на больших проектах)  Как вынести тесты в отдельный проект и не потерять связь между типами: <TypeScriptCompile Include="{Путь-до-базового-проекта}***.ts"> <Link>_referencesTS%(RecursiveDir)%(FileName)</Link> </TypeScriptCompile>
  • 13. 13 Go#Conferences Покрываем клиентский код тестами  Jasmine – удобный framework для BDD unit тестирования  Встроенный framework для быстрого создание mock функций  Простое тестирование timeout функций  «Читабельный» синтаксис  Совместим с TypeScript  Chutzpah – runner тестов в Visual Studio  Простой запуск тестов прямо в VS  Сам создает необходимое окружение для запуска теста в браузере  Поддерживает тесты написанные на TypeScript и Jasmine
  • 14. 14 Перенос логики на клиент Перенос серверных типов на клиент Очереди процессов вместо асинхронности
  • 15. 15 Go#Conferences Быстрый отклик – когда все на клиенте  Клиент работает независимо от сервера. Сервер только уведомляется о новом состоянии модели  Для продолжения работы с документом клиенту не нужен ответ сервера  UI не блокируется на время request/response  Модель отправляется на клиент частями  Вся модель разбивается на небольшие части – chunks  Вместе с рендером страницы отправляется первый chunk  Остальные chunks отсылаются на клиент асинхронно
  • 16. 16 Go#Conferences Передача модели между сервером и клиентом Сервер Model→JSON Response JSON→Model Клиент Model→JSON Request JSON→Model
  • 17. 17 Go#Conferences TextTemplates для генерации JSON конвертеров RichEdit.Core DLL TextTemplate Engine • Type FindType(string typeName) • PropertyInfo[] GetProperties() Converters • .NET type to JSON • TS type to .NET public class ParagraphFormattingInfo { [JSONEnum(JSONParagraphFormattingProperty.Alignment)] public ParagraphAlignment Alignment { get; set; } [JSONEnum(JSONParagraphFormattingProperty.BackColor)] public Color BackColor { get; set; } [JSONEnum(JSONParagraphFormattingProperty.LeftIndent)] public int LeftIndent { get; set; } … public class ParagraphFormattingInfoExporter : IExporter<ParagraphFormattingInfo> { public void FillHashtable(Hashtable result, ParagraphFormattingInfo info) { result.Add(0, (int)info.Alignment); result.Add(1, info.BackColor.ToArgb()); result.Add(2, info.LeftIndent); … public void RestoreInfo(Hashtable source, ParagraphFormattingInfo info) { info.Alignment = (ParagraphAlignment)source[0]; info.BackColor = Color.FromArgb(source[1]); info.LeftIndent = Convert.ToInt32(source[2]); …
  • 18. 18 Go#Conferences Асинхронное выполнение длительных функций  Длительные операции выполняются «асинхронно»  Цикличные алгоритмы упаковываются в вызовы множества «быстрых» примитивных функций  Быстрые функции вызываются поочередно из setTimeout функции с нулевым интервалом runFormating() { if(this.timerID) return; var asyncCalculating = () => { if(this.formatter.formatNext()) this.timerID = setTimeout(asyncCalculating, 0); else this.timerID = null; }; this.timerID = setTimeout(asyncCalculating, 0); } runFormatting() { while(this.formatter.formatNext()) { } }
  • 19. 19 Синхронизация с сервером Модель стейтов и реквестов Синхронизация изменений от нескольких пользователей
  • 20. 20 Go#Conferences Сессионная модель сервера  Реквесты делаются к HttpHandler, но не к странице  Инстанс пользовательской сессии хранится в статичном Dictionary. Ключ отсылается на клиент  Сессия идентифицирует конкретную модель (документ), а не пользователя  Пользователя идентифицирует его ClientGuid (создается на открытии страницы)  Несколько человек могут открыть один и тот же документ и работать с одной сессией Клиент • Тело реквеста • ID рабочей сессии • ID клиента HttpHandler • Поиск рабочей сессии по ID • Передача ей ID клиента и тела реквеста Сессия • Обработка реквеста • Формирование ответа
  • 21. 21 Go#Conferences Очередь реквестов  Реквесты на сервер не блокируют UI контрола  Формирование очереди реквестов  Сформированные реквесты добавляются очередь  Очередь накапливается в течение N секунд  Защита от коллизий  Один и тот же реквест может быть отправлен несколько раз, пока сервер не подтвердит его принятие  Каждый реквест помечен своим идентификатором (версией документа)  Сервер не выполнит реквест с одним и тем же ID дважды
  • 22. 22 Go#Conferences Путь к collaboration  Две роли клиентов – Editor и Viewer  Роли клиентов распределяет сервер  Editor – клиент, последний изменивший актуальную модель  Viewer может стать редактором, если у него была последняя версия модели и он ее поменял  Viewer с устаревшей моделью – менять ее не может  Рассинхронизация возможна только на коротком интервале времени или при потере связи
  • 23. 23 Integration тестирование Как протестировать корректную инициализацию клиента Тестирование синхронизации клиента и сервера PhantomJS
  • 24. 24 Go#Conferences Клиентская часть повторяет серверную Server-side Client-side
  • 25. 25 Go#Conferences Тестируем клиент и сервер одновременно  Инициализация стартового состояния  Тестирование применения изменений клиента на сервере  Тестирование применения изменений состояния серверной модели к клиентской модели  Тестирование возможных коллизий при синхронизации состояний
  • 26. 26 Go#Conferences Цикл интеграционного тестирования Серверный код теста Assert полученного состояния клиентской модели Применение клиентского JSON к серверной модели Assert нового состояния серверной модели PhantomJS с клиентским инстансом Чтение инициализационного JSON Выполнение клиентских операций Запись в console клиентского состояния модели Серверный код теста Создание серверного инстанса Заполнение модели
  • 27. 27 Go#Conferences Пример интеграционного теста [Test] public void TestParagraphProperties() { ChangeDocumentModel(); // предварительная настройка серверной модели string[] clientResults = RunClientSide( GetClientModelStateAction(), // записать Model в Output ExecuteClientCommandAction() // выполнить клиентскую команду, записать реквест в Output ); // clientResults[0] – JSON с клиентским состоянием модели (инициализация) // clientResults[1] – JSON с реквестом на изменение серверной модели AssertClientModelState(clientResults[0]); ApplyClientRequestToServerModel(clientResults[1]); AssertServerModelState(DocumentModel); }
  • 28. 28 Go#Conferences Выбор инструментов Синхронизация и интеграционное тестирование Миграция кода на клиент  TypeScript – отличный инструмент для сложных клиентских проектов  Jasmine+Chutzpah – покрывают все задачи по тестированию клиентского кода  PhantomJS – помогает написать интеграционные тесты  Для переноса серверных типов на клиент можно использовать TextTemplates  Сложные вычисления можно разделить на атомарные операции и выполнять очередью из таймаутов  Строгая типизация TypeScript позволяет довольно просто портировать логику на клиент  Реквесты на сервер не должны блокировать UI  Контрол не должен зависеть от ответов сервера  Интеграционные тесты позволяют протестировать стартовую инициализацию  Применение клиентских изменений на сервере также покрывается тестами ASPxRichEdit – «толстые» клиент и сервер
  • 30. 30 Go#Conferences Спасибо за внимание! Продукты DevExpress можно попробовать на нашем стенде и на http://devexpress.com Ведущий разработчик команды ASP.NET Решетников Роман Developer Express Inc. [email protected]