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

Flipping out with Feature Flags & Toggles - PHP Yorkshire 2017

Flipping out with Feature Flags & Toggles - PHP Yorkshire 2017

Michael C.

April 08, 2017
Tweet

More Decks by Michael C.

Other Decks in Programming

Transcript

  1. ME?

  2. HARDCODED <?php function isEnabled(string $flag): boolean { if ($flag ==

    'profile') { return true; } return false; } if (isEnabled('profile')) { newProfileMagic(); }
  3. HARDCODED <?php function isEnabled(string $flag): boolean { if ($flag ==

    'profile') { return true; } return false; } if (isEnabled('profile')) { newProfileMagic(); }
  4. PARAMETERS IN CONFIG FILES <?php function isEnabled(string $flag): boolean {

    if ($flag == 'mailDelivery') { return $this->container->getParameter('swiftmailer.enabled', $flag); } elseif (isset($this->container->getParameter(sprintf('flag.%s', $flag)))) { return $this->container->getParameter(sprintf('flag.%s', $flag)); } return false; }
  5. CACHE function isEnabled(string $flag): boolean { $cache = $this->cache; $flag

    = $cache->getItem(sprintf('flag.%s', $flag)); if (!$flag->isHit()) { $flag->get(); } return false; }
  6. TWIG <?php namespace AppBundle\Twig; class AppExtension extends \Twig_Extension { public

    function getFunctions() { return array( new \Twig_SimpleFunction('isEnabled', array($this, 'isEnabled')), ); } //.. }
  7. COMPLEXITY <?php if ($container->getParameter('profileFeature')) { if ($container->getParameter('newProfileStyle')) { if ($container->getParameter('newProfileStyleButtons'))

    { enableButtons(); } if ($container->getParameter('myNewCoolProfilePic')) { renderPicture(); if ($container->getParameter('newProfileRenderEngine')) { tryDifferentRenderEngine(); } } renderNewProfiler(); } else { // Render the legacy profile } }
  8. COMPLEXITY <?php if ($container->getParameter('profileFeature')) { if ($container->getParameter('newProfileStyle')) { if ($container->getParameter('newProfileStyleButtons'))

    { enableButtons(); } if ($container->getParameter('myNewCoolProfilePic')) { renderPicture(); if ($container->getParameter('newProfileRenderEngine')) { tryDifferentRenderEngine(); } } renderNewProfiler(); } else { // Render the legacy profile } }
  9. COMPLEXITY <?php if ($container->getParameter('profileFeature')) { if ($container->getParameter('newProfileStyle')) { if ($container->getParameter('newProfileStyleButtons'))

    { enableButtons(); } if ($container->getParameter('myNewCoolProfilePic')) { renderPicture(); if ($container->getParameter('newProfileRenderEngine')) { tryDifferentRenderEngine(); } } renderNewProfiler(); } else { // Render the legacy profile } }
  10. CONTROLLERS - EVENT <?php public function onKernelRequest($event) { $flag =

    $event->getRequest->attributes->get('_flag'); $alternate = $event->getRequest->attributes->get('_alt'); if (isEnabled($flag)) { $event->getRequest->attributes->set(‘controller’, $alternate); } }
  11. CONTROLLERS - EVENT <?php public function onKernelRequest($event) { $flag =

    $event->getRequest->attributes->get(‘_flag'); $alternate = $event->getRequest->attributes->get(‘_alt'); if (isEnabled($flag)) { $event->getRequest->attributes->set(‘_controller’, $alternate); } if (!isset($alternate) && isset($flag) && !isEnabled($flag)) { throw new NotFoundHttpException(); } }
  12. CONTROLLERS - EVENT <?php public function onKernelRequest($event) { $flag =

    $event->getRequest->attributes->get(‘_flag'); $alternate = $event->getRequest->attributes->get(‘_alt'); if (isEnabled($flag)) { $event->getRequest->attributes->set(‘_controller’, $alternate); } if (!isset($alternate) && isset($flag) && !isEnabled($flag)) { throw new NotFoundHttpException(); } }
  13. NON-GENERIC FACTORY <?php class ProfileFactory { public function create(): ProfileInterface

    { return isEnabled(‘newProfile’) ? $container->get(‘newProfile’) : $container->get(‘legacyProfile’); } }
  14. GENERIC FLAGS FACTORY <?php class FlagsFactory { public function createService(string

    $flag, $service, $alternate) { return isEnabled($flag) ? $container->get($service) : $container->get($alternate); } }
  15. GENERIC FLAGS FACTORY services: app.flagsFactory: class: AppBundle\FlagsFactory app.profileManager: class: AppBundle\Profile\ProfileManager

    factory: ['@app.flagsFactory', createService] arguments: - newProfile - legacyProfileManager - newProfileManager