Encapsulate What Varies

Identify aspects of your application that vary and separate from what stays the same.


New Requirements

Does the code change with every new requirement? If so, then its recommended that this code is pulled out and encapsulated somewhere else. Essentially separating code which is fixed and code which is constantly changing.

But why? Later we can alter or extend the code without affecting the parts which don’t vary.

Tips
  • Always look for code thats changes with every new requirement.
  • Alter or extend code that varies without affecting code which doesn’t.
  • When using a design pattern, pay attention to this principle and how the pattern implements it.
Example

Here’s a system for ordering pancakes.


class Pancake 
{
  public function order($type) 
  {
    if ($type === 'classic') {
      $pancake = new ClassicPancake();
    }

    if ($type === 'blueberry') {
      $pancake = new BlueBerryPancake();
    }

    if ($type === 'chocolate_chip') {
      $pancake = new ChocolateChipPancake();
    }

    if ($type === 'banana') {
      $pancake = new BananaPancake();
    }

    $pancake->cook();
    $pancake->plate();
    $pancake->addButter();

    return $pancake;
  }

}

Identify which parts of the code which vary


if ($type === 'classic') {
  $pancake = new ClassicPancake();
}

if ($type === 'blueberry') {
  $pancake = new BlueBerryPancake();
}

if ($type === 'chocolate_chip') {
  $pancake = new ChocolateChipPancake();
}

if ($type === 'banana') {
  $pancake = new BananaPancake();
}

Encapsulate code somewhere else


class Pancake 
{
  public function order($type) 
  {
    $pancake = PancakeFactory::make($type);

    $pancake->cook();
    $pancake->plate();
    $pancake->addButter();

    return $pancake;
  } 
}


class PancakeFactory 
{
  public static function make($type) 
  {

    if ($type === 'classic') {
      return new ClassicPancake();
    }

    if ($type === 'blueberry') {
      return new BlueBerryPancake();
    }

    if ($type === 'chocolate_chip') {
      return new ChocolateChipPancake();
    }

    if ($type === 'banana') {
      return new BananaPancake();
    }

    return null; // Maybe throw an exception here. 
  }
}