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

Package development #phpday

Package development #phpday

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.

Hannes Van De Vreken

May 17, 2016
Tweet

More Decks by Hannes Van De Vreken

Other Decks in Technology

Transcript

  1. Package development
    PHPDay, Verona !
    @hannesvdvreken
    @phpday

    View Slide

  2. Hi, my name is Hannes.

    View Slide

  3. "

    View Slide

  4. View Slide

  5. madewithlove.be

    View Slide

  6. View Slide

  7. Package development
    Intermediate and advanced techniques

    View Slide

  8. 1. Beginner steps
    2. Intermediate tips
    3. Package stability

    View Slide

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

    View Slide

  10. View Slide

  11. BEGINNER STEPS
    phppackagechecklist.com

    View Slide

  12. View Slide

  13. View Slide

  14. View Slide

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

    View Slide

  16. View Slide

  17. View Slide

  18. https:/
    /seld.be/notes/common-files-in-php-packages

    View Slide

  19. View Slide

  20. View Slide

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

    View Slide

  22. BEGINNER STEPS
    Instructions to install
    not: “add guzzlehttp/guzzle to your
    composer.json”

    View Slide

  23. View Slide

  24. View Slide

  25. BEGINNER STEPS - VERSIONS
    Class Sdk
    {
    public function __construct(Framework\Config)
    {

    }
    }
    /**
    * Register method.
    */
    public function register()
    {
    // Register SDK class.
    $this->container->share('twilio', function () {
    return new Sdk($this->container->make('config'))
    });
    }

    View Slide

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

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

    View Slide

  27. View Slide

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

    View Slide

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

    View Slide

  30. BEGINNER STEPS - CODE STYLE
    Do it early
    boy-scouting
    file-per-file
    git blame
    open pull requests

    View Slide

  31. View Slide

  32. BEGINNER STEPS - TESTS/SPECS
    Not just the happy path

    View Slide

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

    View Slide

  34. View Slide

  35. View Slide

  36. BEGINNER STEPS - VERSIONING
    semver.org
    read it

    View Slide

  37. BEGINNER STEPS - VERSIONING
    Release often

    View Slide

  38. View Slide

  39. BEGINNER STEPS - CHANGELOG
    Document releases
    keepachangelog.com

    View Slide

  40. BEGINNER STEPS - CHANGELOG
    Release often

    View Slide

  41. 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

  42. BEGINNER STEPS - CHANGELOG
    keepachangelog.com

    View Slide

  43. View Slide

  44. View Slide

  45. BEGINNER STEPS - CHANGELOG
    upgrade.md

    View Slide

  46. View Slide

  47. View Slide

  48. BEGINNER STEPS
    GitHub
    PC
    test service
    packagist

    View Slide

  49. BEGINNER STEPS
    GitHub
    PC
    test service
    packagist
    git push

    View Slide

  50. BEGINNER STEPS
    GitHub
    PC
    test service
    packagist
    webhook
    webhook

    View Slide

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

    View Slide

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

    View Slide

  53. View Slide

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

    View Slide

  55. 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

  56. View Slide

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

    View Slide

  58. View Slide

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

    View Slide

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

    View Slide

  61. BEGINNER STEPS - HINT 1
    jonathantorres/construct

    View Slide

  62. 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

  63. BEGINNER STEPS - HINT 1
    Or use a skeleton package

    View Slide

  64. BEGINNER STEPS - HINT 2
    franzl/studio

    View Slide

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

    View Slide

  66. 2. Intermediate tips

    View Slide

  67. INTERMEDIATE TIPS - ENVIRONMENTS
    Packages have
    environments too

    View Slide

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

    View Slide

  69. INTERMEDIATE TIPS - ENVIRONMENTS - DEV & CI
    not in production:
    composer require --dev
    also installs require-dev dependencies

    View Slide

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

    View Slide

  71. 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

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

    View Slide

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

    View Slide

  74. INTERMEDIATE TIPS - CLEAN DISTS
    .gitattributes

    View Slide

  75. View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  80. INTERMEDIATE TIPS - COMPOSER BINS
    #!/usr/bin/env php

    View Slide

  81. INTERMEDIATE TIPS - COMPOSER BINS
    "bin": ["construct"]

    View Slide

  82. INTERMEDIATE TIPS - COMPOSER BINS
    composer require --global
    not in CI

    View Slide

  83. INTERMEDIATE TIPS
    Code Style

    View Slide

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

    View Slide

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

    View Slide

  86. View Slide

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

    View Slide

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

    View Slide

  89. View Slide

  90. View Slide

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

    View Slide

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

    View Slide

  93. 3. Package stability

    View Slide

  94. STABILITY
    As package maintainer:
    Less major releases

    View Slide

  95. STABILITY
    If a dependency has new major version,
    your package needs new major version.

    View Slide

  96. Keep number of hard
    requirements low
    STABILITY

    View Slide

  97. STABILITY - SOFT-REQUIREMENTS
    Soft requirements
    eg: use decorators

    View Slide

  98. use Psr\Cache\CacheItemPool;
    class CacheDecorator implements …
    {

    }
    STABILITY - SOFT-REQUIREMENTS

    View Slide

  99. {
    "name": "league/flysystem-eventable-filesystem",
    "require": {
    "php": ">=5.4.0",
    "league/event": "~1.0",
    "league/flysystem": "~1.0"
    },

    STABILITY - SOFT-REQUIREMENTS

    View Slide

  100. Depend on interface
    packages
    STABILITY - DECOUPLING

    View Slide

  101. STABILITY - SOFT-REQUIREMENTS
    Soft requirements
    eg: use decorators

    View Slide

  102. concept
    virtual package
    is a high level placeholder for a dependency
    on a more low level implementation
    STABILITY - DECOUPLING

    View Slide

  103. company/sdk
    requires (1.0.0)
    psr/cache-implementation
    requires (1.0.0)
    psr/cache

    View Slide

  104. psr/cache-implementation
    provides (1.0.0)
    requires (1.0.0)
    doctrine/cache
    requires (^1.3)
    doctrine/cache
    psr/cache

    View Slide

  105. company/sdk
    application
    requires (x.y.z)
    requires (1.0.0)
    psr/cache-implementation

    View Slide

  106. company/sdk
    requires (1.0.0)
    psr/cache-implementation
    provides (1.0.0)
    requires (1.0.0)
    application
    requires (x.y.z)
    requires (0.5.0)
    requires (1.0.0)
    cache/doctrine-adapter
    psr/cache
    requires (^1.3)
    doctrine/cache

    View Slide

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

    View Slide

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

    View Slide

  109. Prefer having less hard
    dependencies
    STABILITY - RECAP

    View Slide

  110. Prefer requiring
    stabler packages
    STABILITY - RECAP

    View Slide

  111. STABILITY - RECAP
    Prefer requiring
    virtual packages

    View Slide

  112. STABILITY - BENEFITS
    As package maintainer:
    Less major releases

    View Slide

  113. DECOUPLING - OTHER CASES
    - File system (Flysystem)
    - Logging (PSR-3)
    - HTTP (PSR-7)
    - Caching (PSR-6)

    View Slide

  114. View Slide

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

    View Slide

  116. Thank you!
    @hannesvdvreken
    @phpday
    https:/
    /joind.in/talk/e48d2

    View Slide

  117. Time for questions.
    @hannesvdvreken
    @phpday

    View Slide

  118. • http:/
    /mwl.be
    REFERENCES

    View Slide