Slide 1

Slide 1 text

EMBRACING CHANGE KYLE FULLER

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

POLLS

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

HOW DOES IT WORK?

Slide 12

Slide 12 text

GET /questions

Slide 13

Slide 13 text

DELETE /questions/{id}

Slide 14

Slide 14 text

GET /questions/{id}

Slide 15

Slide 15 text

POST /questions/{id}/choices/{choice_id}

Slide 16

Slide 16 text

POST /questions

Slide 17

Slide 17 text

APPLICATION WAS BUILT FROM AN OUT-OF-BAND SPECIFICATION

Slide 18

Slide 18 text

TIGHT COUPLING

Slide 19

Slide 19 text

WE WANT TO CHANGE SOMETHING.

Slide 20

Slide 20 text

YOUR BOSS FINDS YOU LATE ON A FRIDAY AFTERNOON

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

I'D LIKE TO...

Slide 23

Slide 23 text

> Add validation to create question with a minimum of 2 choices

Slide 24

Slide 24 text

> Add a minimum or maximum length to questions

Slide 25

Slide 25 text

> Change delete so only admins can delete questions

Slide 26

Slide 26 text

> Change delete so you can only delete your own questions

Slide 27

Slide 27 text

> Change delete so you can't delete the initial questions

Slide 28

Slide 28 text

> Change vote so you can only vote once per question

Slide 29

Slide 29 text

> Change vote so any new votes override old votes on the same question

Slide 30

Slide 30 text

> Add a new report question feature

Slide 31

Slide 31 text

THIS WILL TAKE SOME TIME...

Slide 32

Slide 32 text

BUSINESS LOGIC

Slide 33

Slide 33 text

I HAVE TO REWRITE X

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

"ANTICIPATING CHANGE IS ONE OF THE CENTRAL THEMES OF REST"

Slide 36

Slide 36 text

REPRESENTATIONAL STATE TRANSFER

Slide 37

Slide 37 text

OUR API https://polls.apiblueprint.org/

Slide 38

Slide 38 text

OUR API > Questions (affordance)

Slide 39

Slide 39 text

QUESTIONS > questions > create (affordance)

Slide 40

Slide 40 text

QUESTION > question > choices > delete (affordance) > report (affordance)

Slide 41

Slide 41 text

CHOICE > choice > votes (count) > vote (affordance)

Slide 42

Slide 42 text

SEMANTICS NOT IMPLEMENTATION DETAILS

Slide 43

Slide 43 text

No content

Slide 44

Slide 44 text

$ curl https://polls.apiblueprint.org/ {"questions_url": "/questions", "url": "/"}

Slide 45

Slide 45 text

HAL application/hal+json

Slide 46

Slide 46 text

No content

Slide 47

Slide 47 text

HAL $ curl https://polls.apiblueprint.org/ -H 'Accept: application/hal+json' { "_links": { "questions": { "href": "/questions" }, "self": { "href": "/" } } }

Slide 48

Slide 48 text

HAL $ curl https://polls.apiblueprint.org/questions/1 -H 'Accept: application/hal+json' { "question": "Favourite programming language?", "_links": {"self": {"href": "/questions/1"}}, "_embed": { "choices": [ { "_links": {"self": {"href": "/questions/1/choices/1"}}, "choice": "Swift", "votes": 483 } ] } }

Slide 49

Slide 49 text

$ curl https://polls.apiblueprint.org/questions -H 'Accept: application/hal+json' { "_links": { "first": {"href": "/questions"}, "self": {"href": "/questions"}, "next": {"href": "/questions?page=2"} "last": {"href": "/questions?page=2"}, }, }

Slide 50

Slide 50 text

SIREN application/siren+json

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

SIREN { "actions": [ { "name": "vote", "href": "/questions/1/choices/3", "method": "POST" } ] }

Slide 53

Slide 53 text

SIREN { "actions": [ { "name": "create", "method": "POST", "type": "application/json", "href": "/questions", "fields": [ { "name": "question", "type": "text", "title": "Question" }, { "name": "choices", "type": "array[text]", "title": "Choices" } ] } ] }

Slide 54

Slide 54 text

HYPERDRIVE

Slide 55

Slide 55 text

API BLUEPRINT + HYPERDRIVE

Slide 56

Slide 56 text

API BLUEPRINT ## Questions Collection [/questions] ### Create a new question [POST] + Relation: create + Request (application/json) + Attributes + question (string, required) + choices (array[string], required) + Response 201 (application/json) + Attributes (Question)

Slide 57

Slide 57 text

HYPERDRIVE hyperdrive.enter("https://polls.apiblueprint.org/") { result }

Slide 58

Slide 58 text

REPRESENTOR

Slide 59

Slide 59 text

DEMO

Slide 60

Slide 60 text

hyperdrive.enter("http://localhost:8000/") // follow the 'questions' transition .flatMap { hyperdrive.request($0.transitions["questions"]) } // Follow the 'create' transition .flatMap { hyperdrive.request($0.transitions["create"], attributes: [ "question": "types of egg", "choices": ["hard boiled eggs", "soft boiled eggs"] ]) } // Select the first choice .map { $0.representors["choices"]!.first! } // Follow the 'vote' transition .flatMap { hyperdrive.request($0.transitions["vote"]) }

Slide 61

Slide 61 text

DEMO

Slide 62

Slide 62 text

/// Returns whether the user may create a question var canCreateQuestion: Bool { return representor.transitions["create"] != nil }

Slide 63

Slide 63 text

/// Returns whether the user may delete the question at the given index func canDeleteQuestion(index: Int) -> Bool { let transition = questions?[index].transitions["delete"] return transition != nil }

Slide 64

Slide 64 text

No content

Slide 65

Slide 65 text

import JSONSchema let schema = Schema([ "type": "object", "properties": [ "question": ["type": "string"], "choices": ["type": "array", "minItems": 2], ], ]) schema.validate([ "question": "Favourite Conference?", "choices": [ "MBLTDev 2015" ] ])

Slide 66

Slide 66 text

> the-hypermedia-project / Hyperdrive > kylef / Starship, RxHyperdrive, JSONSchema.swift > apiaryio / polls-app, polls-api

Slide 67

Slide 67 text

> kylefuller > kyle @ fuller.li > fuller.li / slides