"rest-soa-view-controller или Проектирование...

Post on 16-Jan-2017

342 Views

Category:

Mobile

3 Downloads

Preview:

Click to see full reader

TRANSCRIPT

REST-SOA-Controller-View: Проектирование обмена данными

Егор Тафланиди19/03/2016et@redmadrobot.com

Агенда

- Опрос аудитории

- Слои

- Сервер

- Протокол

- Мобильное приложение

- Пример

01

02

Опрос аудитории

03

Польза

Агенда

- Опрос аудитории

- Слои

- Сервер

- Протокол

- Мобильное приложение

- Пример

04

Агенда

- Опрос аудитории

- Слои

- Сервер

- Протокол

- Мобильное приложение

- Пример

04

- Domain-Specific Language

- DSL-интерфейс

- Обмен модельными объектами

Слои

05

СВОЙСТВА

Entity• id { get set }

/* no logic */

Агенда

- Опрос аудитории

- Слои

- Сервер

- Протокол

- Мобильное приложение

- Пример

06

Entity• id { get set }!

- База данных

Сервер

07

СТРУКТУРА

Table: Userid name surname1 Иван Иванов2 Сидор Сидоров

- База данных

Сервер

07

СТРУКТУРА

Table: Username surnameИван ИвановСидор Сидоров

id12

- База данных

Сервер

08

СТРУКТУРА

Table: Username surnameИван ИвановСидор Сидоров

id12

=>

User• id • name • surname

- ORM вычитывает объект из базы

- DAO транслирует ORM-объект в POJO

Сервер

09

СТРУКТУРА: ПУТЕШЕСТВИЕ ENTITY

User• id • name • surname

ORMDatabase DAO

ORM Object

BusinessLogic

Object

Сервер

10

User• id • name • surname

BusinessLogic Serialiser

Object

Transport

DT Object

- ORM вычитывает объект из базы

- DAO транслирует ORM-объект в POJO

- Бизнес-логика транслирует POJO в DTO

СТРУКТУРА: ПУТЕШЕСТВИЕ ENTITY

Сервер

11

User• id • name • surname

Transport HTTP

JSON

MobileApp

JSON

- ORM вычитывает объект из базы

- DAO транслирует ORM-объект в POJO

- Бизнес-логика транслирует POJO в DTO

- Транспорт транслирует DTO в JSON

- JSON передаётся на фронт

СТРУКТУРА: ПУТЕШЕСТВИЕ ENTITY

Сервер

12

СТРУКТУРА: TYPE STACK

User

ORMDatabase

DAO

BusinessLogic

Serialiser

Transport

Product

ORMDatabase

DAO

BusinessLogic

Serialiser

Transport

Message

ORMDatabase

DAO

BusinessLogic

Serialiser

Transport

Сервер

13

СЕРВИСЫ

User

Product

Message

} НаборWeb-сервисов

14

ПротоколREST

Протокол

15

RESOURCE

Resource R is a temporally varying membership

function MR(t), which for time t 

maps to a set of entities

/ Representational State Transfer, dissertation /http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

Протокол

16

ENTITY & URL ENDPOINT

/entities(resource)

Array(Entity)

Entity• id { get set }

Протокол

16

ENTITY & WEB SERVICE

: REntity

POST /entities

GET /entities

GET /entities/{id}

PATCH /entities/{id}

DELETE /entities/{id}

/entities(resource)

Entity• id { get set }

Протокол

17

C.R.U.D.

POST /entities

GET /entities

GET /entities/{id}

PATCH /entities/{id}

DELETE /entities/{id}

Create

Read

Update

Delete

Entity• id { get set }∀

Протокол

18

ВЛОЖЕННОСТЬ. ДОВЕРИЕ К СЕРВЕРУ

User• id: Long • name: String

PATCH /users/{id}/nameUser• id: Long • name: String

/* name patched */

Агенда

- Опрос аудитории

- Слои

- Сервер

- Протокол

- Мобильное приложение

- Пример

19

20

Мобильное приложениеSDK MVC

Мобильное приложение

- Тип данных = ключевая сущность

- Разница в логике = набор полей

21

SERVICE-ORIENTED ARCHITECTURE

Entity

ORMDatabase

DAO

BusinessLogic

Serialiser

Transport

22

Мобильное приложениеSERVICE-ORIENTED ARCHITECTURE

SERVICE

22

SERVICE

TRANSPORT

Мобильное приложениеSERVICE-ORIENTED ARCHITECTURE

22

SERVICE

TRANSPORT

SERIALIZERPARSER

Мобильное приложениеSERVICE-ORIENTED ARCHITECTURE

22

SERVICE

TRANSPORT

SERIALIZERPARSER

Мобильное приложениеSERVICE-ORIENTED ARCHITECTURE

22

SERVICE

DATABASE

Мобильное приложениеSERVICE-ORIENTED ARCHITECTURE

DAO

22

Мобильное приложениеSERVICE-ORIENTED ARCHITECTURE

SERVICESERVICE SERVICE

22

SERVICESERVICE SERVICE

SERVICE LAYER

Мобильное приложениеSERVICE-ORIENTED ARCHITECTURE

22

SERVICESERVICE SERVICE

SERVICE LAYER

Мобильное приложениеSERVICE-ORIENTED ARCHITECTURE

CONTROLLER

23

Интерлюдия: многопоточностьCALLBACK HELL

Callback Hell

24

24

T1

T2

T3

T4

Callback Hell

24

T1

T2

T3

T4

CONTROLLER

Callback Hell

24

T1

T2

T3

T4

CONTROLLER SERVICE

Callback Hell

24

T1

T2

T3

T4

CONTROLLER SERVICE SERIALIZER

Callback Hell

24

T1

T2

T3

T4

CONTROLLER SERVICE SERIALIZER SERVICE

Callback Hell

24

T1

T2

T3

T4

CONTROLLER SERVICE SERIALIZER SERVICE TRANSPORT

Callback Hell

24

T2

T1

T3

T4

CONTROLLER SERVICE SERIALIZER SERVICE TRANSPORT

Callback Hell

24

T2

T1

T3

T4

CONTROLLER SERVICE SERIALIZER SERVICE TRANSPORT PARSER

Callback Hell

24

T2

T1

T3

T4

CONTROLLER SERVICE SERIALIZER SERVICE TRANSPORT PARSER

Callback Hell

24

T2

T1

T3

T4

CONTROLLER SERVICE SERIALIZER SERVICE TRANSPORT DBPARSER

Callback Hell

24

T2

T1

T3

T4

CONTROLLER SERVICE SERIALIZER SERVICE TRANSPORT DBPARSER

Callback Hell

24

T2

T1

T3

T4

CONTROLLER SERVICE SERIALIZER SERVICE TRANSPORT …PARSER DB

Callback Hell

24

T2

T1

T3

T4

SERVICE TRANSPORT PARSER DBSERVICE SERVICE SERVICE

Callback Hell

24

T2

T1

T3

T4

SERVICE TRANSPORT PARSER DBSERVICE SERVICE SERVICE

RESULT

Callback Hell

24

T2

T1

SERVICE PARSERSERVICE SERVICE DB SERVICE …TRANSPORT

Callback Hell

24

T2

T1

SERVICE PARSERSERVICE SERVICE DB SERVICE …TRANSPORT

OPERATION

Callback Hell

Operation

25

id result = transport.obtain(parameters)

id object = parser.parse(result)

db.save(object)

return object

Operation

26

dispatch_async(background_queue, ^{

id result = transport.obtain(parameters)

id object = parser.parse(result)

db.save(object)

dispatch_async(main_queue, ^{

completionBlock(object)

})

})

Operation

27

– (void)main {

id result = transport.obtain(parameters)

id object = parser.parse(result)

db.save(object)

completionBlock(object)

}

@interface Operation : NSOperation…@implementation Operation

Агенда

- Опрос аудитории

- Слои

- Сервер

- Протокол

- Мобильное приложение

- Пример

28

00

ПримерSERVICE LAYER

01

Transport

02

Transport

- CRUD ~ URL endpoint + HTTP method + parameters

- ~ Web service base URL

- Семафор в качестве «выпрямителя» потоков

SYNCHRONOUS

03

/**Операция«Получитьколлекциюсущностей».Пример:

GEThttp://api.customer.com/v1/entitites$headers

@paramparameters-параметрызапроса.@seeTransportationParameters

@returnВозвращаетрезультатвыполненияоперации.*/-(TransportationResult*)obtainAllWithParameters:(TransportationParameters*)parameters;

TransportSYNCHRONOUS

03

/**Операция«Обновитьзначениесвойствасущности».Пример:

PATCHhttp://api.customer.com/v1/entitites/{entityId}/{property}$headers{$body_parameters}

@paramentityId-идентификаторсущности;@paramproperty-названиесвойствасущности;@paramparameters-параметрызапроса.@seeTransportationParameters

@returnВозвращаетрезультатвыполненияоперации.*/

-(TransportationResult*)updateWithId:(NSString*)entityIdproperty:(NSString*)propertyparameters:(TransportationParameters*)parameters;

TransportSYNCHRONOUS

04

Parser

05

Parser

- Наличие объекта = наличие всех его обязательных полей

- Для пользователя ошибки «парсер не смог распознать данные» и «данные не пришли» будут иметь одинаковые последствия

- Не стоит городить непробиваемую «оборону»

- Приложению нужны объекты, а не топология

BLIND

06

ParserBLIND

@interfaceParser<__covariantEntity>:NSObject-(NSArray*)parseAll:(id)json;

-(BOOL)parsable:(NSDictionary*)json;-(Class)objectClass;-(NSDictionary*)mapping;-(Entity)sanitize:(Entity)object;-(Entity)fulfill:(Entity)objectfrom:(NSDictionary*)json;@end

07

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

Entity• id • text • note

08

ParserEXAMPLE

@interfaceParser<__covariantEntity>:NSObject-(NSArray*)parseAll:(id)json;

-(BOOL)parsable:(NSDictionary*)json;-(Class)objectClass;-(NSDictionary*)mapping;-(Entity)sanitize:(Entity)object;-(Entity)fulfill:(Entity)objectfrom:(NSDictionary*)json;@end

– parseAll:

09

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

– parseAll:

10

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

11

ParserEXAMPLE

@interfaceParser<__covariantEntity>:NSObject-(NSArray*)parseAll:(id)json;

-(BOOL)parsable:(NSDictionary*)json;-(Class)objectClass;-(NSDictionary*)mapping;-(Entity)sanitize:(Entity)object;-(Entity)fulfill:(Entity)objectfrom:(NSDictionary*)json;@end

– parseable:

12

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

– parseable:

12

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

– parseable:

12

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

– parseAll:

12

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

– parseAll:

12

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

12

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

– parseAll:

12

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

– parseAll:

12

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

– parseable:

12

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

– parseable:

13

ParserEXAMPLE

@interfaceParser<__covariantEntity>:NSObject-(NSArray*)parseAll:(id)json;

-(BOOL)parsable:(NSDictionary*)json;-(Class)objectClass;-(NSDictionary*)mapping;-(Entity)sanitize:(Entity)object;-(Entity)fulfill:(Entity)objectfrom:(NSDictionary*)json;@end

14

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

– parseable:Entity• id = "3" • text = "annotation" • note = nil

14

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

Entity• id = "3" • text = "annotation" • note = nil

– sanitize:

14

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

Entity• id = "3" • text = "annotation" • note = nil

– sanitize:

14

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

Entity• id = 3 • text = "annotation" • note = nil

– sanitize:

14

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

Entity• id = 3 • text = "annotation" • note = nil

– fulfill:

– parseAll:

15

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

– parseAll:

15

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

15

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

– parseAll:

15

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

15

ParserEXAMPLE{"id":1,"dict":{"id":"3","text":"annotation"},"array":[{"id":4,"text":"description","note":"FYI"}]}

=> [Entity]

16

DAOШАБЛОН ПРОЕКТИРОВАНИЯ

17

DAO

- Взаимодействие с DAO посредством модельных объектов (Entity : NSObject) => изоляция

- Инжектируемость- Потокобезопасность

- «Соединение» с базой данных- Транзакционность

ИДЕОЛОГИЯ

18

DAO

- persist(Entity) -> BOOL

- persistAll(Array<Entity>) -> BOOL

- read(ID) -> Entity

- readAll() -> Array<Entity>

- erase(ID) -> BOOL

- eraseAll() -> BOOL

ИНТЕРФЕЙС

19

Entity TranslatorШАБЛОН ПРОЕКТИРОВАНИЯ

20

Entity Translator

Entity• id • text • note

=><=

{"id":4,"text":"description","note":"FYI"}

EntityDTO : NSDictionary

20

Entity Translator

Entity• id • text • note

=><=

ORMEntity• id • text • note

21

DAO TRANSLATOREntity Translator

@interfaceRealmTranslator:NSObject

-(RLMEntry*)toEntry:(id<Persistable>)entity;

-(id<Persistable>)toEntity:(RLMEntry*)entry;

-(NSString*)entryClass;

@end

22

DAO TRANSLATOREntity Translator

{

letdao:DAO=RealmDAO(translator:translator)

}

23

Entity TranslatorКОДОГЕНЕРАЦИЯ

24

Entity TranslatorКОДОГЕНЕРАЦИЯ

/**Последняятранзакция.

@jsonlast_transaction@mandatory@realmlastTransaction*/@property(…)Transaction*lastTransaction;

25

Service

26

Service

- Инстанциирование утилит (?)

- Набор виртуальных конструкторов

- Координация данных между утилитами

- Многопоточность, инстанциирование операций

- Асинхронный интерфейс для верхнего слоя UI

ОТВЕТСТВЕННОСТЬ

27

Service LayerИНВЕРТЕР ЗАВИСИМОСТЕЙ

28

Service Layer

- Инстанциирование сервисов

- Инжектирование сервисов

- Инжектирование очередей запросов

ОТВЕТСТВЕННОСТЬ

Итоги

- REST

- SOA

- Многопоточность = зло

- Пример реализации сервисного уровня

ВОПРОСЫ ЕСТЬ?ВОПРОСОВ НЕТ!

Егор Тафланидиet@redmadrobot.com

top related