Александр Сычев
Разработчик iOS
Как не выстрелить себе в ногу
из конечного автомата
iOS state machine
• Постановка задачи
• Пример
• Другие реализации
• Заключение
2
iOS state machine
3
• Постановка задачи
• Пример
• Другие реализации
• Заключение
iOS state machine
Power OffPower On
Button click
Button click
State
Transition
Event
4
iOS state machine
Состояние
5
iOS state machine
Состояние
6
iOS state machine
7
• Игровые приложения
• Анализ текстов
• Параллельная обработка запросов
Традиционные задачи
iOS state machine
8
Традиционные задачи
• Игровые приложения
• Анализ текстов
• Параллельная обработка запросов
iOS state machine
iOS state machine
10
Традиционные задачи
• Игровые приложения
• Анализ текстов
• Параллельная обработка запросов
iOS state machine
11
Анализ текстов
Pattern: ABABAC
iOS state machine
12
Традиционные задачи
• Игровые приложения
• Анализ текстов
• Параллельная обработка запросов
iOS state machine
13
Обработка запросов
iOS state machine
14
Power OffPower On
Button click
Button click
State
Transition
Event
iOS state machine
Presentation layer
Business logic layer
Core layer
iOS state machine
Model-View-Controller
16
ModelView
ControllerSends user
actions
Updates
Updates
Notifies
Mediator Strategy
iOS state machine
VIPER
17
iOS state machine
Model-View-ViewModel
ModelView
ViewModel
Owns
Data and user
action
Owns and
updates
Notifies
UIKit independent
18
iOS state machine
Бизнес-логика
19
iOS state machine
Бизнес-логика
20
iOS state machine
21
iOS state machine
// обработка данных
22
ViewController
iOS state machine
23
IF (error) {
// обработка ошибки
} ELSE {
// обработка данных
}
ViewController
iOS state machine
24
IF (error) {
// обработка ошибки
} ELSE IF (data != NULL) {
// обработка данных
} ELSE {
// нет данных
}
ViewController
iOS state machine
25
IF (isWaiting) {
// ждем данные
} ELSE IF (error) {
// обработка ошибки
} ELSE IF (data != NULL) {
// обработка данных
} ELSE {
// нет данных
}
ViewController
iOS state machine
IF (isWaiting) {
IF (isWaitingAgain) {
// повторное ожидание
} ELSE {
// ждем данные
}
} ELSE IF (error) {
IF (systemError) {
// показать alert
} ELSE {
// показать toast
}
} ELSE IF (data != NULL) {
IF (data.length < 10) {
// обработка данных
} ELSE {
// обработка данных
}
} ELSE {
// нет данных
}
ViewController
26
iOS state machine
Недостатки
©💩kod.ru
27
• Нечитабелен
iOS state machine
Недостатки
• Нечитабелен
• Высокий порог вхождения
• Высокая сложность поддержки и развития
• Негибкий
• Нет защиты от фиктивных состояний
28
iOS state machine
Недостатки
29
• Нечитабелен
• Высокий порог вхождения
• Высокая сложность поддержки и развития
• Негибкий
• Нет защиты от фиктивных состояний
iOS state machine
Недостатки
30
• Нечитабелен
• Высокий порог вхождения
• Высокая сложность поддержки и развития
• Негибкий
• Нет защиты от фиктивных состояний
iOS state machine
Недостатки
31
• Нечитабелен
• Высокий порог вхождения
• Высокая сложность поддержки и развития
• Негибкий
• Нет защиты от фиктивных состояний
iOS state machine
32
Power OffPower On
Button click
Button click
State
Transition
Event
iOS state machine
33
• Постановка задачи
• Пример
• Другие реализации
• Заключение
iOS state machine
GKState
GKStateMachine
34
iOS state machine
35
GKState
GKStateMachine
iOS state machine
GKState
1.class CustomState: GKState
2.func isValidNextState(stateClass: AnyClass) -> Bool
3.func didEnterWithPreviousState(previousState: GKState?)
4.func willExitWithNextState(nextState: GKState)
36
iOS state machine
GKState
1.class CustomState: GKState
2.func isValidNextState(stateClass: AnyClass) -> Bool
3.func didEnterWithPreviousState(previousState: GKState?)
4.func willExitWithNextState(nextState: GKState)
37
iOS state machine
GKState
1.class CustomState: GKState
2.func isValidNextState(stateClass: AnyClass) -> Bool
3.func didEnterWithPreviousState(previousState: GKState?)
4.func willExitWithNextState(nextState: GKState)
38
iOS state machine
GKState
1.class CustomState: GKState
2.func isValidNextState(stateClass: AnyClass) -> Bool
3.func didEnterWithPreviousState(previousState: GKState?)
4.func willExitWithNextState(nextState: GKState)
39
iOS state machine
40
GKState
GKStateMachine
iOS state machine
GKStateMachine
1.init(states states: [GKState])
2.func enterState(_ stateClass: AnyClass) -> Bool
41
iOS state machine
GKStateMachine
1.init(states states: [GKState])
2.func enterState(_ stateClass: AnyClass) -> Bool
42
iOS state machine
Опишем состояния и
переходы между ними
43
iOS state machine
Состояния
Received
Waiting
NoData
Error
44
iOS state machine
Состояния
45
iOS state machine
Состояния
46
iOS state machine
Зададим параметры
автомата
47
iOS state machine
Создаем состояния
let waitingDataState = WaitingDataState()
let dataAvailableState = DataAvailableState()
let dataNotAvailableState = DataNotAvailableState()
let errorState = ErrorState()
48
iOS state machine
Задаем начальное состояние
stateMachine.enterState(WaitingDataState)
49
iOS state machine
Управление
50
enterState(WaitingDataState)
…
IF (error) {
enterState(ErrorState)
} ELSE IF (data != NULL) {
enterState(DataAvailableState)
} ELSE {
enterState(DataNotAvailableState)
}
iOS state machine
51
Gang of Four
iOS state machine
State pattern
52
iOS state machine
GKStateMachine
func goNextWith(_ config: AnyObject)
53
iOS state machine
GKState
func nextStateWith(_ config: AnyObject) -> AnyClass
54
iOS state machine
GameplayKit
Достоинства
• стандартная библиотека
• проста в освоении
• Objective-C / Swift
55
iOS state machine
GameplayKit
Недостатки
• доступна с iOS 9.0
• реализации состояний и переходов
тесно связаны
• дубликаты состояний
56
iOS state machine
57
• Постановка задачи
• Пример
• Другие реализации
• Заключение
iOS state machine
Objective-C
58
Библиотека iOS
TransitionKit 998 5.0
Shift 127 5.0?
TBStateMachine 36 5.0
iOS state machine
Библиотека iOS
TransitionKit 998 5.0
Shift 127 5.0?
TBStateMachine 36 5.0
Objective-C
59
iOS state machine
TransitionKit
• Состояния отделены от переходов
• Передача полезных данных при переходе
• Описание ошибочных переходов
60
iOS state machine
TransitionKit
61
• Состояния отделены от переходов
• Передача полезных данных при переходе
• Описание ошибочных переходов
iOS state machine
TransitionKit
62
• Состояния отделены от переходов
• Передача полезных данных при переходе
• Описание ошибочных переходов
iOS state machine
RestKit
63
iOS state machine
@interface RKOperationStateMachine : NSObject
@property (weak) NSOperation *operation;
@property dispatch_queue_t dispatchQueue;
@end
@interface RKOperationStateMachine ()
@property TKStateMachine *stateMachine;
@end
RestKit
64
iOS state machine
RestKit
ExecutingReady Finished
Start Finish / Cancel
65
iOS state machine
RestKit
- (void)start {
[self.stateMachine start];
}
66
iOS state machine
Objective-C
67
Библиотека iOS
TransitionKit 998 5.0
Shift 127 5.0?
TBStateMachine 36 5.0
iOS state machine
Shift
Любой NSObject может быть автоматом
68
iOS state machine
Swift
Библиотека Swift version
SwiftState 483 2.2
SwiftyStateMachine 287 2.2
Transporter 232 2.2
69
iOS state machine
Библиотека Swift version
SwiftState 483 2.2
SwiftyStateMachine 287 2.2
Transporter 232 2.2
Swift
70
iOS state machine
SwiftyStateMachine
•Полное описание автомата
•Контроль входных сигналов
•Высокая производительность
•Визуализация
71
iOS state machine
SwiftyStateMachine
72
•Полное описание автомата
•Контроль входных сигналов
•Высокая производительность
•Визуализация
iOS state machine
SwiftyStateMachine
73
•Полное описание автомата
•Контроль входных сигналов
•Высокая производительность
•Визуализация
iOS state machine
SwiftyStateMachine
74
•Полное описание автомата
•Контроль входных сигналов
•Высокая производительность
•Визуализация
iOS state machine
SwiftyStateMachine
75
<DOTLabelable>
•Визуализация
iOS state machine
76
• Постановка задачи
• Пример
• Другие реализации
• Заключение
iOS state machine
Достоинства
• Формализация
• Тестируемость
• Контроль потоков данных
• Контроль ошибок
• Единая точка входа для логирования / статистики
• История операций
77
iOS state machine
Достоинства
78
• Формализация
• Тестируемость
• Контроль потоков данных
• Контроль ошибок
• Единая точка входа для логирования / статистики
• История операций
iOS state machine
Достоинства
79
• Формализация
• Тестируемость
• Контроль потоков данных
• Контроль ошибок
• Единая точка входа для логирования / статистики
• История операций
iOS state machine
Достоинства
80
• Формализация
• Тестируемость
• Контроль потоков данных
• Контроль ошибок
• Единая точка входа для логирования / статистики
• История операций
iOS state machine
Достоинства
81
• Формализация
• Тестируемость
• Контроль потоков данных
• Контроль ошибок
• Единая точка входа для логирования / статистики
• История операций
iOS state machine
Достоинства
82
• Формализация
• Тестируемость
• Контроль потоков данных
• Контроль ошибок
• Единая точка входа для логирования / статистики
• История операций
iOS state machine
Задачи
Заказ такси
83
iOS state machine
Задачи
- (void)handleOrder:(Order *)order {
OrderStatus status = order.status;
switch (status) {
case OrderStatusOrdering:
[self.view showOrdering];
[self.interactor handleRideWithOrder:order];
break;
case OrderStatusWaiting:
[self.view showWaiting];
[self.interactor handleWaitingWithOrder:order];
break;
case OrderStatusDriverIsWaiting:
[self.view showDriverIsWaiting];
[self.interactor handleDriverIsWaitingWithOrder:order];
break;
case OrderStatusRide:
[self.view showRide];
[self.interactor handleRideWithOrder:order];
break;
case OrderStatusPayment:
[self.view showPayment];
[self.interactor handlePaymentWithOrder:order];
break;
case OrderStatusFinished:
[self.view showFinished];
[self.interactor handleFinishedWithOrder:order];
break;
case OrderStatusWaitingCancelled:
[self.view showWaitingCancelled];
[self.interactor handleWaitingCancelledWithOrder:order];
break;
case OrderStatusDriverIsWaitingCancelled:
[self.view showDriverIsWaitingCancelled];
[self.interactor handleDriverIsWaitingCancelledWithOrder:order];
break;
default:
[self.view showError];
break;
}
}
84
iOS state machine
Задачи
WaitingOrdering
Driver is
waiting
Placed
RidePayment
Arrived
Go
ArrivedFinished Paid
Cancelled
Cancelled
85
Заказ такси
iOS state machine
Заказ такси
86
iOS state machine
Задачи
Оформление заказа
87
iOS state machine
Задачи
DrawingUpOrdering Payment
Confirm
ShippingReceipt
Approved
Paid
Arrived
Finished
Received
Cancelled
Cancelled
88
Оформление заказа
iOS state machine
Задачи
Оплата
89
iOS state machine
App Coordinators
90
iOS state machine
@sychevbrain89
Brain89
rambler-ios
hr@rambler-co.ru
www.rambler-co.ru/jobs
Power OffPower On
Button click
Button click
State
Transition
Event

Как не выстрелить себе в ногу из конечного автомата / Александр Сычев (RAMBLER&Co)