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

Going Bare - Writing the web without a framework - Cascadia PHP 2018

Going Bare - Writing the web without a framework - Cascadia PHP 2018

Talk given at Cascadia PHP 2018

If you've only ever experienced web development through a web framework, you're missing out. Have you ever been tempted to rewrite a codebase in your favorite framework? That's a smell that you need to come to this talk.

Being comfortable developing without a framework is a crucial skill to have for refactoring legacy applications. In this talk I show you how to harness the power of going "frameworkless" so you'll feel empowered to make better decisions in your next web project. Be set free from your web-framework ball and chain.

Sammy Kaye Powers

September 15, 2018
Tweet

More Decks by Sammy Kaye Powers

Other Decks in Programming

Transcript

  1. Going Bare
    Writing the web
    without a framework
    Sammy Kaye Powers
    2018-09-15

    View full-size slide

  2. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Slides
    Get the
    joind.in/talk/2e67a

    View full-size slide

  3. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    frameworks
    The point is
    not
    <3 frameworks!
    I

    View full-size slide

  4. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    opinion
    It’s OK to have an

    View full-size slide

  5. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    experiment
    It’s OK to

    View full-size slide

  6. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Bootstrapping
    / ˈbo ͞
    otˌstraˌpiNG /
    Define:
    (…at least for this talk)
    Code that acts as
    an entry point
    into an app.

    View full-size slide

  7. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Boilerplate
    / ˈboilərˌplāt /
    Define:
    The “glue” code that
    ties components
    together.
    (…at least for this talk)

    View full-size slide

  8. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Frameworks are a
    tool

    View full-size slide

  9. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Going bare is a
    skill
    (that you don’t get with a framework)

    View full-size slide

  10. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    The of going bare
    skill
    • Writing bootstrap & boilerplate
    • Choosing exact components
    • Use different paradigms
    • Use those skills on domain code
    (Get to know the component ecosystem)
    (Like singleton, et al)
    (Gives you more control over how components interact)
    (Makes you better at writing your domain code)

    View full-size slide

  11. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Myths
    about
    going
    frameworkless

    View full-size slide

  12. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Myth #1
    You must write
    everything from
    scratch

    View full-size slide

  13. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Myth #2
    You’re inherently
    anti-framework or
    anti-convention

    View full-size slide

  14. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Myth #3
    You’ll spend most of
    your time on
    boilerplate instead of
    on domain code

    View full-size slide

  15. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Myth #4
    You must be an
    architecture
    astronaut

    View full-size slide

  16. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Myth #5
    You like pain

    View full-size slide

  17. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Pros
    Framework
    Cons

    View full-size slide

  18. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Pros

    View full-size slide

  19. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Pros

    View full-size slide

  20. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Pros
    crazy
    fast
    You get started

    View full-size slide

  21. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Pros
    First-time
    install time
    minutes!
    5

    View full-size slide

  22. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Pros

    View full-size slide

  23. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Pros
    boilerplate
    all the things
    You don’t have to Con
    but it can be a

    View full-size slide

  24. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Pros
    bootstrap &
    boilerplate
    code
    You don’t have to maintain

    View full-size slide

  25. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Pros
    battle-tested
    The code is

    View full-size slide

  26. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Pros
    conventions
    Ready-to-follow
    Con
    but it can be a

    View full-size slide

  27. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Pros
    documentation
    Most frameworks
    have great

    View full-size slide

  28. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Pros
    marketable
    It makes you more

    View full-size slide

  29. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Pros
    pragmatic
    They are often

    View full-size slide

  30. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    cons?
    What about the

    View full-size slide

  31. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Cons
    legacy
    codebases
    Useless for

    View full-size slide

  32. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Cons
    cruft
    They fill your project with

    View full-size slide

  33. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Cons
    Cruft
    • Deployment takes longer
    • Upgrading pulls in all
    the new features

    View full-size slide

  34. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Cons
    tightly couple
    Easier to
    due to convenience

    View full-size slide

  35. joind.in/talk/2e67a
    @SammyK #cascadiaphp18

    View full-size slide

  36. 5.7
    2018-09-04

    View full-size slide

  37. 5.7
    Did not
    support
    laravelcollective/html
    mccool/laravel-auto-presenter

    View full-size slide

  38. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Cons
    upgrading
    Framework-specific deps
    can keep you from

    View full-size slide

  39. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    The
    The Cons
    Pros seem great
    are weak…

    View full-size slide

  40. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Why
    would you go bare?
    (To answer we must ask…)

    View full-size slide

  41. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    When
    should you go bare?

    View full-size slide

  42. joind.in/talk/2e67a
    @SammyK #cascadiaphp18

    View full-size slide

  43. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Greenfield Legacy
    Depends

    View full-size slide

  44. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    1%
    99%
    90%
    10%
    Go Bare Framwork
    Greenfield Legacy
    Going bare vs framework

    View full-size slide

  45. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    How
    do you go bare?

    View full-size slide

  46. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    from
    scratch
    You could just write

    View full-size slide

  47. joind.in/talk/2e67a
    @SammyK #cascadiaphp18

    View full-size slide

  48. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    That means writing all the things
    Router DBAL/ORM Dep Injection Logger

    View full-size slide

  49. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    reinventing
    the wheel
    But that’s like

    View full-size slide

  50. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Better Way™
    There’s a

    View full-size slide

  51. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    po-
    nents
    Com-

    View full-size slide

  52. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    components
    has a healthy ecosystem of

    View full-size slide

  53. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    using them
    You’re probably already

    View full-size slide

  54. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    built on them
    Most frameworks are
    zend-router zend-db zend-di zend-log

    View full-size slide

  55. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    choose ur candy
    Going bare lets you
    Look at all
    those smarties!
    Yum!

    View full-size slide

  56. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    I like smarties

    View full-size slide

  57. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Router DBAL/ORM Dep Injection Logger

    View full-size slide

  58. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    zend-router fast-route php-router phroute
    Routers
    Tons of variety

    View full-size slide

  59. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Easily installed with

    View full-size slide

  60. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    bag o’ candy
    A framework is like a
    Comes with
    licorice?
    Yuck!

    View full-size slide

  61. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    I don’t like licorice

    View full-size slide

  62. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    components
    When you go bare
    don’t just magically start
    working together

    View full-size slide

  63. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Key:
    Get comfy with
    bootstrapping &
    boilerplate code
    It’s really
    not that bad

    View full-size slide

  64. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    examples
    Real-world

    View full-size slide

  65. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    conventions
    When going bare, there aren’t any
    …so this is a way,
    not the way

    View full-size slide

  66. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Greenfield
    Let’s start with

    View full-size slide

  67. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Case study
    Raw
    CSV
    Calculate

    & save
    to DB
    Show
    report
    Client’s server Our server

    View full-size slide

  68. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Case study
    Download CSV & calculate
    CLI
    View the report
    HTTP Endpoint

    View full-size slide

  69. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    coding domain
    in 5 mins
    Install framework &

    View full-size slide

  70. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    61components
    installed before
    we code
    https://framework.zend.com/downloads

    View full-size slide

  71. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    go micro
    We could…
    Slim Silex
    (et al)

    View full-size slide

  72. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Silex
    DEAD!

    View full-size slide

  73. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    go bare! :)
    But let’s

    View full-size slide

  74. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Start in the CLI
    (Just like when you use a framework!)

    View full-size slide

  75. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    1. Make an empty
    composer.json or…
    $ composer init

    View full-size slide

  76. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    2. Make a folder for
    domain code
    $ mkdir src

    View full-size slide

  77. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    3. Add autoloading
    $ composer \
    dumpautoload
    And then run…

    View full-size slide

  78. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Now just install your
    components &
    tie them together

    View full-size slide

  79. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Key:
    Get comfy with
    bootstrapping &
    boilerplate code
    It’s really
    not that bad

    View full-size slide

  80. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Case study
    Download CSV & calculate
    CLI
    View the report
    HTTP Endpoint

    View full-size slide

  81. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Install a
    console component
    $ composer require symfony/console
    (or maybe you like zendframework/zend-console)

    View full-size slide

  82. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    src/Console/Runner.php

    View full-size slide

  83. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    We get to make our
    first bootstrap code!

    View full-size slide

  84. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    run (sans .php extension)
    $ chmod +x run

    View full-size slide

  85. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    $ ./run

    View full-size slide

  86. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    B.A.U.
    Now it’s just
    src/Console/Runner.php

    View full-size slide

  87. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    src/Console/CalculateReportsCommand.php

    View full-size slide

  88. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    $ ./run

    View full-size slide

  89. joind.in/talk/2e67a
    @SammyK #cascadiaphp18

    View full-size slide

  90. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Congrats!

    View full-size slide

  91. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Install the
    DI container
    $ composer require pimple/pimple
    (Choose your poison)

    View full-size slide

  92. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Need to
    make
    singleton
    ready
    src/Application.php

    View full-size slide

  93. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Singleton
    Isn’t that an anti-pattern?

    View full-size slide

  94. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    https://en.wikipedia.org/wiki/Singleton_pattern

    View full-size slide

  95. joind.in/talk/2e67a
    @SammyK #cascadiaphp18

    View full-size slide

  96. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Singleton
    •Ensures one & only one instance
    •Global access (static function)
    •Initialization on first access

    View full-size slide

  97. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Fatal error: Call to private
    App\Application::__construct()
    src/Application.php

    View full-size slide

  98. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    src/Application.php
    Global access
    + instantiate
    on first use

    View full-size slide

  99. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Get an instance of Application

    View full-size slide

  100. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Prevent cloning
    src/Application.php

    View full-size slide

  101. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    src/Application.php
    Prevent unserialization

    View full-size slide

  102. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    •Ensures one & only one instance
    •Global access (static function)
    •Initialization on first access

    View full-size slide

  103. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Case study
    Download CSV & calculate
    CLI
    View the report
    HTTP Endpoint

    View full-size slide

  104. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    We get to make our
    final bootstrap code!

    View full-size slide

  105. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    public/index.php

    View full-size slide

  106. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Eh?

    View full-size slide

  107. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    src/Application.php
    However you
    register service
    providers into the
    container
    (different DI containers have their own API)

    View full-size slide

  108. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Why not
    in constructor?

    View full-size slide

  109. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    src/Application.php

    View full-size slide

  110. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Install
    a router
    $ composer require nikic/fast-route
    (Choose your poison)

    View full-size slide

  111. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    service provider
    Make a routing
    Pimple syntax - mileage my vary

    View full-size slide

  112. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Register in container
    src/Application.php

    View full-size slide

  113. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    src/Router.php

    View full-size slide

  114. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Ugly A.F.
    src/routes.php

    View full-size slide

  115. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Different project,
    same component
    src/routes.php

    View full-size slide

  116. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    public/index.php
    run
    We got bootstrap
    Runs CLI Runs HTTP

    View full-size slide

  117. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    We got boilerplate
    src/Router.php
    src/Console/Runner.php
    symfony/console nikic/fast-route

    View full-size slide

  118. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Still not
    convinced?

    View full-size slide

  119. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    What about
    Legacy

    View full-size slide

  120. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Why
    would you go bare?
    It’s a skill you can use
    for legacy apps

    View full-size slide

  121. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    I’ll just rewrite this
    in x framework…

    View full-size slide

  122. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Totes
    samezies
    except routing

    View full-size slide

  123. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Route exists?
    Not found
    Router
    Yes No
    Code
    404

    View full-size slide

  124. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Route exists?
    Legacy router
    New router
    Yes No
    New code

    View full-size slide

  125. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    app/webroot/index.php
    Old CakePHP bootstrap file

    View full-size slide

  126. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    src/bootstrap.php
    Same as public/index.php for HTTP

    View full-size slide

  127. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    src/Router.php

    View full-size slide

  128. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    tests?
    What about

    View full-size slide

  129. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Install
    PHPUnit
    $ composer require phpunit/phpunit --dev

    View full-size slide

  130. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    phpunit.xml

    View full-size slide

  131. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    tests/bootstrap.php

    View full-size slide

  132. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    src/Application.php

    View full-size slide

  133. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Run the
    test suite
    $ ./vendor/bin/phpunit

    View full-size slide

  134. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    How to choose your
    components

    View full-size slide

  135. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Use more than one
    framework
    #1

    View full-size slide

  136. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Search
    packagist.org
    #2
    (Make sure it has good docs &
    is actively maintained)

    View full-size slide

  137. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    experiments
    Try some

    View full-size slide

  138. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    100%
    middleware
    My next experiment:
    (I could totes use Zend Expressive or just go bare)

    View full-size slide

  139. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    pros?
    framework
    ‘member the

    View full-size slide

  140. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Framework pros
    Crazy fast
    to get started
    …but you’ll get faster
    at going bare

    View full-size slide

  141. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Framework pros
    to maintain
    …most the time it’s
    really not that bad
    No bootstrap & boilerplate code

    View full-size slide

  142. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Framework pros
    The code is
    …so are the
    components you use
    when going bare
    battle tested

    View full-size slide

  143. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Framework pros
    Great
    …so are the
    components you use
    when going bare
    documentation

    View full-size slide

  144. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Framework pros
    Makes you more
    …going bare is a
    marketable skill
    marketable

    View full-size slide

  145. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Framework pros
    They are often
    …in many contexts
    going bare is more
    pragmatic
    pragmatic

    View full-size slide

  146. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    myths?
    Did we bust the

    View full-size slide

  147. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    #1 You must write
    everything from scratch
    Nope,
    use components

    View full-size slide

  148. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    #2 You’re inherently anti-
    framework or anti-convention
    Nope, frameworks
    are great for most
    greenfield projects

    View full-size slide

  149. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    #3 You’ll spend most of your time
    on bootstrapping instead of on
    domain code
    It takes a little longer
    at first but you’ll get
    faster with practice

    View full-size slide

  150. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    #4 You must be an architecture
    astronaut
    Going bare is more
    pragmatic for legacy
    codebases

    View full-size slide

  151. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    #5 You like pain
    No, we just like to
    improve our skills

    View full-size slide

  152. joind.in/talk/2e67a
    @SammyK #cascadiaphp18

    View full-size slide

  153. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Remember:
    It’s all about
    tradeoffs.

    View full-size slide

  154. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Resources

    View full-size slide

  155. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Create a PHP
    application without
    a framework
    Patrick Louys
    https://github.com/PatrickLouys/no-
    framework-tutorial

    View full-size slide

  156. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    Refactoring
    Martin Fowler

    View full-size slide

  157. joind.in/talk/2e67a
    @SammyK #cascadiaphp18
    <3 frameworks
    I
    I also <3 my skill for
    Going Bare

    View full-size slide

  158. Sammy Kaye Powers
    Thanks!
    /talk/2e67a
    @SammyK
    SammyK.me
    Host of @PHPRoundtable

    View full-size slide