Slide 1

Slide 1 text

UNIDIRECTIONAL WHY IT IS IMPORTANT?

Slide 2

Slide 2 text

DEBUGGING IS TWICE AS HARD AS WRITING A PROGRAM IN THE FIRST PLACE. Brian Kernighan "The Elements of Programming Style" (1980)

Slide 3

Slide 3 text

WHY?

Slide 4

Slide 4 text

CODE HAPPINESS

Slide 5

Slide 5 text

CODE EVOLUTION

Slide 6

Slide 6 text

IMPLICIT IMPACT

Slide 7

Slide 7 text

OK, SO?

Slide 8

Slide 8 text

COST

Slide 9

Slide 9 text

TIME

Slide 10

Slide 10 text

QUALITY

Slide 11

Slide 11 text

SO?

Slide 12

Slide 12 text

WHY SUFFER?

Slide 13

Slide 13 text

THIS IS SOFTWARE

Slide 14

Slide 14 text

WE CAN DO BETTER

Slide 15

Slide 15 text

IMPOSSIBLE STATES https://www.youtube.com/watch?list=PLglJM3BYAMPH2zuz1nbKHQyeawE4SN0Cd&v=IcgmSRJHu_8

Slide 16

Slide 16 text

struct Quiz { let questions: [String] let answers: [String?] }

Slide 17

Slide 17 text

struct Quiz { struct Question { let text: String let answer: String? } let questions: [Question] }

Slide 18

Slide 18 text

struct Quiz { struct Question { let text: String let answer: String? } let questions: [Question] let current: Question }

Slide 19

Slide 19 text

struct Quiz { struct Question { let text: String let answer: String? } let previousQuestions: [Question] let current: Question let nextQuestions: [Question] }

Slide 20

Slide 20 text

INTENT / ACTION SEPARATION

Slide 21

Slide 21 text

class APIClient { func requestQuiz() -> Future } let apiClient = APIClient() // or DI var quiz: Quiz? func refreshQuiz() { apiClient.requestQuiz().onComplete { quiz = $0 } }

Slide 22

Slide 22 text

enum Effects { case requestQuiz((Quiz) -> Void) } func refreshQuiz() -> Effects { return Effects.requestQuiz { quiz = $0 } }

Slide 23

Slide 23 text

func perform(effect: Effects) { switch effect { case .requestQuiz(let callback): apiClient.requestQuiz() .onComplete(action: callback) } }

Slide 24

Slide 24 text

enum Effects { case requestQuiz((Quiz) -> Effects) case updateQuiz(Quiz) } func refreshQuiz() -> Effects { return Effects.requestQuiz(Effects.updateQuiz) }

Slide 25

Slide 25 text

func perform(effect: Effects) { switch effect { case .requestQuiz(let callback): apiClient.requestQuiz().onComplete { perform(effect: callback($0)) } case .updateQuiz(let newQuiz): quiz = newQuiz } }

Slide 26

Slide 26 text

☝ELM https://guide.elm-lang.org

Slide 27

Slide 27 text

TOOLING

Slide 28

Slide 28 text

https://github.com/zalmoxisus/remotedev

Slide 29

Slide 29 text

print(effect)

Slide 30

Slide 30 text

CQRS https://martinfowler.com/bliki/CommandQuerySeparation.html

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

LIMITED SCOPE

Slide 33

Slide 33 text

REACT https://facebook.github.io/react/docs/thinking-in-react.html

Slide 34

Slide 34 text

STATE / DATA SEPARATION

Slide 35

Slide 35 text

struct Quiz { struct Question { let text: String let answer: String? } let previousQuestions: [Question] let current: Question let nextQuestions: [Question] }

Slide 36

Slide 36 text

class ViewController: UIViewController { var quiz: Quiz? }

Slide 37

Slide 37 text

class ViewController: UIViewController { struct Props { let questions: [( text: String, isAnswered: Bool )] } }

Slide 38

Slide 38 text

extension ViewController.Props { init(quiz: Quiz) { let allQuestions = quiz.previousQuestions + [quiz.current] + quiz.nextQuestions self.questions = allQuestions.map { ($0.text, $0.answer != nil) } } }

Slide 39

Slide 39 text

REDUX https://egghead.io/courses/building-react-applications-with-idiomatic-redux

Slide 40

Slide 40 text

EFFECT ACTION STATE PROPS

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

QUESTIONS? [email protected]