Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової...

48
Сам собі паблішер. Від сату ігрово студі до універсального back-end провадера і сервісу публікаці ігор. Leonid Kuzmin lead developer Eforb EFORB GAMEBOX

Upload: lviv-startup-club

Post on 05-Aug-2015

180 views

Category:

Business


1 download

TRANSCRIPT

Page 1: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Сам собі паблішер. Від саиту ігровоі студіі до універсального back-end проваидера і сервісу

публікаціі ігор.

Leonid Kuzminlead developer Eforb

EFORB GAMEBOX

Page 2: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу
Page 3: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу
Page 4: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу
Page 5: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

REST and RESTful API RESTful API adhere to the REST architectural constraints.

REST is not a protocol, but architectural style

Page 6: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

• Client-Server – determined by environment

REST Architectural Constraints applied to web services

REST and RESTful API

Page 7: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

• Client-Server – determined by environment

• Stateless – data needed for authentication included in every request headers (e.g. Cookies)

REST Architectural Constraints applied to web services

REST and RESTful API

Page 8: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

• Client-Server – determined by environment

• Stateless – data needed for authentication included in every request headers (e.g. Cookies)

• Cacheable – HTTP cache control headers

REST Architectural Constraints applied to web services

REST and RESTful API

Page 9: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

• Client-Server – determined by environment

• Stateless – data needed for authentication included in every request headers (e.g. Cookies)

• Cacheable – HTTP cache control headers

• Layered system – reverse proxy server could be used

REST Architectural Constraints applied to web services

REST and RESTful API

Page 10: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

• Client-Server – determined by environment

• Stateless – data needed for authentication included in every request headers (e.g. Cookies)

• Cacheable – HTTP cache control headers

• Layered system – reverse proxy server could be used

• Uniform interface

REST Architectural Constraints applied to web services

REST and RESTful API

Page 11: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

• Client-Server – determined by environment

• Stateless – data needed for authentication included in every request headers (e.g. Cookies)

• Cacheable – HTTP cache control headers

• Layered system – reverse proxy server could be used

• Uniform interface

REST Architectural Constraints applied to web services

- Identification of resources – URI

REST and RESTful API

Page 12: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

• Client-Server – determined by environment

• Stateless – data needed for authentication included in every request headers (e.g. Cookies)

• Cacheable – HTTP cache control headers

• Layered system – reverse proxy server could be used

• Uniform interface

REST Architectural Constraints applied to web services

- Identification of resources – URI

- Self-descriptive messages – HTTP headers: cache control headers, “Content-Type” header, “Accept” header

REST and RESTful API

Page 13: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

• Client-Server – determined by environment

• Stateless – data needed for authentication included in every request headers (e.g. Cookies)

• Cacheable – HTTP cache control headers

• Layered system – reverse proxy server could be used

• Uniform interface

REST Architectural Constraints applied to web services

- Identification of resources – URI

- Self-descriptive messages – HTTP headers: cache control headers, “Content-Type” header, “Accept” header

- Standard HTTP methods: POST, GET, PUT, DELETE and HTTP Response codes

REST and RESTful API

Page 14: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

• Client-Server – determined by environment

• Stateless – data needed for authentication included in every request headers (e.g. Cookies)

• Cacheable – HTTP cache control headers

• Layered system – reverse proxy server could be used

• Uniform interface

REST Architectural Constraints applied to web services

- Identification of resources – URI

- Self-descriptive messages – HTTP headers: cache control headers, “Content-Type” header, “Accept” header

- Standard HTTP methods: POST, GET, PUT, DELETE and HTTP Response codes

- Resource entities can be filtered by referencing resources properties values in URI REST and

RESTful API

Page 15: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

This is not RESTfulPOST /createAccount

Request:

Cookie: ...

{name: Petro, email: [email protected]}

Response:

{name: Petro, email: [email protected]}

GET /getAllAccounts?name=Petro

Request:

Cookie: ...

Response:

[{name: Petro, email: [email protected]},

{name: admin, email: [email protected]}]

GET /findAccounts?name=Petro

Request:

Cookie: ...

Response:

[{name: Petro, email: [email protected]}]

GET /getAccount?id=1

Request:

Cookie: ...

Response:

{name: Petro, email: [email protected]}

POST /updateAccount

Request:

Cookie: ...

{id: 1, name: PetroP, email: [email protected]}

Response:

{name: PetroP, email: [email protected]}

POST /deleteAccount

Request:

Cookie: ...

{id: 1}

Response codes

Success: 200 OK

Fail: 200 OK {error: …}

Page 16: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

This is RESTful!

Page 17: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

POST /accounts

Request:

Cookie: ...

Content-Type: application/json

Accept: application/json

{name: Petro, email: [email protected]}

Response:

Cache-Control : private, max-age=0, no-cache

Content-Type: application/json

{name: Petro, email: [email protected]}

GET /accounts/1

Request:

Cookie: ...

Accept: application/json

Response:

Cache-Control : private, max-age=0, no-cache

Content-Type: application/json

{name: Petro, email: [email protected]}

GET /accounts

Request:

Cookie: ...

Accept: application/json

Response:

Cache-Control : private, max-age=0, no-cache

Content-Type: application/json

[{name: Petro, email: [email protected]},

{name: admin, email: [email protected]}]

GET /accounts?name=Petro

Request:

Cookie: ...

Accept: application/json

Response:

Cache-Control : private, max-age=0, no-cache

Content-Type: application/json

[{name: Petro, email: [email protected]}]

PUT /accounts/1

Request:

Cookie: ...

Accept: application/json

{name: PetroP, email: [email protected]}

Response:

Cache-Control : private, max-age=0, no-cache

Content-Type: application/json

{name: PetroP, email: [email protected]}

DELETE /accounts/1

Request:

Cookie: ...

Content-Type: application/json

Accept: application/json

Response codes

Success: 200 OK, 201 Created

Fail: 400 Bad Request, 404 Not Found, 403 Forbidden, 500 Internal Server Error

Page 18: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Calculated data in REST

Int sum (a, b)

{ return a + b; }

• GET /sum – collection of all integers' sums: [0, 1, 2, 3, ..., N, ...]

• GET /sum/N – collection of all sums of 2 and all integers: [2, 3, 4, ..., N, ...]

• GET/sum/N/M–N+M

• POST /account/1/leaderboard/2 {score: 50}

• GET /account/1/leaderboard/2 {score: 100}

• GET /leaderboard/2 [ { account_id: 1, score: 100, position: 2 },{ account_id: 2, score: 200, position: 1 }

Game Leaderboard [

{ account_id: 1, score: 50, game_id: 2 },

{ account_id: 1, score: 100, game_id: 2 },

{ account_id: 2, score: 150, game_id: 2 },

{ account_id: 2, score: 200, game_id: 2 }]

Page 19: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

RESTful: Pros and Cons

PROS

• Simply

• Consistent

• Easy to debug

• Scalable

Page 20: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

RESTful: Pros and Cons

PROS CONS

• Simply

• Consistent

• Easy to debug

• Scalable

• Strange

• Lack of support

• Stateless

• Not a protocol

Page 21: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

What we got from REST

• Direct mapping of resources to DB entities (SQL tables, NoSQL documents collections): POST /accounts => INSERT INTO accounts

Page 22: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

What we got from REST

• Direct mapping of resources to DB entities (SQL tables, NoSQL documents collections): POST /accounts => INSERT INTO accounts

• Same access policies for different authentication flows (Cookies authorization, HTTP basic authorization)

Page 23: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

What we got from REST

• Direct mapping of resources to DB entities (SQL tables, NoSQL documents collections): POST /accounts => INSERT INTO accounts

• Same access policies for different authentication flows (Cookies authorization, HTTP basic authorization)

• URI aliases (/accounts/1 => / me, /account/1/gamedata =>/my/gamedata)

Page 24: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

What we got from REST

• Direct mapping of resources to DB entities (SQL tables, NoSQL documents collections): POST /accounts => INSERT INTO accounts

• Same access policies for different authentication flows (Cookies authorization, HTTP basic authorization)

• URI aliases (/accounts/1 => / me, /account/1/gamedata =>/my/gamedata)

• Common design guidelines

Page 25: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

What we got from REST

• Direct mapping of resources to DB entities (SQL tables, NoSQL documents collections): POST /accounts => INSERT INTO accounts

• Same access policies for different authentication flows (Cookies authorization, HTTP basic authorization)

• URI aliases (/accounts/1 => / me, /account/1/gamedata => / my/gamedata)

• Common design guidelines

• Same back-end for external and internal services

Page 26: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

What we got from REST

• Direct mapping of resources to DB entities (SQL tables, NoSQL documents collections): POST /accounts => INSERT INTO accounts

• Same access policies for different authentication flows (Cookies authorization, HTTP basic authorization)

• URI aliases (/accounts/1 => / me, /account/1/gamedata => / my/gamedata)

• Common design guidelines

• Same back-end for external and internal services

• Common test flow

Page 27: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

REST API Testing

Test Unit = HTTP Verb + URI + Request headers + [Request Body]

HTTP Verb

URL

Request headers + [Request Body]

Test steps

1. Start the Application

2. Prepare test data in storage if needed

3. Perform HTTP API query

4. Check response headers and body

5. Check affected piece of data retrieved from storage directly or even through the REST API

Storage API could be stubbed and spied, in this case storage API calls should be checked on step 5.

Page 28: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Our API Building Codex

1. Everything is a collection

Page 29: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Our API Building Codex

1. Everything is a collection

2. Every collection has CRUD (POST, GET, PUT, DELETE)

Page 30: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Our API Building Codex

1. Everything is a collection

2. Every collection has CRUD (POST, GET, PUT, DELETE)

3. Use HTTP response codes

Page 31: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Our API Building Codex

1. Everything is a collection

2. Every collection has CRUD (POST, GET, PUT, DELETE)

3. Use HTTP response codes

4. Filter and pagination through URI params

Page 32: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Our API Building Codex

1. Everything is a collection

2. Every collection has CRUD (POST, GET, PUT, DELETE)

3. Use HTTP response codes

4. Filter and pagination through URI params

5. API version in URI

Page 33: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Our API Building Codex

1. Everything is a collection

2. Every collection has CRUD (POST, GET, PUT, DELETE)

3. Use HTTP response codes

4. Filter and pagination through URI params

5. API version in URI

6. Communicate with developers

Page 34: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Our API Building Codex

1. Everything is a collection

2. Every collection has CRUD (POST, GET, PUT, DELETE)

3. Use HTTP response codes

4. Filter and pagination through URI params

5. API version in URI

6. Communicate with developers

7. Documentation in code and tests

Page 35: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Our API Building Codex

1. Everything is a collection

2. Every collection has CRUD (POST, GET, PUT, DELETE)

3. Use HTTP response codes

4. Filter and pagination through URI params

5. API version in URI

6. Communicate with developers

7. Documentation in code and tests

8. No exceptions

Page 36: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Our API Building Codex

1. Everything is a collection

2. Every collection has CRUD (POST, GET, PUT, DELETE)

3. Use HTTP response codes

4. Filter and pagination through URI params

5. API version in URI

6. Communicate with developers

7. Documentation in code and tests

8. No exceptions

9. No exceptions for “No exceptions”

Page 37: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

How games are published

Traditional Way Our Way

• Sign contract

• Satisfy publisher requirements

• Deploy game somewhere and providelink to publisher or send game archivedirectly

• Receive profit according to contract

• Register, fill billing info

• Fill game description fields, upload game archive through API

• Game appears in available gameslist for clients

• Start earning from ads and transactions

Page 38: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Our publishing way vs traditional way

Increased time between complete game and

actual publishing

Almost immediate game publishing

You need to implement and maintain back-end

for your games

Back-end services included

You need to implement monetization (ads or transactions)

Ads are served by our service, payment system

could be integrated with API. You receive profit

share.

Payment reports are often poor Full reports from ad providers and payment

systems

You need to maintain your own deploy cycle We have sandbox mode where you can view

your game before actual publishing.

Deployment API can be

Traditional Way Our Way

Page 39: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Embedding to third-party WEB resources

• IFrame

• Construct application on the fly on page with JS

• Subdomain with third-party wrapper

Page 40: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Embedding: IFrame

PROS

• Easy and obvious

• No cross-domain requests

• Client can control own page view

• Client can control own page view

• No conflicts with client's JS and CSS

Page 41: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Embedding: IFrame

PROS CONS

• Easy and obvious

• No cross-domain requests

• Client can control own page view

• Client can control own page view

• No conflicts with client's JS and CSS

• Client should be explicitlyidentified in each AJAX request

• Client can't customizeour application view

• Third-party cookiesbrowser policies

• No direct links to ourapplication's subpages

• Increased page construction time

Page 42: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Embedding: Subdomain

PROS

• No third-party cookies

• Client identified by domain

• No cross-domain requests

• Direct links to our applicationsubpages

• Less page construction time

• No conflicts with client's JS and CSS

Page 43: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Embedding: Subdomain

PROS CONS

• No third-party cookies

• Client identified by domain

• No cross-domain requests

• Direct links to our applicationsubpages

• Less page construction time

• No conflicts with client's JS and CSS

• Server configuration on theside of Client

• Client can't customize application view by own CSS or JS

• Client can't customize own views in wrapper

Page 44: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Embedding: Construct on the fly with JS

PROS

• No third-party cookies

• Client identified by domain

• No cross-domain requests

• Client can customize our application view

• Client can control own page

• Direct links to our applicationsubpages

Page 45: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Embedding: Construct on the fly with JS

PROS CONS

• No third-party cookies

• Client identified by domain

• No cross-domain requests

• Client can customize our application view

• Client can control own page

• Direct links to our applicationsubpages

• Increased page construction time

• Restricting customization of our application by Client'sCSS

• Isolating our application from client's JS

Page 46: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Construct on the fly solutions• Increased page construction time – pre-

rendered HTML

• Restricting customization of our application's CSS – random dynamic prefix for CSS

CSSclient.css.tpl: .{{placeholder}}_class {color: red;}GET /client.css .SOME_RANDOM_VALUE_class {color: red;}

JSapp.js.tpl: function App (cssPrefix) {var container = document.createElement('div');container.className = cssPrefix + '_class';}new App({{placeholder}});GET app.js…new App(‘SOME_RANDOM_VALUE’);

• Isolating our application from client's JS – wrap all code in closure, do not touch existing objects (internal browser objects, DOM objects etc.)

(function () {//all application code here})();

var container = document.createElement('div');

container.remove = function () {…}; //wrong

function remove (element) {…} //right

Page 47: Леонід Кузьмін “Сам собі паблішер. Від сайту ігрової студії до універсального back-end провайдера і сервісу

Our technologies and tools

• Back-end

• Front-end

- Node.js (Sails.js, pm2, Grunt)

- PostgreSQL

- HTML 5, CSS3

- Require.js

- Google Closure Compiler + Almond.js for production build