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

Immutability to save an ever-changing world

Immutability to save an ever-changing world

Want to build software that is more testable, easier to modify, and has fewer lines of code? Architecting with more immutable objects that are always in a valid state is the most important lesson I have learned in building better software applications. Using immutable value objects will lead to less checking, fewer bugs, and more DRY code, and will help avoid the “spooky action at a distance” problem in PHP. We will also learn how to use immutable objects and immutable collections to improve design of our mutable entities. Lastly, we’ll see how immutable objects and functional programming can reduce complexity.

Andrew Cassell

October 16, 2018
Tweet

More Decks by Andrew Cassell

Other Decks in Programming

Transcript

  1. • POPOs • No setters, all parameters are passed into

    constructor • Declare all class properties as private • No properties that are mutable objects Immutable Objects in PHP
  2. • POPOs • No setters, all parameters are passed into

    constructor • Declare all class properties as private • No properties that are mutable objects Immutable Objects in PHP
  3. • Immutable Objects • Always in a valid state •

    Validate in constructor • Behavioral methods return new object • Not dependencies Value Objects in PHP
  4. Always Valid Value Object Immutable No Identity (Only Values) Recipe

    Name Weight Temperature Entity Identifiable Mutable Lifecycle Contains Value Objects Line Item Brewer Recipe
  5. First Name Last Name Full Name Email Address Recipe Name

    Date Brewed On Recipe ID Temperature Liters Gallons Kilograms Pounds Value Objects
  6. cassell:beeriously cassell$ docker run --rm --interactive --tty --network beeriously_default --volume

    `pwd`:/app --user : --workdir /app beeriously_php-fpm /app/vendor/bin/phpunit --configuration /app/src/Tests/Unit/ phpunit.xml.dist PHPUnit 6.4.3 by Sebastian Bergmann and contributors. FEE 3 / 3 (100%) Time: 2.34 seconds, Memory: 4.00MB There were 2 errors: 1) Beeriously\Tests\Unit\Domain\Recipe\RecipeNameTest::testGetter Error: Class 'Beeriously\Domain\Recipe\RecipeName' not found /app/src/Tests/Unit/Domain/Recipe/RecipeNameTest.php:20 2) Beeriously\Tests\Unit\Domain\Recipe\RecipeNameTest::testToString Error: Class 'Beeriously\Domain\Recipe\RecipeName' not found /app/src/Tests/Unit/Domain/Recipe/RecipeNameTest.php:26 -- There was 1 failure: 1) Beeriously\Tests\Unit\Domain\Recipe\RecipeNameTest::testEmptyFails Failed asserting that exception of type "Error" matches expected exception "Beeriously\Domain\Recipe\InvalidRecipeNameException". Message was: "Class 'Beeriously\Domain\Recipe\RecipeName' not found" at /app/src/Tests/Unit/Domain/Recipe/RecipeNameTest.php:15 . ERRORS! Tests: 3, Assertions: 1, Errors: 2, Failures: 1.
  7. cassell:beeriously cassell$ docker run --rm --interactive --tty --network beeriously_default --volume

    `pwd`:/app --user : --workdir /app beeriously_php-fpm /app/vendor/bin/phpunit --configuration /app/src/Tests/ Unit/phpunit.xml.dist PHPUnit 6.4.3 by Sebastian Bergmann and contributors. ... 3 / 3 (100%) Time: 192 ms, Memory: 4.00MB OK (3 tests, 4 assertions)
  8. <?php var_dump(-0.0 > 0); // false var_dump(-0.0 < 0); //

    false var_dump(-0.0 === 0.0); // true (float) var_dump(-0.0 === 0); // false (int) var_dump(-0.0 == false); // true (bool) var_dump(-0.0 == null); // true (bool) var_dump(-0.0 == null); // true (string) var_dump(-0.0 == "negativezero"); // true (string)
  9. if(!is_numeric($a)) { throw new \Exception(…) } if(!is_numeric($b)) { throw new

    \Exception(…) } if($a < $b) { throw new \Exception(…) } $pounds = $a - $b;
  10. Sugar + Yeast = Alcohol + CO 2 C H

    O ->2C H OH + 2CO 6 12 6 2 5 2
  11. Identifiable Have State and are Mutable (Lifecycle) Operate using Value

    Objects *(Ideally) Storage Agnostic *(Ideally) Never in an Invalid State Entities
  12. $book->setPrice(16.96); $amount = new Amount(16.96, new Currency(‘USD’); $price = new

    BookPrice($book, $amount); $price->change(new Amount(15.99, new Currency(‘USD’)); Mutable Immutable
  13. $recipe = new Recipe($time + //…); $recipe->addThisIngredient($time + //…); $recipe->addWater($time

    + //…); $recipe->addThatIngredient($time + //…); $recipe->boil($time + //…); $recipe->getEstimatedABV($time);
  14. $recipe = new Recipe($history + //…); $recipe->addThisIngredient($history + //…); $recipe->addWater($history

    + //…); $recipe->addThatIngredient($history + //…); $recipe->boil($history + //…); $recipe->getEstimatedABV($history);
  15. PHP BEER BREWING SOFTWARE FOR BITTER DEVELOPERS WHO WANT TO

    BREW EVEN MORE BITTER BEERS And never heard of not-invented-here and wanna learn and do other good stuff too.