Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Stateful ElePHPant

The Stateful ElePHPant

State machines and the state pattern seem to be pretty underestimated in the PHP world. Most examples found are of doors and other objects that have no application in most of our projects. Starting the talk I will be explaining what the state pattern is and how it's used in a game. Then we'll be discovering what this can do for us in the world of web applications. Following that we're taking a brief look at the state machine, how it's different from the pattern and why it's useful to us.

Instead of simply presenting you these concepts I prefer doing a live coding session so we can explore the possibilities together. You will be walking away from this talk with a solid understanding of the state pattern/state machine and the knowledge on when you should apply these concepts. There will also be plenty of time to have your questions answered.

At the end of the presentation I will also provide a list of useful resources that can help you introduce these concepts within your own projects.

Rick Kuipers

May 20, 2016
Tweet

More Decks by Rick Kuipers

Other Decks in Programming

Transcript

  1. THE STATEFUL ELEPHPANT
    RICK KUIPERS / @RSKUIPERS
    @PHPSTORMTIPS

    View Slide

  2. THE STATEFUL ELE ANT
    PHP
    C# RUBY
    PYTHON SCALA
    JAVA
    JAVASCRIPT
    GO
    PASCAL

    View Slide

  3. ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>+
    +.>+.+++++++..+++.>++.<<+++++++++++++++.>.++
    +.------.--------.>+.>.
    HAI 1.2
    CAN HAS STDIO?
    VISIBLE "HAI WORLD!"
    KTHXBYE

    View Slide

  4. TOPICS
    ! STATE
    ! STATE DIAGRAM
    ! STATE MACHINES
    ! STATE PATTERN

    View Slide

  5. STATE

    View Slide

  6. THE GAME

    View Slide

  7. STATE DIAGRAM

    View Slide

  8. ini#al state
    10101
    accep#ng state

    01110
    DETERMINISTIC FINITE AUTOMATON
    state
    transi#on
    ACCEPTOR

    View Slide

  9. DETERMINISTIC FINITE AUTOMATON
    TRANSDUCER
    MEALY

    View Slide

  10. DETERMINISTIC FINITE AUTOMATON
    TRANSDUCER
    MEALY

    View Slide

  11. FINITE STATE ACCEPTOR

    View Slide

  12. STATUSES
    PENDING
    NEW COMPLETED CANCELED REFUNDED

    View Slide

  13. DETERMINISTIC FINITE AUTOMATON
    ACCEPTOR

    View Slide

  14. $order = $this->getOrder();
    $order->setStatus(Order::STATUS_COMPLETED);

    View Slide

  15. [
    'transitions' => [
    'create' => [
    'from' => ['new'],
    'to' => 'pending',
    ],
    'cancel' => [
    'from' => ['new', 'pending'],
    'to' => 'canceled',
    ],
    'complete' => [
    'from' => ['pending'],
    'to' => 'completed',
    ],
    'refund' => [
    'from' => ['completed'],
    'to' => 'refunded',
    ],
    ],
    ];

    View Slide

  16. $order = $this->getOrder();
    $stateMachine = $stateMachineFactory->get($order);
    $stateMachine->apply('complete');

    View Slide

  17. $order = $this->getOrder();
    $stateMachine = $stateMachineFactory->get($order);
    $stateMachine->apply('complete');
    $stateMachine->apply('cancel');
    PHP FATAL ERROR: UNCAUGHT SM\SMEXCEPTION: TRANSITION "CANCEL" CANNOT BE
    APPLIED ON STATE "COMPLETED" OF OBJECT "ORDER" WITH GRAPH "DEFAULT"

    View Slide

  18. Complete Refund Cancel
    $sm->can('cancel');
    true
    $sm->can('refund');
    false
    $sm->can('complete');
    true

    View Slide

  19. Complete Refund Cancel
    $sm->can('cancel');
    false
    $sm->can('refund');
    true
    $sm->can('complete');
    false

    View Slide

  20. Complete Refund Cancel
    $sm->can('cancel');
    false
    $sm->can('refund');
    false
    $sm->can('complete');
    false

    View Slide

  21. [
    'callbacks' => [
    'after' => [
    'refund' => [
    ['Inventory\Callback\Refund', 'onRefund'],
    ],
    ],
    ],
    ];

    View Slide

  22. THE STATE PATTERN

    View Slide

  23. if (cursors.left.isDown) {
    player.body.velocity.x = -150;
    player.scale.x = 1;
    player.animations.play('left');
    if (player.body.touching.down) {
    state.text = 'running';
    }
    } else if (cursors.right.isDown) {
    player.body.velocity.x = 150;
    player.scale.x = -1;
    player.animations.play('right');
    if (player.body.touching.down) {
    state.text = 'running';
    }
    } else {
    player.animations.stop();
    player.frame = 2;
    if (player.body.touching.down) {
    state.text = 'idling';
    }
    }
    if (game.input.keyboard.isDown(Phaser.Keyboard.SPACEBAR) && player.body.touching.down) {
    player.body.velocity.y = -350;
    state.text = 'jumping';
    }

    View Slide

  24. THE GAME WITH STATE PATTERN

    View Slide

  25. var Elephpant = function(player) {
    this.state = new Idling(this, player);
    this.shoot = function() {
    // Shoot gigantic fireball
    };
    this.transitionTo = function(state) {
    this.state = state;
    };
    this.handle = function(input) {
    this.state.process(input);
    this.state.display(input);
    };
    };

    View Slide

  26. var Idling = function(elephpant, player) {
    this.display = function() {
    player.body.velocity.x = 0;
    player.animations.stop();
    player.frame = 2;
    };
    this.process = function(input) {
    if (input.left.isDown || input.right.isDown) {
    elephpant.transitionTo(new Running(elephpant, player));
    return;
    }
    if (input.up.isDown) {
    elephpant.transitionTo(new Jumping(elephpant, player));
    return;
    }
    if (input.space.isDown) {
    elephpant.shoot();
    }
    };
    };

    View Slide

  27. var Jumping = function(elephpant, player) {
    this.display = function() {
    if (player.body.touching.down) {
    player.body.velocity.y = -350;
    }
    };
    this.process = function(input) {
    if (!input.up.isDown && player.body.touching.down) {
    elephpant.transitionTo(new Idling(elephpant, player));
    }
    };
    };

    View Slide

  28. View Slide

  29. THE STATE STRATEGY PATTERN?

    View Slide

  30. STRATEGY PATTERN
    ! Tries to achieve similar result for input
    ! Strategies can’t transition to other

    strategies
    ! Strategy processes the input and gives

    output to the caller
    STATE PATTERN
    ! Result can be completely different
    ! States can trigger transitions to other

    states
    ! State controls the behaviour of its

    wrapper

    View Slide

  31. WHY SHOULD WE CARE?

    View Slide

  32. CHECKOUT
    PAYMENT
    DETAILS REVIEW

    View Slide

  33. EXAMPLE

    View Slide

  34. View Slide

  35. View Slide

  36. RECAP
    FINITE STATE ACCEPTOR STATE PATTERN
    ! Monolith
    ! Acceptor (pa9ern matching)
    ! Is this a valid transi#on?
    ! Transi#ons are set in stone
    ! Callbacks are easy to implement
    ! Object Oriented
    ! Transducer (controlling)
    ! Different behaviour per state
    ! Reduces the amount of condi#onals

    View Slide

  37. PACKAGES
    DON’T REINVENT THE WHEEL
    ! https://github.com/winzou/state-machine
    ! https://github.com/Sylius/SyliusFlowBundle
    ! https://github.com/rskuipers/stateful-elephpant
    ! https://github.com/rskuipers/stateful-elephpant-talk
    ! https://github.com/rskuipers/stateful-elephpant-expressive

    View Slide

  38. 4
    @RSKUIPERS
    RICK KUIPERS
    QUESTIONS?
    [email protected]
    HTTPS://JOIND.IN/TALK/26C09

    View Slide