$30 off During Our Annual Pro Sale. View Details »

Package Development Laracon EU

Package Development Laracon EU

Registering your new awesome package to packagist is easy. But what about maintainability? What dependencies should you avoid? Have you considered reducing download size? How will you keep your users up to date with changes in newer versions? How do you best handle releases? How do you manage your package to behave in an optimal way both in other people's production environment as in your local package development environment?

These and many other tips for medium to high quality packages are included in this talk.

https://www.youtube.com/watch?v=lreUaGnOOYs

Hannes Van De Vreken

August 26, 2015
Tweet

More Decks by Hannes Van De Vreken

Other Decks in Technology

Transcript

  1. Package development
    Laracon EU
    @hannesvdvreken

    View Slide

  2. Hi, my name is Hannes.

    View Slide

  3. .be
    madewithlove

    View Slide

  4. Me after 100 km (62 miles)

    View Slide

  5. Package development
    Intermediate and advanced techniques

    View Slide

  6. 1. Beginner steps
    2. Intermediate tips
    3. Decouple for stability

    View Slide

  7. 1. Beginner steps
    Everyone started out as a newbie.

    View Slide

  8. View Slide

  9. View Slide

  10. BEGINNER STEPS
    http:/
    /phppackagechecklist.com/

    View Slide

  11. View Slide

  12. View Slide

  13. BEGINNER STEPS
    No renaming
    keep the old one, but create a new

    View Slide

  14. View Slide

  15. View Slide

  16. View Slide

  17. BEGINNER STEPS
    Instructions to install
    composer require guzzlehttp/guzzle

    View Slide

  18. View Slide

  19. View Slide

  20. BEGINNER STEPS - VERSIONS
    Class Sdk
    {
    public function __construct(Illuminate\Config\Repository $confi
    {

    }
    }
    /**
    * Register method.
    */
    public function register()
    {
    // Register SDK class.
    $this->app->singleton('twilio', function () {
    return new Sdk($this->app['config']);
    });
    }

    View Slide

  21. BEGINNER STEPS - VERSIONS
    Class Sdk
    {
    public function __construct(array $options)
    {

    }
    }
    /**
    * Register method.
    */
    public function register()
    {
    // Register SDK class.
    $this->app->singleton('twilio', function () {
    $config = $this->app['config'];
    return new Sdk($config->get('services.twilio'));
    });
    }

    View Slide

  22. View Slide

  23. BEGINNER STEPS - CODE STYLE
    Recommendations:
    PSR-2

    View Slide

  24. BEGINNER STEPS - CODE STYLE
    Use of tooling
    phpcs, php-cs-fixer

    View Slide

  25. BEGINNER STEPS - CODE STYLE
    Do it early
    git history, open pull requests

    View Slide

  26. View Slide

  27. BEGINNER STEPS - TESTS/SPECS
    It’s your insurance
    in multiple ways

    View Slide

  28. View Slide

  29. View Slide

  30. BEGINNER STEPS - VERSIONING
    semver.org
    read it

    View Slide

  31. BEGINNER STEPS - VERSIONING
    Release often

    View Slide

  32. View Slide

  33. BEGINNER STEPS - CHANGELOG
    Document releases
    keepachangelog.com

    View Slide

  34. BEGINNER STEPS - CHANGELOG
    Release often

    View Slide

  35. BEGINNER STEPS - CHANGELOG
    # Change Log
    All notable changes to this project will be documented in this file.
    This project adheres to [Semantic Versioning](http://semver.org/).
    ## [Unreleased][unreleased]
    ### Changed
    - Improve argument against commit logs.
    ## [0.0.8] - 2015-02-17
    ### Changed
    - Update year to match in every README example.
    - Reluctantly stop making fun of Brits only, since most of the world
    writes dates in a strange way.
    ### Fixed
    - Fix typos in recent README changes.
    - Update outdated unreleased diff link.

    View Slide

  36. View Slide

  37. View Slide

  38. BEGINNER STEPS - CHANGELOG
    upgrade.md

    View Slide

  39. View Slide

  40. View Slide

  41. BEGINNER STEPS
    GitHub
    PC
    test service
    packagist

    View Slide

  42. BEGINNER STEPS
    GitHub
    PC
    test service
    packagist
    git push

    View Slide

  43. BEGINNER STEPS
    GitHub
    PC
    test service
    packagist
    webhook
    webhook

    View Slide

  44. BEGINNER STEPS
    GitHub
    PC
    test service
    packagist
    analyses
    composer.json
    /stores version
    runs tests

    View Slide

  45. BEGINNER STEPS
    GitHub
    PC
    test service
    packagist
    status
    green!

    View Slide

  46. View Slide

  47. BEGINNER STEPS - README.MD
    Code samples
    copy-paste

    View Slide

  48. BEGINNER STEPS - README.MD
    // open an image file
    $img = Image::make('public/foo.jpg');
    // resize image instance
    $img->resize(320, 240);
    // insert a watermark
    $img->insert('public/watermark.png');
    // save image in desired format
    $img->save('public/bar.jpg');

    View Slide

  49. View Slide

  50. BEGINNER STEPS
    No license is the worst
    http:/
    /choosealicense.com/

    View Slide

  51. View Slide

  52. BEGINNER STEPS - CONTRIBUTING
    Instructions
    how to test
    how to make pull request
    philosophy

    View Slide

  53. BEGINNER STEPS
    Congrats,
    you’re no longer a newbie!

    View Slide

  54. BEGINNER STEPS - HINT 1
    jonathantorres/construct

    View Slide

  55. BEGINNER STEPS - HINT 1
    $ construct generate --help
    Arguments:
    name The vendor/project name
    Options:
    --test (-t) Testing framework (default: "phpunit")
    --license (-l) License (default: "MIT")
    --namespace (-s) Namespace for project (default: "Vendor\\Pro
    --git (-g) Initialize an empty Git repo
    --phpcs (-p) Generate a PHP Coding Standards Fixer config
    --keywords (-k) Comma separated list of Composer keywords
    --vagrant Generate a Vagrantfile

    View Slide

  56. BEGINNER STEPS - HINT 2
    franzl/studio

    View Slide

  57. BEGINNER STEPS - HINT 2
    $ studio load --help
    Usage:
    load
    Arguments:
    path The path where the package files are located

    View Slide

  58. 2. Intermediate tips

    View Slide

  59. INTERMEDIATE TIPS - ENVIRONMENTS
    Packages have
    environments too

    View Slide

  60. INTERMEDIATE TIPS - ENVIRONMENTS
    dev/local
    test/ci
    production

    View Slide

  61. INTERMEDIATE TIPS - ENVIRONMENTS - DEV & CI
    not in production:
    composer require --dev

    View Slide

  62. INTERMEDIATE TIPS - ENVIRONMENTS - CI
    CI only:
    code coverage

    View Slide

  63. INTERMEDIATE TIPS - ENVIRONMENTS - CI
    phpunit --coverage-html=/tmp/coverage/;
    vs
    phpunit --coverage-clover=/tmp/coverage.xml;
    ocular code-coverage:upload /tmp/coverage.xml;

    View Slide

  64. INTERMEDIATE TIPS - ENVIRONMENTS - PROD
    Keep your tests
    out of other people’s
    production

    View Slide

  65. INTERMEDIATE TIPS - CLEAN DISTS
    --prefer-dist

    View Slide

  66. INTERMEDIATE TIPS - CLEAN DISTS
    .gitattributes

    View Slide

  67. View Slide

  68. INTERMEDIATE TIPS - CLEAN DISTS
    "autoload": {
    "psr-4": {
    "GuzzleHttp\\": "src/"
    }
    },
    "autoload-dev": {
    "psr-4": {
    "GuzzleHttp\\Stubs\\": "tests/stubs/"
    }
    }

    View Slide

  69. INTERMEDIATE TIPS
    Composer scripts
    stop typing vendor/bin/

    View Slide

  70. INTERMEDIATE TIPS - COMPOSER SCRIPTS
    "scripts": {
    "cs": "php-cs-fixer fix"
    }
    $ composer cs

    View Slide

  71. INTERMEDIATE TIPS - COMPOSER SCRIPTS
    "scripts": {
    "test": ["phpunit", "phpspec run"]
    }

    View Slide

  72. INTERMEDIATE TIPS - COMPOSER SCRIPTS
    #!/usr/bin/env php

    View Slide

  73. INTERMEDIATE TIPS - COMPOSER SCRIPTS
    "bin": ["construct"]

    View Slide

  74. INTERMEDIATE TIPS - COMPOSER SCRIPTS
    not in ci:
    require --global

    View Slide

  75. INTERMEDIATE TIPS
    Code Style

    View Slide

  76. INTERMEDIATE TIPS - CODE STYLE
    Recommendations:
    PSR-2 < Symfony

    View Slide

  77. View Slide

  78. if (5 === count($list)) {
    Yoda conditions

    View Slide

  79. INTERMEDIATE TIPS - CODE STYLE
    $container = new Container;
    $container = new Container();
    $options = [
    'ssl' => true,
    'redirects' => false,
    ];

    View Slide

  80. INTERMEDIATE TIPS - CODE STYLE
    Atomic commits
    easier to review w/o code style fixes

    View Slide

  81. INTERMEDIATE TIPS - RECAP
    - separate environments
    - composer scripts
    - code style

    View Slide

  82. Semver checker
    ^ vs ~
    Marketing
    Communication (empathy)
    composer --sort-packages

    View Slide

  83. Semver checker
    ^ vs ~
    Marketing
    Communication (empathy)
    composer --sort-packages

    View Slide

  84. 3. Decouple for stability

    View Slide

  85. DECOUPLING
    Imagine…
    You’re creating an SDK

    View Slide

  86. DECOUPLING
    HTTP

    View Slide

  87. DECOUPLING - HTTP EXAMPLE
    Roll your own
    when?

    View Slide

  88. View Slide

  89. View Slide

  90. View Slide

  91. View Slide

  92. DECOUPLING - HTTP EXAMPLE
    Better:
    Use HTTP Client

    View Slide

  93. DECOUPLING - HTTP EXAMPLE
    Better:
    Use Guzzle v6

    View Slide

  94. DECOUPLING - HTTP EXAMPLE

    “But I’m already using
    Guzzle v4 instead of v6”

    View Slide

  95. DECOUPLING - HTTP EXAMPLE

    “But I’m already using
    Buzz HTTP client”

    View Slide

  96. DECOUPLING - HTTP EXAMPLE
    Decouple
    from the implementation

    View Slide

  97. DECOUPLING - HTTP EXAMPLE
    php-http/adapter-interface

    View Slide

  98. DECOUPLING - HTTP EXAMPLE
    Uses PSR-7
    HTTP Message Interfaces

    View Slide

  99. DECOUPLING - HTTP EXAMPLE
    /* @var \Psr\Http\Message\RequestInterface $request */
    /* @var \Psr\Http\Message\ResponseInterface $response */
    /* @var \Http\Adapter\HttpAdapter $adapter */
    $response = $adapter->send($request);

    View Slide

  100. DECOUPLING - HTTP EXAMPLE
    /**
    * @param \Http\Adapter\HttpAdapter $adapter
    */
    public function __construct(HttpAdapter $adapter)
    {
    $this->adapter = $adapter;
    }

    View Slide

  101. DECOUPLING - HTTP EXAMPLE
    (optional)
    $client = new \Http\Adapter\Client($adapter)
    $response = $client->get($url);

    View Slide

  102. DECOUPLING - HTTP EXAMPLE
    Adapters:
    Guzzle5
    Guzzle6
    Mock
    Buzz
    Zend2
    Zend1
    Cake

    View Slide

  103. DECOUPLING - HTTP EXAMPLE
    Used by
    friendsofsymfony/http-cache

    View Slide

  104. DECOUPLING - HTTP EXAMPLE
    egeloen/http-adapter
    Used by
    geocoder-php/geocoder
    florianv/swap

    View Slide

  105. DECOUPLING - HTTP EXAMPLE
    Could be used by
    league/oauth2-client
    toin0u/digitalocean-v2

    View Slide

  106. DECOUPLING - OTHER CASES
    - HTTP
    - Logging
    - File system

    View Slide

  107. DECOUPLING - OTHER CASES
    Sadly not for caching

    View Slide

  108. DECOUPLING - INTERFACES
    Decoupling
    requires interfaces

    View Slide

  109. DECOUPLING - INTERFACES
    interfaces
    have implementations

    View Slide

  110. DECOUPLING - INTERFACES
    concept
    virtual package
    is a placeholder for a dependency
    on some implementation

    View Slide

  111. company/sdk
    requires (1.0.0)
    php-http/adapter-implementation

    View Slide

  112. php-http/adapter-implementation
    php-http/adapter
    provides (1.0.0)
    requires (1.0.0)
    guzzlehttp/guzzle
    requires (^6.0)
    php-http/guzzle6-adapter

    View Slide

  113. company/sdk
    application
    requires (x.y.z)

    View Slide

  114. company/sdk
    requires (1.0.0)
    php-http/adapter-implementation
    php-http/adapter
    provides (1.0.0)
    requires (1.0.0)
    guzzlehttp/guzzle
    requires (^6.0)
    application
    requires (x.y.z)
    requires (1.0.0)
    requires (1.0.0)
    php-http/guzzle6-adapter

    View Slide

  115. DECOUPLING - RECAP
    Prefer requiring stabler packages

    View Slide

  116. DECOUPLING - RECAP
    Prefer requiring virtual packages

    View Slide

  117. DECOUPLING - BENEFITS
    As package maintainer:
    Less major releases

    View Slide

  118. DECOUPLING - BENEFITS
    Users can choose
    low level packages they want

    View Slide

  119. DECOUPLING - BENEFITS
    Users don’t get
    locked-in to a major version

    View Slide

  120. DECOUPLING - RECAP
    - Single responsibility principle
    - Try to decouple from implementation
    - Depend on virtual packages

    View Slide

  121. View Slide

  122. RECAP
    1. Beginner steps
    2. Intermediate tips
    3. Decouple for stability

    View Slide

  123. One more thing

    View Slide

  124. 1 November 2015

    View Slide

  125. gofundme.com/tcsnycmarathon

    View Slide

  126. Thank you!
    @hannesvdvreken
    https:/
    /joind.in/15023

    View Slide

  127. Time for questions.
    @hannesvdvreken
    https:/
    /joind.in/15023

    View Slide

  128. • http:/
    /mwl.be
    REFERENCES

    View Slide