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

39eb3f3d313b13f05534e496285040b8?s=128

Hannes Van De Vreken

August 26, 2015
Tweet

Transcript

  1. Package development Laracon EU @hannesvdvreken

  2. Hi, my name is Hannes.

  3. .be madewithlove

  4. Me after 100 km (62 miles)

  5. Package development Intermediate and advanced techniques

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

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

  8. None
  9. None
  10. BEGINNER STEPS http:/ /phppackagechecklist.com/

  11. None
  12. None
  13. BEGINNER STEPS No renaming keep the old one, but create

    a new
  14. None
  15. None
  16. None
  17. BEGINNER STEPS Instructions to install composer require guzzlehttp/guzzle

  18. None
  19. None
  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']); }); }
  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')); }); }
  22. None
  23. BEGINNER STEPS - CODE STYLE Recommendations: PSR-2

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

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

    open pull requests
  26. None
  27. BEGINNER STEPS - TESTS/SPECS It’s your insurance in multiple ways

  28. None
  29. None
  30. BEGINNER STEPS - VERSIONING semver.org read it

  31. BEGINNER STEPS - VERSIONING Release often

  32. None
  33. BEGINNER STEPS - CHANGELOG Document releases keepachangelog.com

  34. BEGINNER STEPS - CHANGELOG Release often

  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.
  36. None
  37. None
  38. BEGINNER STEPS - CHANGELOG upgrade.md

  39. None
  40. None
  41. BEGINNER STEPS GitHub PC test service packagist

  42. BEGINNER STEPS GitHub PC test service packagist git push

  43. BEGINNER STEPS GitHub PC test service packagist webhook webhook

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

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

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

  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');
  49. None
  50. BEGINNER STEPS No license is the worst http:/ /choosealicense.com/

  51. None
  52. BEGINNER STEPS - CONTRIBUTING Instructions how to test how to

    make pull request philosophy
  53. BEGINNER STEPS Congrats, you’re no longer a newbie!

  54. BEGINNER STEPS - HINT 1 jonathantorres/construct

  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
  56. BEGINNER STEPS - HINT 2 franzl/studio

  57. BEGINNER STEPS - HINT 2 $ studio load --help Usage:

    load <path> Arguments: path The path where the package files are located
  58. 2. Intermediate tips

  59. INTERMEDIATE TIPS - ENVIRONMENTS Packages have environments too

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

  61. INTERMEDIATE TIPS - ENVIRONMENTS - DEV & CI not in

    production: composer require --dev
  62. INTERMEDIATE TIPS - ENVIRONMENTS - CI CI only: code coverage

  63. INTERMEDIATE TIPS - ENVIRONMENTS - CI phpunit --coverage-html=/tmp/coverage/; vs phpunit

    --coverage-clover=/tmp/coverage.xml; ocular code-coverage:upload /tmp/coverage.xml;
  64. INTERMEDIATE TIPS - ENVIRONMENTS - PROD Keep your tests out

    of other people’s production
  65. INTERMEDIATE TIPS - CLEAN DISTS --prefer-dist

  66. INTERMEDIATE TIPS - CLEAN DISTS .gitattributes

  67. None
  68. INTERMEDIATE TIPS - CLEAN DISTS "autoload": { "psr-4": { "GuzzleHttp\\":

    "src/" } }, "autoload-dev": { "psr-4": { "GuzzleHttp\\Stubs\\": "tests/stubs/" } }
  69. INTERMEDIATE TIPS Composer scripts stop typing vendor/bin/

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

    } $ composer cs
  71. INTERMEDIATE TIPS - COMPOSER SCRIPTS "scripts": { "test": ["phpunit", "phpspec

    run"] }
  72. INTERMEDIATE TIPS - COMPOSER SCRIPTS #!/usr/bin/env php <?php

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

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

  75. INTERMEDIATE TIPS Code Style

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

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

  79. INTERMEDIATE TIPS - CODE STYLE $container = new Container; $container

    = new Container(); $options = [ 'ssl' => true, 'redirects' => false, ];
  80. INTERMEDIATE TIPS - CODE STYLE Atomic commits easier to review

    w/o code style fixes
  81. INTERMEDIATE TIPS - RECAP - separate environments - composer scripts

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

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

  84. 3. Decouple for stability

  85. DECOUPLING Imagine… You’re creating an SDK

  86. DECOUPLING HTTP

  87. DECOUPLING - HTTP EXAMPLE Roll your own when?

  88. None
  89. None
  90. None
  91. None
  92. DECOUPLING - HTTP EXAMPLE Better: Use HTTP Client

  93. DECOUPLING - HTTP EXAMPLE Better: Use Guzzle v6

  94. DECOUPLING - HTTP EXAMPLE “But I’m already using Guzzle v4

    instead of v6”
  95. DECOUPLING - HTTP EXAMPLE “But I’m already using Buzz HTTP

    client”
  96. DECOUPLING - HTTP EXAMPLE Decouple from the implementation

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

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

  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);
  100. DECOUPLING - HTTP EXAMPLE /** * @param \Http\Adapter\HttpAdapter $adapter */

    public function __construct(HttpAdapter $adapter) { $this->adapter = $adapter; }
  101. DECOUPLING - HTTP EXAMPLE (optional) $client = new \Http\Adapter\Client($adapter) $response

    = $client->get($url);
  102. DECOUPLING - HTTP EXAMPLE Adapters: Guzzle5 Guzzle6 Mock Buzz Zend2

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

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

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

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

    system
  107. DECOUPLING - OTHER CASES Sadly not for caching

  108. DECOUPLING - INTERFACES Decoupling requires interfaces

  109. DECOUPLING - INTERFACES interfaces have implementations

  110. DECOUPLING - INTERFACES concept virtual package is a placeholder for

    a dependency on some implementation
  111. company/sdk requires (1.0.0) php-http/adapter-implementation

  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

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

  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
  115. DECOUPLING - RECAP Prefer requiring stabler packages

  116. DECOUPLING - RECAP Prefer requiring virtual packages

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

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

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

    version
  120. DECOUPLING - RECAP - Single responsibility principle - Try to

    decouple from implementation - Depend on virtual packages
  121. None
  122. RECAP 1. Beginner steps 2. Intermediate tips 3. Decouple for

    stability
  123. One more thing

  124. 1 November 2015

  125. gofundme.com/tcsnycmarathon

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

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

  128. • http:/ /mwl.be REFERENCES