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

30
1 На примере текстового редактора ASPxRichEdit Опыт разработки сложных клиент-серверных приложений на TypeScript и ASP.NET Developer Express Inc. Роман Решетников Ведущий разработчик команды ASP.NET

Upload: gosharp

Post on 27-Jul-2015

343 views

Category:

Technology


3 download

TRANSCRIPT

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

1

На примере текстового редактора ASPxRichEdit

Опыт разработки сложных

клиент-серверных приложений на

TypeScript и ASP.NET

Developer Express Inc.

Роман Решетников

Ведущий разработчик команды ASP.NET

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

2Go

# C

on

fere

nce

s

Продукты DevExpress - для множества платформ

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

3Go

# C

on

fere

nce

s

Продукты DevExpress - для всех устройств

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

4Go

# C

on

fere

nce

s

Продукты команды ASP.NET

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

5Go

# C

on

fere

nce

s

Офисные контролы ASP.NET - ASPxSpreadSheet

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

6Go

# C

on

fere

nce

s

ASPxRichEdit – процессор rich-text документов

Работа со всеми популярными rich-text форматами

(DOCX, DOC, RTF, TXT, MHT, ODT, EPUB и т.д.)

Нативная работа с rich-text документами без потери

содержимого

Поддержка стилей, настроек секций, форматирования

текста и параграфов

Печать, экспорт в PDF

Знакомый UI вдохновленный продуктами MS Office

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

7Go

# C

on

fere

nce

s

ASPxRichEdit – не очередной HTML редактор

Rich-Text Editor HTML Editor

Постраничная разбивка

Настраиваемые поля

Поддержка колонок

Header и Footer

Поддержка содержания

Стили документа

Форматирование текста

Поддержка параграфов

Принцип работы Полный контроль над

документом

Нативная браузерная

функциональность

Формат документа RTF, DOCX, DOC, ODT… HTML

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

8Go

# C

on

fere

nce

s

RichEdit для десктопных платформ: WinForms, WPF

30+MB исходного кода (базового для всех платформ)

9000+ тестов базового кода

Более 8 лет разработки

Язык разработки C#

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

9Go

# C

on

fere

nce

s

Выбираем инструменты TypeScript

Jasmine + Chutzpah

Перенос логики на

клиент

Синхронизация с

сервером

Integration тесты

Генерация кода

Асинхронность в JS

Сервис/хандлер вместо привычных

ASP.NET коллбеков

Синхронизируем реквесты, версионность

Тестируем синхронизацию

Как перенести код с сервера на клиент?

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

10

Инструменты

TypeScript – язык, позволяющий работать со сложной типизированной моделью

Тестирование клиентского кода

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

11Go

# C

on

fere

nce

s

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 код

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

12Go

# C

on

fere

nce

s

Но не все идеально в TypeScript

Отсутствует автоматическая линковка .ts файлов.

Компилятору надо подсказывать в каком порядке их

склеивать

Сложно выделить .ts файлы с тестами за пределы

основного TypeScript кода

TS классы не линкуются между проектами Visual Studio

Медленный и не всегда корректный анализ ошибок

компиляции в VS (на больших проектах)

Как вынести тесты в отдельный проект и не потерять связь

между типами:

<TypeScriptCompile Include="{Путь-до-базового-проекта}\**\*.ts"><Link>_referencesTS\%(RecursiveDir)%(FileName)</Link>

</TypeScriptCompile>

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

13Go

# C

on

fere

nce

s

Покрываем клиентский код тестами

Jasmine – удобный framework для BDD unit тестирования

Встроенный framework для быстрого создание mock функций

Простое тестирование timeout функций

«Читабельный» синтаксис

Совместим с TypeScript

Chutzpah – runner тестов в Visual Studio

Простой запуск тестов прямо в VS

Сам создает необходимое окружение для запуска теста в

браузере

Поддерживает тесты написанные на TypeScript и Jasmine

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

14

Перенос логики на клиент

Перенос серверных типов на клиент

Очереди процессов вместо асинхронности

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

15Go

# C

on

fere

nce

s

Быстрый отклик – когда все на клиенте

Клиент работает независимо от сервера. Сервер только

уведомляется о новом состоянии модели

Для продолжения работы с документом клиенту не нужен

ответ сервера

UI не блокируется на время request/response

Модель отправляется на клиент частями

Вся модель разбивается на небольшие части – chunks

Вместе с рендером страницы отправляется первый chunk

Остальные chunks отсылаются на клиент асинхронно

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

16Go

# C

on

fere

nce

s

Передача модели между сервером и клиентом

Сервер

Model→JSON

Response

JSON→Model

Клиент

Model→JSON

Request

JSON→Model

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

17Go

# C

on

fere

nce

s

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]);

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

18Go

# C

on

fere

nce

s

Асинхронное выполнение длительных функций

Длительные операции выполняются «асинхронно»

Цикличные алгоритмы упаковываются в вызовы множества

«быстрых» примитивных функций

Быстрые функции вызываются поочередно из 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()) { }

}

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

19

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

Модель стейтов и реквестов

Синхронизация изменений от нескольких пользователей

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

20Go

# C

on

fere

nce

s

Сессионная модель сервера

Реквесты делаются к HttpHandler, но не к странице

Инстанс пользовательской сессии хранится в статичном

Dictionary. Ключ отсылается на клиент

Сессия идентифицирует конкретную модель (документ), а

не пользователя

Пользователя идентифицирует его ClientGuid (создается

на открытии страницы)

Несколько человек могут открыть один и тот же документ

и работать с одной сессией

Клиент

• Тело реквеста

• ID рабочей сессии

• ID клиента

HttpHandler• Поиск рабочей сессии по ID

• Передача ей ID клиента и

тела реквеста

Сессия

• Обработка реквеста

• Формирование

ответа

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

21Go

# C

on

fere

nce

s

Очередь реквестов

Реквесты на сервер не блокируют UI контрола

Формирование очереди реквестов

Сформированные реквесты добавляются очередь

Очередь накапливается в течение N секунд

Защита от коллизий

Один и тот же реквест может быть отправлен несколько раз,

пока сервер не подтвердит его принятие

Каждый реквест помечен своим идентификатором (версией

документа)

Сервер не выполнит реквест с одним и тем же ID дважды

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

22Go

# C

on

fere

nce

s

Путь к collaboration

Две роли клиентов – Editor и Viewer

Роли клиентов распределяет сервер

Editor – клиент, последний изменивший актуальную

модель

Viewer может стать редактором, если у него была

последняя версия модели и он ее поменял

Viewer с устаревшей моделью – менять ее не может

Рассинхронизация возможна только на коротком

интервале времени или при потере связи

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

23

Integration тестирование

Как протестировать корректную инициализацию клиента

Тестирование синхронизации клиента и сервера

PhantomJS

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

24Go

# C

on

fere

nce

s

Клиентская часть повторяет серверную

Server-side

Client-side

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

25Go

# C

on

fere

nce

s

Тестируем клиент и сервер одновременно

Инициализация стартового состояния

Тестирование применения изменений клиента на

сервере

Тестирование применения изменений состояния

серверной модели к клиентской модели

Тестирование возможных коллизий при синхронизации

состояний

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

26Go

# C

on

fere

nce

s

Цикл интеграционного тестирования

Серверный код теста

Assert полученного состояния

клиентской модели

Применение клиентского

JSON к серверной модели

Assert нового состояния

серверной модели

PhantomJS с клиентским инстансом

Чтение инициализационного

JSON

Выполнение клиентских

операций

Запись в console клиентского

состояния модели

Серверный код теста

Создание серверного инстанса Заполнение модели

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

27Go

# C

on

fere

nce

s

Пример интеграционного теста

[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);

}

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

28Go

# C

on

fere

nce

s

Выбор инструментовСинхронизация и

интеграционное тестированиеМиграция кода на клиент

TypeScript – отличный

инструмент для сложных

клиентских проектов

Jasmine+Chutzpah –

покрывают все задачи по

тестированию клиентского

кода

PhantomJS – помогает

написать интеграционные

тесты

Для переноса серверных

типов на клиент можно

использовать TextTemplates

Сложные вычисления можно

разделить на атомарные

операции и выполнять

очередью из таймаутов

Строгая типизация TypeScript

позволяет довольно просто

портировать логику на клиент

Реквесты на сервер не

должны блокировать UI

Контрол не должен зависеть

от ответов сервера

Интеграционные тесты

позволяют протестировать

стартовую инициализацию

Применение клиентских

изменений на сервере также

покрывается тестами

ASPxRichEdit – «толстые» клиент и сервер

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

29Go

# C

on

fere

nce

s

Синхронизация моделей без коллизий

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

30Go

# C

on

fere

nce

s

Спасибо за внимание!

Продукты DevExpress можно попробовать на нашем

стенде и на http://devexpress.com

Ведущий разработчик команды ASP.NET

Решетников Роман

Developer Express Inc.

[email protected]