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

Functional Application Design in PHP

Functional Application Design in PHP

A review of contemporary application design in PHP, and the over-reliance on object-orientation to solve all problems. A major alternative to this paradigm, functional programming, is poorly supported in PHP, however there is still a lot of architectural inspiration we can derive from functional languages.

Michael John Burgess

January 24, 2014
Tweet

Other Decks in Programming

Transcript

  1. FUNCTIONAL APPLICATION
    DESIGN IN PHP
    Michael J. Burgess
    @mjburgess
    #fadphp

    View full-size slide

  2. ABSTRACT
    THIS TALK WILL…
    • review “contemporary application design in PHP”
    • present “a major alternative […], functional programming”
    • discuss “architectural inspiration we can derive from functional
    languages”
    • conclude
    functional design has much better ‘performance’
    under ideal conditions

    View full-size slide

  3. ABSTRACT
    OVERVIEW
    • Introduction
    • What is Application Design?
    • A History of Application Design in PHP
    • Problem
    • How do we do better?
    • How do you measure the performance of a design paradigm?
    • How does the present paradigm (and alternatives) perform?
    • Idea
    • Functional design has better performance under ideal conditions
    • Details
    • Conclusions

    View full-size slide

  4. INTRODUCTION
    WHAT IS APPLICATION DESIGN?
    • Patterns in problems become themselves problems
    $a, $b

    $weight, $height

    $weightKg, $heightFt …
    one file

    many files

    many functions/file

    one class/file …
    • Design paradigms (

    ) distribute this labour (eg. debugging $a)
    • Design paradigms (

    ) map problem domain to program domain
    • Design (specializing

    ) is cognitive (‘conceptual’) labour

    View full-size slide

  5. INTRODUCTION
    WHAT IS APPLICATION DESIGN?
    Linear Procedural OO
    A Person $name = ‘M’;
    $age = 24;
    [‘name’ => ‘M’,
    ‘age’ => 24 ]
    new Person(‘M’, 24)
    An Event switch callback observer
    Protection $pwd == $password is_allowed($pwd) new ACL()->check($U)
    HTTP State $_POST get_post() $request->getPost()

    View full-size slide

  6. INTRODUCTION
    WHAT IS APPLICATION DESIGN?
    • the aim of design is to minimize spare complexity
    ie. complexity not due to the language or the problem domain
    • Your application design should be as complex as your problem domain
    • too simple => complexity hiding => making careless assumptions
    • too complex => difficult to understand => difficult to reason about
    • Paradigms usually sold on a ‘spare complexity economy’
    • ‘Spare complexity’ is the complexity which arises when mapping the problem domain
    to program domain
    • A ‘spare complexity economy’ is therefore how paradigms change how complex this
    mapping becomes for different kinds of application

    View full-size slide

  7. 0 10 20 30 40 50 60 70 80 90 100
    Physics Simulations
    HTTP Apps
    Games
    Concurrent Apps
    Linear Proceedural OO Functional
    INTRODUCTION
    SPARE COMPLEXITY

    View full-size slide

  8. INTRODUCTION
    WHAT IS APPLICATION DESIGN?
    • The spare complexity economy for HTTP Applications underdetermines our
    paradigm choice
    • Web Application design is an ‘aparadigmatic’ case.
    • Most problems may be phrased on way or another without incurring additional spare
    complexity (nb. more code != more spare complexity!)
    • So, what other important measures of paradigm ‘performance’ are there?
    • Planning (client requirements, technical architecture, integration…),
    • Programming (static requirements, dynamic requirements, new requirements, …),
    • Maintenance (misapplied rules, broken code, …)
    • Describe the difficulty of these (for a programmer) as ‘conceptual labour’;
    this translates into training difficulty, time, cost, etc.

    View full-size slide

  9. 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%
    OO
    Proceedural
    Linear
    Planning Programming Maintaining
    INTRODUCTION
    CONCEPTUAL LABOUR BREAKDOWN

    View full-size slide

  10. ie., where do the ‘Conceptual Labour’ numbers come from?
    • Phenomenology of Programming
    • Also, phenomenology of planning, of maintaining, etc. which require different
    analyses
    • Reasoning vs Compiling
    • Conceptual Models
    • Non-conscious reasoning
    • State Change and Execution Flow
    PROBLEM
    MEASURING PARADIGM PERFORMANCE

    View full-size slide

  11. PROBLEM
    ASSESSING CURRENT BEST PRACTICE
    • What is our present paradigm?
    • Object Orientation != Good Programmer
    • correlation != causation
    • Object Orientation vs Type Orientation
    • Dependency Injection: Hidden Type Orientation?
    • How do our present paradigms perform?
    • Object Orientation
    • DI/Type Orientation

    View full-size slide

  12. PROBLEM
    ASSESSING FUNCTIONAL PROGRAMMING
    • What is the functional paradigm?
    • Key terms:
    • function f value vs. procedure vs. method
    • application f($x) ‘filling in the gaps’ vs. execution
    • Transformation [1, 2, 3] -> 6 relations vs. destructions
    • Composition f(g($x)) flow vs. steps
    • State is function application
    • Execution flow is function application …therefore…
    • State is a series of transformations
    • Execution flow is a kind of composition
    • How does the function paradigm perform?

    View full-size slide

  13. DETAILS
    FUNCTIONAL PROGRAMMING
    $input = [['Michael', 24], ['Lucy', 17]];
    function under18($x) { return $x < 18; }
    function getSecond(array $xs) { return $xs[1]; }
    $output = array_map('under18', array_map('getSecond', $input));
    $> [false, true]
    function lessThan($y) {
    return function ($x) use($y) { return $x < $y; };
    }
    function getNth($n) {
    return function (array $xs) use($n) { return $xs[$n - 1]; };
    }
    $output = array_map(lessThan(18), array_map(getNth(2), $input));
    $> [false, true]

    View full-size slide

  14. DETAILS
    FUNCTIONAL STATE
    //immutable lightweight data representation
    function newPerson($name, $age) { return [$name, $age]; }
    function personName($person) { return $person[0]; }
    function personAge($person) { return $person[1]; }
    function agePerson($person, $age = 1) {
    return newPerson(personName($person), personAge($person) + $age);
    }
    function fmtPerson($person) {
    return newPerson(ucwords(personName($person)), personAge($person));
    }
    $input = [newPerson('michael burgess', 24), newPerson('lucy rain', 17)];
    $output = array_map('fmtPerson', array_map('agePerson', $input));
    $> [['Michael Burgess', 25], ['Lucy Rain', 18]]

    View full-size slide

  15. DETAILS
    FUNCTIONAL EXECUTION FLOW
    function age($person) { return [ $person[0], $person[1] + 1 ]; }
    function format($person) { return [ ucwords($person[0]), $person[1] ]; }
    function mapWith($fn) {
    return function ($xs) use($fn) { return array_map($fn, $xs); };
    }
    function chain($flow, $xs) {
    foreach($flow as $fn) {
    $xs = $fn($xs); //cheating! (a little…)
    }
    return $xs;
    }
    $flow = [mapWith('age'), mapWith('format')];
    $input = [['michael burgess', 24], ['lucy rain', 17]];
    $output = chain($flow, $input);
    $> [['Michael Burgess', 25], ['Lucy Rain', 18]]

    View full-size slide

  16. DETAILS
    FUNCTIONAL DESIGN CONCLUSIONS
    • Programs use
    • Input state $input = [$_GET, $_POST]; ?
    • Arrays of functions $flow = [data(), model($x), view($y), …]; ?
    • A HOF defining flow $output = chain($flow, $input); ?
    • Light-weight data representation
    • Function combination to achieve novelty
    • Programs do not
    • mutate state ( have side effects )
    • have unpredictable execution flow

    View full-size slide

  17. DETAILS
    FUNCTIONAL DESIGN CONCLUSIONS
    • Problems
    • Function combination in PHP is poor & no dynamic definitions
    • No immutable data collection
    • No function-level polymorphism ( & no types )
    add(18, 1) is the same function as add(‘Hello ’, ‘World’)
    • No syntax sugar (function deferencing foo()(), …)
    • Decomposition support (eg. list) is poor
    • etc.
    • Solution
    • Combine Objects & Functional Programming: Object-Functional Programming

    View full-size slide

  18. DETAILS
    OBJECT-FUNCTIONAL DESIGN
    • What is a web application?
    • Input, ‘Application Context’
    • HTTP Context: [$_SERVER, $_GET, $_POST, $_COOKIE]
    • Static Context: [$_ENV, $_SESSION, $CONFIG]
    • Runtime Context: [$actions, $services]
    • Output
    • String (Template, View, HTML, etc.)
    • Transformation
    • ApplicationContext -> Response
    • [httpContext, $staticContext, $runtimeContext] -> Response -> string
    • AppContext -> Request (AppContext) -> Response (string) -> string
    • Request (AppContext) -> Action (Request, AppCtx) -> Response

    View full-size slide

  19. DESIGN
    OBJECT-FUNCTIONAL WEB APPS
    class ApplicationContext {
    private $httpContext, $staticContext, $runtimeContext;
    public function setHttpContext(HttpServer $s, HttpRequest $r) {}
    public function setStaticContext(array $env, HttpSession $s) {}
    public function setRuntimeContext(Router $r, ServiceManager $s) {}
    }
    class Request { private $appContext, $target; }
    class Response { private $string; }
    class ToAppContext implements IArrayTransform { public function __invoke() {} }
    class ToRequest implements IContextTransform {} //ToHttpRequest, ToCliRequest,...
    class ToAction implements IRequestTransform {} //ToRestfulAction, ...
    class ToResponse implements IActionTransform {} //ToHttpResonse, ToCliResponse, ...
    class ToOutput implements IResponseTransform {} //ToJsonOutput, ToXmlOutput, ...
    $flow = ['ToAppContext', 'ToRequest', 'ToAction', 'ToResponse', 'ToOutput'];
    $string = chainAppFlow($flow, $actions, [$_SERVER, $_GET, $_POST /*, ...*/]);
    echo $string;

    View full-size slide

  20. DESIGN
    OBJECT-FUNCTIONAL WEB APPS
    $actions = ['/' => function (Request $r) {
    return $r->getAppContext()->write('Hello World!');
    },];
    $router = function () { return '/'; }; $services = ['write' => 'print_r'];
    $flow = new Flow();
    $flow->then(function () use($actions, $services) {
    return new ToApplicationContext($actions, $services);
    });
    $flow->then(function () use($router) { return new ToRequest($router); });
    $flow->then(function () { return new ToAction(); });
    $flow->then(function () { return new ToResponse(); });
    $flow->then(function () { return new ToOutput(); });
    $flow->run([$_SERVER, $_GET, $_POST]);
    $> Hello World

    View full-size slide

  21. • If actions return Views and Models are Tod by the service layer then this
    has a 1:1 conceptual correspondence with MVC.
    • Objection: this is just MVC!
    • Zend2/Symfony/etc. basically have these steps in their dispatch structure.
    • Reply: that’s true. But they aren’t phrased to:
    • Transform rather than mutate (cf. problems of state)
    • Constrain execution flow with higer-order functions (__invokeables, etc.)
    • Expose execution flow (cf. xml files & type relations)
    DESIGN
    OBJECT-FUNCTIONAL WEB APPS

    View full-size slide

  22. 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%
    Functional
    O-Functional
    Type-O
    OO
    Proceedural
    Linear
    Planning Programming Maintaining
    CONCLUSIONS
    CONCEPTUAL LABOUR BREAKDOWN

    View full-size slide

  23. 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%
    Functional
    O-Functional
    Type-O
    OO
    Proceedural
    Linear
    Developing Expanding Dynamic
    CONCLUSIONS
    CODING LABOUR

    View full-size slide

  24. 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%
    Functional
    O-Functional
    Type-O
    OO
    Proceedural
    Linear
    Requirements Architecture Integration
    CONCLUSIONS
    PLANNING LABOUR

    View full-size slide

  25. 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%
    Functional
    O-Functional
    Type-O
    OO
    Proceedural
    Linear
    Planning Programming Maintaining
    CONCLUSIONS
    CONCEPTUAL LABOUR BREAKDOWN

    View full-size slide

  26. 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%
    Functional
    O-Functional
    Type-O
    OO
    Proceedural
    Linear
    Prq Parch Pint Cdev Cexp Cdyn Mdom Mprog
    CONCLUSIONS
    CONCEPTUAL LABOUR 8D-BREAKDOWN

    View full-size slide

  27. • Conceptual labour distributions describe the effect of the paradigm
    on a programmer
    • They imply team distributions, market requirements, …, i.e., ‘ideal
    conditions’ under which a paradigm will reach its inherent distribution
    • CL distributions do not imply fixed time, costs, etc.
    • CL distributions in conjunction with empirical distributions do imply time
    (for comparable problem domains)
    CONCLUSIONS
    ‘IDEAL CONDITIONS’

    View full-size slide

  28. 0
    100
    200
    300
    400
    500
    600
    Functional O-Functional Type-O OO Proceedural Linear
    $k/Lifetime/Application
    CONCLUSIONS
    LABOUR COMPARISON IS NOT ZERO SUM

    View full-size slide

  29. 0
    100
    200
    300
    400
    Functional O-Functional Type-O OO Proceedural Linear
    Programmers/100k People
    CONCLUSIONS
    LABOUR COMPARISON IS NOT ZERO SUM

    View full-size slide

  30. • ‘Pure programmers’ want to drive the adoption of paradigms which
    maximize mastery
    • ‘Pure managers’ want to drive paradigms which maximize productivity.
    • I consider type-orientation a symptom of managerial programming:
    trading programmers’ self-development for a team stratification which suits
    market/empirical conditions
    • However, we can resist stratifying paradigms by investing in programmers:
    by changing market conditions
    • nb. ‘Best Practices’ evolve under these two (mastery, productivity)
    pressures!
    CONCLUSIONS
    THE SOCIOLOGY OF APPLICATION DESIGN

    View full-size slide

  31. CONCLUSIONS
    TAKE-AWAYS
    • Paradigms distribute conceptual labour (but not zero-sum!)
    • Comparing paradigms is difficult
    • The functional paradigm offers PHP a different (object-functional) direction
    • In one conclusion,
    Functional design has much better performance
    under ideal conditions

    View full-size slide

  32. QUESTIONS?
    Functional Application Design in PHP by Michael J. Burgess
    @mjburgess
    #fadphp

    View full-size slide