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

PHP For Grown Ups

PHP For Grown Ups

My first User Group talk filled to the brim with tips on writing maintainable, reliable and (re)usable PHP applications.

Andreas Lindeboom

December 23, 2014
Tweet

Other Decks in Programming

Transcript

  1. EXTRACT METHOD // before: if (is_numeric($amount) && $amount > 0)

    // after: if ($this->isValidAmount($amount))
  2. /** * If what this method does can not be

    made obvious from * its name, explain it here. * * @param string $firstname * @return void */ public function changeFirstName($firstName) { // code }
  3. “Shy code - modules that don’t reveal anything unnecessary to

    other modules and that don’t rely on other modules’ implementations” - The Pragmatic Programmer
  4. $totalPrice = 0; foreach ($order->getItems() as $item) { /** @var

    OrderItem $item */ $amount = $item->getAmount(); $price = $item->getPrice(); $totalPrice += $amount * $price; } $totalPrice += $order->getShippingCosts();
  5. $discountedItems = array(); foreach ($order->getItems() as $item) { /** @var

    OrderItem $item */ $oldPrice = $item->getPrice(); $newPrice = $oldPrice - ($oldPrice * ($discountPercentage / 100)) $item->setPrice($discountPercentage); $discountedItems[] = $item; } $order->setItems($items);
  6. Before: class EmployeeService { /** * @param integer $employeeId *

    @return void */ public function delete($id) { $employeeStore = new EmployeeStore(); $employeeStore->deleteById($id); } }
  7. After: class EmployeeService { /* * @var EmployeeStore */ private

    $employeeStore /** * @param mixed $employeeStore * @return void */ public function __construct($employeeStore) { $this->employeeStore = $employeeStore; } // rest of class here... }
  8. /** * @param integer $id * @return void */ public

    function deleteById($id) { $this->employeeStore->deleteById($id); }
  9. class PdoEmployeeStore implements EmployeeStoreInterface { /** * @param integer $id

    */ public function deleteById($id) { // PDO implementation here } }
  10. “Mathematics is the art of giving the same name to

    different things.” ― Henri Poincaré
  11. /** * @param string $searchTerm * @param string $productCategory *

    @param string $make * @param string $color */ public function search($searchTerm, $productCategory, $make, $color) { switch ($productType) { // search products } }
  12. /** * @param SearchTerm $searchTerm * @param ProductCategory $productCategory *

    @param Make $make * @param Color $color */ public function search( SearchTerm $searchTerm, ProductCategory $productCategory, Make $make, Color $color ) { switch($productType->getTypeId()) // search products ) }
  13. VALUE OBJECTS class SearchTerm { const MAX_TERM_LENGTH = 30; /**

    * @var string */ private $searchTerm; /** * @param string $term * @throws InvalidTermException */ public function __construct($term) { if (strlen($term) >= self::MAX_TERM_LENGTH) { throw new InvalidTermException($term); } } }
  14. “Figuring out if two people are married is easy. Figuring

    out if they should be is hard.” - Michael Feathers
  15. /** * @param SearchQuery $query * @return SearchResults */ public

    function search(SearchQuery $query) { /** @var SearchWorker $worker */ $worker = $this->getWorkerForQuery($query); /** @var SearchResults $results */ $results = $worker->process($query); return $results; }
  16. LOW LEVEL OF ABSTRACTION $statement = $database->prepare( “INSERT INTO `fish`(‘name’,

    ‘species’, ‘gender’, ‘tankId’) VALUES(?, ?, ?, ?)” ); $statement->execute(array(‘Nemo’, $speciesId, ‘M’, $tankId));
  17. if (! $amount) { // do something } // $amount

    can actually be 0, “0”, “”, null or false for this to be true
  18. if ($amount == 0) { // do something } //

    you would think that explicitly checking for 0 would improve things...
  19. if ($amount === 0) { // do something } //

    this will only evaluate as true when $amount is actually the number 0
  20. CRANK YOUR ERROR REPORTING UP KNOW WHY YOUR CODE WORKS

    BE AWARE OF FAILURE SCENARIOS CATCH AND THROW EXCEPTIONS
  21. // FILE: composer.json { "repositories": [ { "type": "vcs", "url":

    "http://github.com/user/repo" }, ], “require”: { “user/package”: “*” } }
  22. $userAccount = new UserAccount($userName, $password); $authenticationManager->register($userAccount); $customer = new Customer($firstName,

    $lastName, $email); $customer->linkUserAccount($userAccount); $customerService->register($customer); $authenticationService->login($userName, $password)
  23. public function ship(Product $product, $shippingMethod) { switch ($shippingmethod) { case

    shipping::shipping_default: $this->defaultshipping($product); break; case shipping::shipping_priority: $this->priorityshipping($product); break; } }
  24. public function addShippingMethod(ShippingMethodInterface $method, $identifier) { $this->shippingMethods[$identifier] = $method; }

    public function ship(Product $product, $shippingMethodIdentifier) { $shippingMethod = $this->shippingMethods[$shippingMethodIdentifier]; $shippingMethod->ship($product); }
  25. “Any implementation of an abstraction (interface) should be substitutable in

    any place that the abstraction is accepted” - Jeffrey Way
  26. class Car implements VehicleInterface { public function driveTo(Destination $destination) {

    // start driving } public function swapTires(TyreTypeInterface $tyreType) { // swap tyres } }
  27. class Boat implements VehicleInterface { public function driveTo(Destination $destination) {

    // start driving } public function swapTires(TyreTypeInterface $tyreType) { throw new BoatHasNoWheelsException(); } }
  28. class FooBarIncSupplier implements SupplierInterface { public function order(Product $product) {

    $orderId = $this->fooBarInc->createProductOrder(); $this->fooBarInc->addProductToOrder($orderId); } }
  29. READING LIST Patterns of Enterprise Application Architecture - Martin Fowler

    Clean Code - Robert C. Martin Growing Object-Oriented Software, Guided By Tests (the GOOS book) - Steve Freeman & Nat Pryce The Pragmatic Programmer - Dave Thomas & Andy Hunt
  30. VIDEOS Models and Service Layers; Hemoglobin and Hobgoblins - Ross

    Tuck (https://www.youtube.com/watch?v=3uV3ngl1Z8g) Unbreakable Domain Models - Mathias Verraes (https:// www.youtube.com/watch?v=ZJ63ltuwMaE) The Framework As An Implementation Detail (https:// www.youtube.com/watch?v=0L_9NutiJlc)