Как приручить реактивное программирование

Post on 21-Mar-2017

90 Views

Category:

Software

3 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Как приручить реактивное программирование

Денис ЦветцихIce Rock Dev

icerockdev.com

12-я конференция .NET разработчиков15 мая 2016dotnetconf.ru

2

Кто я?• 7+ лет .NET• Разработка корпоративных

приложений• Люблю хипстерские библиотеки

3

Почему я здесь?• 6 лет назад приручил Rx• 3 года назад приручил ReactiveUI• С тех пор активно использую в

XAML проектах

4

Многие не используют• Не знают о Rx и ReactiveUI• Находятся под влиянием «мифов»

о реактивном программировании

5

О чем мы поговорим?• Что такое реактивное

программирование?• Для каких задач его использовать?• Развеем мифы, которые мешают его

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

6

Опрос• Кто не знает, что такое реактивное

программирование?• Кто знаком с Rx и ReactiveUI, но не

решился использовать в своих проектах?

• Кто использовал Rx или ReactiveUI на продакшене?

ЧТО ТАКОЕ РЕАКТИВНОЕ ПРОГРАММИРОВАНИЕ

8

Что такое реактивное программирование?

Реактивное программирование – это парадигма программирования, ориентированная на потоки данных и распространение изменений. (Википедия)

9

Парадигма программирования

Парадигма программирования – это система идей и понятий, определяющих стиль написания компьютерных программ.

10

Императивная программа

var A = 10;var B = A + 1;

// Чему равно В?11

A = A + 1;

// А теперь чему равно В?11

11

Реактивная программаvar A = 10;var B <- A + 1; <- оператор «судьбы»

// Чему равно В?11

A = A + 1;

// А теперь чему равно В?12

12

Реактивное программирование

Реактивное программирование – это парадигма программирования, ориентированная на потоки данных и распространение изменений.

Потоки данных – последовательность значений каждой переменной или свойства класса.

Распространение изменений – уведомления «заинтересованных» об изменениях.

13

PullPull – класс A взаимодействует с классом B и вытягивает из него необходимые данные

Class A Class B

GetData()

Interacts with

14

PushPush – класс B самостоятельно выталкивает данные, как только они становятся доступны.

Class A

ProcessData()

Class BReacts on

15

Примеры из жизни• Вычислимые ячейки Excel

• Принцип Голливуда – «Не звоните нам, мы сами вам позвоним»

• Push - уведомления

РЕАКТИВНОЕ ПРОГРАММИРОВАНИЕ НА C#

17

Прошлое реактивного программирования на C#

• Bindable Linq• https://bindablelinq.codeplex.com• 1.0 beta 1• Последний коммит 5 окт 2008

• Continuous LINQ• http://clinq.codeplex.com/• 2.2.0.1• Последний коммит 23 июня 2010

• Obtics• https://obtics.codeplex.com/• 1.0.13.0• Последний коммит 11 июня 2011

18

Настоящее• Reactive Extensions (Rx)• Эрик Мейер из MS Research

• ReactiveUI• библиотека на базе Rx для создания

элегантных UI для всех XAML платформ

19

Внутри .NETpublic interface IObservable<T>{

IDisposable Subscribe(IObserver<T> observer);}

public interface IObserver<T>{

void OnNext(T value);void OnCompleted();void OnError(Exception error);

}

20

Внутри .NETpublic interface IObservable<T>{

IDisposable Subscribe(IObserver<T> observer);}

public interface IObserver<T>{

void OnNext(T value);void OnCompleted();void OnError(Exception error);

}

21

Внутри .NETpublic interface IObservable<T>{

IDisposable Subscribe(IObserver<T> observer);}

public interface IObserver<T>{

void OnNext(T value);void OnCompleted();void OnError(Exception error);

}

22

Внутри .NETpublic interface IObservable<T>{

IDisposable Subscribe(IObserver<T> observer);}

public interface IObserver<T>{

void OnNext(T value);void OnCompleted();void OnError(Exception error);

}

23

Внутри .NETpublic interface IObservable<T>{

IDisposable Subscribe(IObserver<T> observer);}

public interface IObserver<T>{

void OnNext(T value);void OnCompleted();void OnError(Exception error);

}

24

Оператор судьбы через Rx

var A = new Subject<int>();

// B <- A + 3var B = A.Select(a => a + 3);

// C <- A * Bvar С = A.Zip(B, (a, b) => a * b);

A.OnNext(1);

25

Оператор судьбы через Rx

var A = new Subject<int>();

// B <- A + 3var B = A.Select(a => a + 3);

// C <- A * Bvar С = A.Zip(B, (a, b) => a * b);

A.OnNext(1);

26

Оператор судьбы через Rx

var A = new Subject<int>();

// B <- A + 3var B = A.Select(a => a + 3);

// C <- A * Bvar С = A.Zip(B, (a, b) => a * b);

A.OnNext(1);

27

Observable.Select – проекция

28

Observable.Merge – слияние

29

Observable.Zip - объединение

КАКИЕ ЗАДАЧИ МОЖНО РЕШАТЬ

31

Пример - LoginViewModel

public class LoginViewModel //: INotifyPropertyChanged{ public string Login { get; set; } // PropertyChanged

public string Password { get; set; } // PropertyChanged

public ICommand LoginCommand { get; private set; }

private Task OnLogin() { }}

32

1. Подписка на изменение свойства

// ПодпискаIDisposable _subscription = this.ObservableForProperty(vm => vm.Login) .Subscribe(OnLoginChanged);

// Реакция на событиеprivate void OnLoginChanged (IObservedChange<LoginViewModel, String> change){ }

// Отписка_subscription.Dispose();

33

1. Подписка на изменение свойства

// ПодпискаIDisposable _subscription = this.ObservableForProperty(vm => vm.Login) .Subscribe(OnLoginChanged);

// Реакция на событиеprivate void OnLoginChanged (IObservedChange<LoginViewModel, String> change){ }

// Отписка_subscription.Dispose();

34

1. Подписка на изменение свойства

// ПодпискаIDisposable _subscription = this.ObservableForProperty(vm => vm.Login) .Subscribe(OnLoginChanged);

// Реакция на событиеprivate void OnLoginChanged (IObservedChange<LoginViewModel, String> change){ }

// Отписка_subscription.Dispose();

35

1. Подписка на изменение свойства

// ПодпискаIDisposable _subscription = this.ObservableForProperty(vm => vm.Login) .Subscribe(OnLoginChanged);

// Реакция на событиеprivate void OnLoginChanged (IObservedChange<LoginViewModel, String> change){ }

// Отписка_subscription.Dispose();

36

2. Подписка на изменение нескольких свойств

IDisposable _subscription = this.WhenAny( vm => vm.Login, vn => vm.Password, (login, password) => !string.IsNullOrEmpty(login.Value) && !string.IsNullOrEmpty(password.Value)) .Subscribe(OnCredentialsChanged);

37

2. Подписка на изменение нескольких свойств

IDisposable _subscription = this.WhenAny( vm => vm.Login, vm => vm.Password, (login, password) => !string.IsNullOrEmpty(login.Value) && !string.IsNullOrEmpty(password.Value)) .Subscribe(OnCredentialsChanged);

38

2. Подписка на изменение нескольких свойств

IDisposable _subscription = this.WhenAny( vm => vm.Login, vn => vm.Password, (login, password) => !string.IsNullOrEmpty(login.Value) && !string.IsNullOrEmpty(password.Value)) .Subscribe(OnCredentialsChanged);

39

3. Реактивная асинхронная команда

CanExecute – false, когда1) Не выполняется условие отправки

запроса2) Выполняется асинхронный запрос

40

3. Реактивная асинхронная команда

public LoginViewModel(ILoginService loginService){ _loginService = loginService;

var canExecute = this.WhenAny(vm => vm.Login, vm => vm.Password, (login, password) => !string.IsNullOrEmpty(login.Value) && !string.IsNullOrEmpty(password.Value));

41

3. Реактивная асинхронная команда

public LoginViewModel(ILoginService loginService){ _loginService = loginService;

// Task<bool> Login(login, password)

var canExecute = this.WhenAny(vm => vm.Login, vm => vm.Password, (login, password) => !string.IsNullOrEmpty(login.Value) && !string.IsNullOrEmpty(password.Value));

42

3. Реактивная асинхронная команда

public LoginViewModel(ILoginService loginService){ _loginService = loginService;

var canExecute = this.WhenAny(vm => vm.Login, vm => vm.Password, (login, password) => !string.IsNullOrEmpty(login.Value) && !string.IsNullOrEmpty(password.Value));

43

3. Реактивная асинхронная команда

LoginCommand = ReactiveCommand.CreateAsyncTask (canExecute, async _ => await _loginService.Login(Login, Password));

LoginCommand.Subscribe(OnLoginCompleted);} // of ctor

private void OnLoginCompleted(bool loginSuccessed){ }

44

3. Реактивная асинхронная команда

LoginCommand = ReactiveCommand.CreateAsyncTask (canExecute, async _ => await _loginService.Login(Login, Password));

LoginCommand.Subscribe(OnLoginCompleted);} // of ctor

private void OnLoginCompleted(bool loginSuccessed){ }

45

3. Реактивная асинхронная команда

LoginCommand = ReactiveCommand.CreateAsyncTask (canExecute, async _ => await _loginService.Login(Login, Password));

LoginCommand.Subscribe(OnLoginCompleted);} // of ctor

private void OnLoginCompleted(bool loginSuccessed){ }

46

Достоинства ReactiveCommand

• Не нужно мониторить значения свойств Login и Password

• Не нужно мониторить начало и конец асинхронной операции логина

47

Что ещё умеет ReactiveUI

• Навигация ViewModel First• Маппинг View и ViewModel ручной• IoC на основе Splat • Валидация (не в фреймворке, в сэмплах)• Есть плагин для Fody, который генерит INPC

Но все равно как MVVM фреймворк ReactiveUI слабоват

Поэтому используем из него только команды и привязки

48

Книга мифов о ReactiveUI

49

1. Rx – это экзотическая функциональщина (F#, Scala, Haskel)

F#

Scala

50

На самом деле• Интерфейсы IObservable и

IObserver входят в состав .NET• Для C# существует несколько

библиотек от BindableLinq до ReactiveUI

51

2. Реактивное программирование – это backend

Akka.NET Orleans

ReactiveUI

52

Rx для UI маленький, да удаленький

Что ещё ReactiveUI:• ReactiveCommand• ObservableForProperty• WhenAny

53

3. Боюсь использовать ReactiveUI, слишком экзотично

54

Недостатки ReactiveUI• IoC привязан к Splat• Есть MessageBus, без которого

можно обойтись• Неудобная для WinRT и UWP

навигация ViewModelFirst

55

Используем совместно с другим MVVM

Используем сильные стороны:• ReactiveCommand• Привязки на уровне ViewModel

(ObservableForProperty и WhenAny)

Не используем слабые стороны:• Навигация• IoC

56

4. Использовать несколько MVVM на одном проекте нельзя!

57

Можно, только осторожно

• Каждому MVVM – своя область ответственности

• Контроль, чтобы эта область не расползалась (регулярные ревью)

58

Наш опытReactiveUI Mugen PrismReactiveCommandObservableForPropertyWhenAny

XAML BindingsComposite UI

59

Подведем итоги• ReactiveUI можно (и нужно )

использовать:• Реактивные команды• Привязки на уровне ViewModel вместо

MessageBus• ReactiveUI используем как

дополнение к любимому MVVM фреймворку

60

Реактивное программирование – не страшный и загадочный зверь

61

А верный друг на ваших проектах!

62

Что дальше делать?• Познакомиться: скачать Rx или

ReactiveUI, посмотреть сэмплы• Отладить приложение для

Codefest, сообщество будет вам благодарно

• Попробовать Rx и ReactiveUI на продакшене

63

Полезные ссылкиКлассное видео для начинающихhttps://vimeo.com/43172610

Про Rx для разных языков программированияhttp://reactivex.io/

Официальная страницаhttp://reactiveui.net/Код, примерыhttps://github.com/reactiveuiAutofac https://github.com/alexeyzimarev/RxUI6WithAutofac

64

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

Денис Цветцихden.tsvettsih@yandex.ru

top related