Александр Сычев "Разделяй и властвуй: CQRS в iOS"

Preview:

Citation preview

CQRS

Lead iOS developer

Александр Сычев

a.sychev@rambler-co.ru

@asychev89

CQRS

Collaboration and staleness

CQRS

CQRS

😈

CQRS

Consistency Availability

Partition tolerance

CQRS

Consistency Availability

Partition tolerance

AP

CQRS

CQRS

CQRS

Presentation layer

Data access layer

Data layer

Business logic layer

CQRS

Presentation layer

Data access layer

Data layer

Business logic layer

SQL

CQRS

Presentation layer

Data access layer

Data layer

Business logic layer

SQL

ManagedObject

CQRS

Presentation layer

Data access layer

Data layer

Business logic layer

SQL

ManagedObject

PlainObject

CQRS

Presentation layer

Data access layer

Data layer

Business logic layer

SQL

ManagedObject

PlainObject

ViewModel

CQRS

Presentation layer

Data assess layer

Data layer

Business logic layer

SQL

ManagedObject

PlainObject

ViewModel

3

CQRS

Presentation layer

Data access layer

Data layer

Business logic layer

ViewModel

ViewModel

ViewModel

ViewModel

CQRS

SELECT * FROM MyViewTable WHERE FolderID = INBOX

CQRS

SELECT * FROM MyViewTable WHERE FolderID = INBOX

In-memory

CQRS

In-memory In-memory

CQRS

key/value store key/value store

CQRS

Queries and Commands

CQRS

Command–query separation B. Meyer

CQRS

1. Queries

2. Commands

CQRS

class User { private(set) var email: String? func isValid(emailAddress: String?) -> Bool { let emailTest = NSPredicate() let isValid = emailTest.evaluate(with: emailAddress) if isValid { email = emailAddress // Command } return isValid // Query } }

CQRS

class User { private(set) var email: String? func isValid(emailAddress: String?) -> Bool { let emailTest = NSPredicate() let isValid = emailTest.evaluate(with: emailAddress) if isValid { email = emailAddress // Command } return isValid // Query } }

CQRS

class User { private(set) var email: String? func isValid(emailAddress: String?) -> Bool { let emailTest = NSPredicate() let isValid = emailTest.evaluate(with: emailAddress) if isValid { email = emailAddress // Command } return isValid // Query } }

CQRS

class User { private(set) var email: String? func isValid(emailAddress: String?) -> Bool { let emailTest = NSPredicate() return emailTest.evaluate(with: emailAddress) } func update(emailAddress: String?) { if isValid(emailAddress: emailAddress) { email = emailAddress } } }

CQRS

Command Query Responsibility Segregation

CQRS

Domain Model

Validation

O R M

Presentation

CQRS

Domain Model

Validation

Query

Command

Query model

O R M

CQRS

Command•Изменяет состояние системы

•Ничего не возвращает

•Описывает действия пользователей над системой

•Хранит нужные для её выполнения данные

CQRS

Commandclass DeleteUserCommand: Command, DeleteUserContext { private var session: Session init(session: Session) { self.session = session } func execute(context: CommandContext) { session.delete(context) } }

CQRS

Query

•Не изменяет состояние системы

•Хранит нужные для её выполнения данные

•Возвращает результат

CQRS

Queryclass FindUserByIdQuery: Query { private var session: Session init(session: Session) { self.session = session } func ask(context: QueryContext) -> User { return session.query(context) } }

CQRS

MessageService- (void)createDraftMessageWithCompletion:(CompletionBlock)block;

- (void)sendMessage:(Message *)message;

- (Array<Message> *)messagesForFolder:(NSString *)folder;

- (void)obtainAttachment:(Attachment *)attachment completion:(ErrorBlock)block;

CQRS

MessageService- (void)createDraftMessageWithCompletion:(CompletionBlock)block;

- (void)sendMessage:(Message *)message;

- (Array<Message> *)messagesForFolder:(NSString *)folder;

- (void)obtainAttachment:(Attachment *)attachment completion:(ErrorBlock)block;

•- query•- command

CQRS

MessageService

•- query•- command

CreateMessageCommand

SendMessageCommand

ObtainMessagesInFolderQuery

ObtainAttachmentQuery

CQRS

CQRS•Меньше зависимостей в каждом классе

•Соблюдается SRP

•Проще изменять

•Проще тестировать

•Однотипный дизайн кода

CQRS

Domain Model

Validation

Query

Command

Query model

O R M

w

r

Event Publisher

CQRS

Event

struct Event { var name: String var payload: [String: AnyObject]? }

DidSendMessage DidCreateDraft

CQRS

Occasionally Connected Clients

CQRS

CQRS

Conference

•Что пойдет не так, если сети нет?

•Как клиент обрабатывает отложенные события?

•Что стоит сделать при появлении сети?

CQRS

Conference

•Пусть клиент продолжает работать

•Нужна очередь отложенных событий

•Синхронизировать данные и сообщить о конфликте

CQRS

Domain Model

Validation

Query

Command

Query model

O R M

w

r

Event Publisher

CQRS

Flux

CQRS

CQRS

Выводы

CQRS

Недостатки

•Новый стиль мышления

•Сложность синхронизации

•Overengineering

CQRS

Достоинства

•Высокая производительность чтения

•SRP

•Тестируемость

CQRS

Достоинства

ivdyagileva@gmail.com

CQRS

Достоинства

•Высокая производительность чтения

•SRP

•Тестируемость

CQRS

a.sychev@rambler-co.ru

@asychev89

Domain Model

Validation

Query

Command

Query model

w

r

Event

O R M

Recommended