# PHPRefactor

## 1 Refactorings

Smell: An array with elements of generic type or method which can throw Exception

public function printUsersNames(array $users): void { foreach ($users as $user) { echo$user->getName();
}
}


#### 1.1.1 Refactor the code

Add PHPDoc - the Object[] notation in addition to an array type-hint to explain what kind of object is expected

/**
* @param User[] $users */ public function printUsersNames(array$users): void
{
foreach ($users as$user) {
echo $user->getName(); } }  ### 1.2 Add Type-Hint Smell: A method with no type defined parameters or return type declaration public function setNumber($number)
{
$this->number =$number;
}


public function setNumber(int $number): void {$this->number = $number; }  #### 1.2.2 Helper phpdoc-to-typehint adds automatically scalar type hints and return types to all functions and methods using existing PHPDoc annotations #### 1.2.3 Further Reading ### 1.3 Consolidate Conditional Expression Smell: Sequence of conditionals with the same result class Sale { public function calculateShipping(Customer$customer)
{
if ($customer->isEmployee) return 0; if ($customer->isGoldCustomer) return 0;
if ($customer->isHasACoupon) return 0; if($isUsa) return 10;
if($isEurope) return 20; } }  #### 1.3.1 Write a test that pass #### 1.3.2 Refactor the code Combine them into a single conditional expression and extract it. class Sale { public function calculateShipping(Customer$customer): int
{
if ($this->isFreeShipping()){ return 0; } if($isUsa) {
return 10;
}

if($isEurope) { return 20; } } private function isFreeShipping(): bool { return ($customer->isEmployee || $customer->isGoldCustomer ||$customer->isHasACoupon);
}
}


### 1.4 Consolidate Duplicate Conditional Fragments

Smell: The same fragment of code is in all branches of a conditional expression.

final class Sale
{
public function calculateTotal(int $price) { if ($this->isSpecialDeal()) {
$total =$price * 0.95;
$this->setTotal($total);
}
else {
$total =$price * 0.98;
$this->setTotal($total);
}
}
}


#### 1.4.2 Refactor the code

Move it outside of the expression.

final class Sale
{
public function calculateTotal(int $price) { if ($this->isSpecialDeal()) {
$total =$price * 0.95;
}
else {
$total =$price * 0.98;
}

$this->setTotal($total);
}
}


### 1.5 Decompose Conditional

Smell: Complicated conditional (if-else) statement.

class Sale
{
public $expired_at; public$amount;

public function getAmount()
{
if(null !== $this->expired_at &&$this->expired_at < time())
{
$interest = 10;$this->amount = $this->amount + ($this->amount / 100 * $interest); } else {$discount = 10;
$this->amount =$this->amount - ($this->amount / 100 *$discount);
}
return $this->amount; } }  #### 1.5.1 Write a test that pass class SaleTest extends TestCase { public function testAmount() {$sale = new Sale();
$sale->amount = 10;$sale->expired_at = strtotime('-10 days');
$this->assertEquals(10 + (10 / 100 * 10),$sale->getAmount());
$sale = new Sale();$sale->amount = 10;
$sale->expired_at = strtotime('+10 days');$this->assertEquals(10 - (10 / 100 * 10), $sale->getAmount()); } }  #### 1.5.2 Refactor the code Extract conditional code in a private method. We name the method isExpired() because our conditional chunk of code checks if the sale is expired. We create the private method isExpired() and, with the technique of extract method, we move chunks of code into the new method. The next step is to move each branch of the condition in a private method. We do the same as we did before for each branch. So we create the private method getAmountWithInterest() for the first branch and the method getAmountWithDiscount() for the second branch. class Sale { public$expired_at;
public $amount; public function getAmount() { if ($this->isExpired()) {
return $this->getAmountWithInterest(); } else { return$this->getAmountWithDiscount();
}
}

private function isExpired()
{
return !is_null($this->expired_at) &&$this->expired_at < time();
}

private function getAmountWithInterest()
{
$interest = 10; return$this->amount + ($this->amount / 100 *$interest);
}

private function getAmountWithDiscount()
{
$discount = 10; return$this->amount - ($this->amount / 100 *$discount);
}
}


### 1.6 Encapsulate Field

Smell: A public field

final class User
{
/**
* @var string
*/
public $name; }  #### 1.6.1 Write a test that pass #### 1.6.2 Refactor the code Make it private and provide accessors. final class User { /** * @var string */ private$name;

public function getName(): string
{
return $this->name; } public function setName(string$name): void
{
$this->name =$name;
}
}


### 1.7 Extract Class

SmellL Large Class

final class User
{
private $name; private$surname;

private $city; private$zipCode;
private $street; private$state;
}


#### 1.7.2 Refactor the code

Create a new class and move the relevant fields and methods from the old class into the new class.

final class User
{
private $name; private$surname;

private $address; } final class Address { private$city;
private $zipCode; private$street;
private $state; }  #### 1.7.3 Pass a test ### 1.8 Extract Function Alias: Extract Method Inverse of: Inline Function Smell: Code fragment that can be grouped together public function printInvoice(Invoice$invoice): void
{
echo 'Invoice';
echo '<br>';
echo $invoice->getNumber(); echo 'phpRefactor: '; echo '<br>'; echo$invoice->getDate();
}


#### 1.8.2 Refactor the code

Turn the fragment into a method whose name explains the purpose of the method

public function printInvoice(Invoice $invoice): void { printInvoiceHeader($invoice);
printInvoiceFooter($invoice); } function printInvoiceHeader(Invoice$invoice): void
{
echo 'Invoice';
echo '<br>';
echo $invoice->getNumber(); } function printInvoiceFooter(Invoice$invoice): void
{
echo 'phpRefactor: ';
echo '<br>';
echo $invoice->getDate(); }  #### 1.8.3 Run a test #### 1.8.4 Notes function printInvoice() {$footer=function() {
echo "phpRefactor.com \n";
echo "2019";
};

$footer(); } printInvoice();  ### 1.9 Extract Variable Alias: Introduce Explaining Variable Smell: Complicated expression if(($stock->checkStatus($order->getItem) >$order->getQuantity())
if($stockAvailable &&$freeShipping && $addressMatches);  #### 1.9.3 Pass a test ### 1.10 Inline Class Smell: A class isn't doing very much final class User { private$name;
private $surname; private$telephoneNumber;
}

final class TelephoneNumber
{
private $number; }  ### 1.11DONE Inline Function Smell: A function's body is just as clear as it's name class Circle { public const RADIUS = 2; public function getArea(): float { return$this->getValueOfPI() * self::RADIUS * self::RADIUS;
}

private function getValueOfPI(): float
{
return pi();
}
}


#### 1.11.1 Write a test that pass

use PHPUnit\Framework\TestCase;

class CircleTest extends TestCase
{
public function testGetArea()
{
$circle = new Circle();$this->assertEquals( 12.566370614359172, $circle->getArea()); } }  PHPUnit 7.4.3 by Sebastian Bergmann and contributors. . 1 / 1 (100%) Time: 53 ms, Memory: 10.00MB OK (1 test, 1 assertion)  #### 1.11.2 Refactor the code Put the method's body into the body of its callers and remove the method. public function getArea(): float { return pi() *$radius * $radius; }  #### 1.11.3 Pass a test ### 1.12 Inline Variable Smell: Variable name doesn't really communicate more than the expression itself or gets in the way of refactoring neighboring code. let basePrice = anOrder.basePrice; return (basePrice > 1000);  #### 1.12.1 Refactor the code return anOrder.basePrice > 1000;  140 ### 1.13 Introduce Parameter Object Smell: Long Parameter List and parameters that naturally go together final class Account { public function findAllTransactions(DateTime$start, DateTime $end) { ... } }  #### 1.13.1 Write a test that pass #### 1.13.2 Refactor the code Replace them with an object. #+BEGINSRC php#+ENDSRC #### 1.13.3 Pass a test ### 1.14 Optimize Imports Smell: Imports unused or not in alphabetically order. Multiple use statement use SomeClass\Worker; use SomeClass\Foo; use SomeClass\UnusedClass;  #### 1.14.1 Write a test that pass #### 1.14.2 Refactor the code Remove unused imports. Sort imports alphabetically (ascending order). Splits multiple use statement imports into single use statement imports use SomeClass\{Foo, Worker};  #### 1.14.3 Pass a test ### 1.15 Move Method Smell: Method accessing fields and methods in different class final class Customer { function printInvoice(Order$order)
{
echo "Invoice {$order->getId()}"; echo "Date: {$order->getDate()}";
echo "Customer: {$this->getName()}";$address = $order->getAddress(); echo "City: {$address->getCity()}";
echo "Address: {$address->getStreet()}"; foreach ($order->getItems() as $item){ echo "Name: {$item->getName()}";
echo "Price: {$item->getPrice()}"; } } }  #### 1.15.1 Write a test that pass #### 1.15.2 Refactor the code Move all its features into another class and delete it. final class Order { function printInvoice() { echo "Invoice {$this->getId()}";
echo "Date: {$this->getDate()}"; echo "Customer: {$this->getCustomer()->getName()}";

$address =$this->getAddress();
echo "City: {$address->getCity()}"; echo "Address: {$address->getStreet()}";

foreach ($this->getItems() as$item){

echo "Name: {$item->getName()}"; echo "Price: {$item->getPrice()}";
}
}
}


### 1.16 Parameterize Method

Smell: Several methods do similar things but with different values contained in the method body.

final class Employee
{
/**
* @var float
*/
private $salary; public function setSalary(float$salary)
{
$this->salary =$salary;
}

public function getSalary(): float
{
return $this->salary; } public function fivePercentRaise() {$this->salary += $this->salary* (5 / 100); } public function tenPercentRaise() {$this->salary += $this->salary* (10 / 100) ; } }  #### 1.16.1TODO Write a test that pass #### 1.16.2 Refactor the code Create one method that uses a parameter for the different values. final class Employee { /** * @var float */ private$salary;

public function setSalary(float $salary) {$this->salary = $salary; } public function getSalary(): float { return$this->salary;
}

public function raise(float $percent) {$this->salary += $this->salary * ($percent / 100);
}
}


### 1.17 Preserve Whole Object

Smell: More than one value from an object are passing as parameters in a method call

class September
{
/**
* @var float
*/
private $highestTemp; /** * @var float */ private$lowestTemp;

public function __construct(float $highestTemp, float$lowestTemp)
{
$this->highestTemp =$highestTemp;
$this->lowestTemp =$lowestTemp;
}

public function getHighestTemp(): float
{
return $this->highestTemp; } public function getLowestTemp(): float { return$this->lowestTemp;
}
}

class Calculator
{
public function calculateAverageTemperature(float $highestTemp, float$lowestTemp)
{
return ($highestTemp +$lowestTemp) / 2;
}
}

$september = new September(15,5);$calculator = new Calculator();

$averageTemperature =$calculator->calculateAverageTemperature(
$september->getHighestTemp(),$september->getLowestTemp()
);


#### 1.17.1 Write a test that pass

public function testCalculateAverageTemperature()
{
$september = new September(15,5);$calculator = new Calculator();

$averageTemperature =$calculator->calculateAverageTemperature(
$september->getHighestTemp(),$september->getLowestTemp());

$this->assertEquals(10,$averageTemperature);
}


#### 1.17.2 Refactor the code

Add object as a new parameter. Set it default value to null, that will help to manage the transitions towards the final version of the method.

class Calculator
{
public function calculateAverageTemperature(float $highestTemp, float$lowestTemp, September $september = null) { return ($highestTemp + $lowestTemp) / 2; } }  #### 1.17.3 Pass a test #### 1.17.4 Refactor the code Replace values with values coming from the whole object class Calculator { public function calculateAverageTemperature(float$highestTemp, float $lowestTemp, September$september = null)
{
return ($september->getHighestTemp() +$september->getLowestTemp()) / 2;
}
}


#### 1.17.6 Refactor the code

Remove useless parameters and default null value of $september object class Calculator { public function calculateAverageTemperature(September$september)
{
return ($september->getHighestTemp() +$september->getLowestTemp()) / 2;
}
}


### 1.18 Pull Up Method

Smell: Subclasses have the same method.

class Employee
{
/**
* @var string
*/
protected $name; public function __construct(string$name)
{
$this->name =$name;
}
}

final class Salesman extends Employee
{
public function getName()
{
return $this->name; } } final class Engineer extends Employee { public function getName() { return$this->name;
}
}


#### 1.18.2 Refactor the code

Move the methods to the super class.

class Employee
{
/**
* @var string
*/
protected $name; public function __construct(string$name)
{
$this->name =$name;
}

public function getName()
{
return $this->name; } } final class Salesman extends Employee {} final class Engineer extends Employee {}  #### 1.18.3 Pass a test ### 1.19 Remove Assignments to Parameters Smell: Reassign to a parameter public function discount(int$priceTotal): int
{
if ($priceTotal > 100) {$priceTotal = $priceTotal - 10; } return$priceTotal;
}


#### 1.19.2 Refactor the code

public function discount(int $priceTotal): int {$result = $priceTotal; if ($priceTotal > 100) {
$result =$result - 10;
}

* @return void
*/
return $db->query(...); } }  #### 1.22.1 Write a test that pass #### 1.22.2 Refactor the code Move global variable in class to the constructor final class Item { /** * @var Database */ private$db;

public function __construct(Database $db) {$this->db = $db; } public function fetch() { return$db->query(...);
}
}


### 1.23DONE Replace Magic Number With Symbolic Constant

Smell: Number with a particular meaning

final class Circle
{
/**
* @var float
*/
private $radius; public function __construct(float$radius)
{
$this->radius =$radius;
}

public function getCircumference(): float
{
return $this->radius * 2 * 3.1416; } }  #### 1.23.1 Write a test that pass use PHPUnit\Framework\TestCase; class CircleTest extends TestCase { public function testGetCircumference() {$circle = new Circle(2);
$this->assertEquals(12.5664,$circle->getCircumference());
}
}

PHPUnit 7.5.2 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 151 ms, Memory: 10.00MB

OK (1 test, 1 assertion)



#### 1.23.2 Refactor the code

Create a constant, name it after the meaning, and replace the number with it

final class Circle
{
/**
* @var float
*/
private const PI = 3.1416;

/**
* @var float
*/
private $radius; public function __construct(float$radius)
{
$this->radius =$radius;
}

public function getCircumference(): float
{
{
if($from){$this->mailer->send($to,$body, $from); }else{$this->mailer->send($to,$body, $this->defaultSender); } } }  #### 1.24.1 Write a test that pass #### 1.24.2 Refactor the code Create a separate method for each value of the parameter final class EmailNotification { public function send(string$to, string $body, string$from)
{
$this->mailer->send($to, $body,$from);
}

public function sendFromDefaultSender(string $to, string$body)
{
$this->mailer->send($to, $body,$this->defaultSender);
}
}


### 1.25 Replace Temp with Query

Smell: Using a temporary variable to hold the result of an expression. Damage: Temporary variable increase the temptation to write longer methods. Temporaries aren’t necessarily bad, but sometimes they attract new code.

public function getTotalPrice(): int
{
$basePrice =$this->quantity * $this->itemPrice; if ($basePrice > self::DISCOUNT_POINT) {
return $basePrice * self::DISCOUNT; } return$basePrice;
}


#### 1.25.2 Refactor the code

Extract the expression into a method. Replace all references to the temp with the expression. The new method can then be used in other methods.

public function getTotalPrice(): int
{
if ($this->getBasePrice() > self::DISCOUNT_POINT) { return$this->getBasePrice() * self::DISCOUNT;
}
return $this->getBasePrice(); } public function getBasePrice(): int {$this->quantity * $this->itemPrice; }  #### 1.25.3 Pass a test #### 1.25.4 Info Now, but wait, you might say. Isn't this more inefficient? Because if we created the temp the old way, we'd only have to execute the expression once, but if we turn it into a method, we might be calling it many different times. And yes, you're absolutely right, but remember, the pure efficiency of the code is not our first goal in refactoring. Clarity is. The likelihood is that a typical expression you would deal with in this sort of refactoring is going to be so undemanding, it wouldn't be noticeable at all, even having to call it several more times. But if it is an intensive operation, an intensive expression, well you should really be working on that later, after you've refactored using profilers. And other tools to make sure you're not doing pointless, premature optimization. And the real benefit is that by creating this as its own method, we will also have use of it anywhere else in the class, which wasn't the case before. As the original temp was scoped to the original method. So, we won't be tempted to add more code to the original method just to have access to that temp. ### 1.26 Replacing Type Code with Subclasses Smell: Immutable type code affecting the class behavior. final class Account { /** * @var int */ private$accountType;

/**
* @var float
*/
private $balance; /** * @var int */ public const CHECKING = 0; /** * @var int */ public const SAVINGS = 1; /** * @var int */ public const INVESTMENT = 2; public function __construct(int$accountType)
{
$this->accountType =$accountType;
}

public function getAccountType(): int
{
return $this->accountType; } public function getBalance(): float { return$this->balance;
}

public function withdraw(float $amount): void { switch ($this->accountType){
case self::CHECKING:
$this->balance -=$amount;
break;
case self::SAVINGS:
$this->balance -=$amount + 100;
break;
case self::INVESTMENT:
$this->balance -=$amount + 300;
break;
default:
throw new RuntimeException('Unknown Account Type');
}
}
}


#### 1.26.2 Refactor the code

Replace the type code with subclasses.

abstract class Account
{
/**
* @var float
*/
private $balance; public function getBalance(): float { return$this->balance;
}

abstract public function withdraw(float $amount): void } final class AccountChecking extends Account { public function withdraw(float$amount): void
{
$this->balance -=$amount;
}
}

final class AccountSavings extends Account
{
public function withdraw(float $amount): void {$this->balance -= $amount + 100; } } final class AccountInvestment extends Account { public function withdraw(float$amount): void
{
$this->balance -=$amount + 300;
}
}


### 1.27 Separate Query from Modifier

Smell: A method that returns a value but also changes the state of an object.

final class Account
{
/**
* @var float
*/
private $balance; public function withdrawAndGetBalance(float$amount): float
{
$this->balance -=$amount;
return $this->balance; } }  #### 1.27.1 Write a test that pass #### 1.27.2 Refactor the code Create two methods, one for the query and one for the modification. final class Account { /** * @var float */ private$balance;

public function getBalance(): float
{
return $this->balance; } public function withdraw(float$amount): void
{
$this->balance -=$amount;
}
}


### 1.28 Split Temporary Variable

Smell: Temporary variable is assigned to more than once (overwrite), but is not a loop variable nor a collecting temporary variable.

$temp =$item.getPrice() * item.getQuantity();
echo "Total: $temp";$temp = order.getTotal() - order.getDiscount();
echo "Price after discount: $temp;"  #### 1.28.1 Write a test that pass #### 1.28.2 Refactor the code Make a separate temporary variable for each assignment. $totalPrice = $item.getPrice() * item.getQuantity(); echo "Total:$totalPrice";
$totalDiscountPrice = order.getTotal() - order.getDiscount(); echo "Price after discount:$totalDiscountPrice";


## 2 Tutorials

 Automated Tests with PHPUnit Anna Filina testing - PHPUnit Catalog of Refactoring to Patterns Joshua Kerievsky patterns Catalog of Refactorings Martin Fowler refactoring Clean Code PHP Piotr Plenik clean code Detecting Code Smells Patkós Csaba refactoring Doctrine Best Practices Marco Pivetta (Ocramius) doctrine Encapsulation and SOLID Mark Seemann SOLID Extremely Defensive PHP Programming Marco Pivetta (Ocramius) defensive programming How to Refactor Like a Boss 1 Michael Cheng refactoring How to Refactor Like a Boss 2 Michael Cheng refactoring HTTP Smoke Testing Peter Heinz testing - smoke test Introduction to Testing with PHPUnit Trevor Sawler testing - PHPUnit Legacy Coderetreat (Java) Adrian Bolboaca refactoring List of Static Analysis Tools analysis PHP: Testing Legacy Applications Chris Hartjes testing - PHPUnit PHPUnit: Testing with a Bite Ryan Weaver testing - PHPUnit Programming Foundations: Refactoring Code Simon Allardice refactoring Programming Foundations: Test-Driven Development Simon Allardice testing - TDD Refactoring 101 Adam Culp refactoring Refactoring Legacy Code Patkós Csaba refactoring Refactoring Legacy Code Adam Culp refactoring Refactoring to Collections Adam Wathan collections Solving the N+1 Problem Paul M. Jones database Steps Toward Modernizing a Legacy Codebase Paul M. Jones refactoring Techniques for Refactoring Code Patkós Csaba refactoring

### 2.1Behavior-Driven Development

#### 2.1.1 The 5 Ws

1. As (who, what or where)
2. I (want)
3. because (why)

Example: Who - as a user of Acme.com What - I want to access content on my mobile phone Why - because I might not always have a computer available

#### 2.1.2 Throw Over the Wall

1. Developers would coe and then throw it over the wall for someone else to test

#### 2.1.3 After BDD Transformation

1. testing cycle went down
2. defect count went down
3. time to market went down
4. team's confidence in code increased and anxiety decreased
5. manual testing cost went down

"The hardest part of building a software system is deciding precisely what to build." - Fred Brooks

If you're having trouble, example mapping helps us keep these conversations short and on track by creating a visual representation of a user story to guide and document the discussion. The process of example mapping is fairly straightforward. Using a four-color pack of index cards, we build a visual representation of our user's story with each color providing a specific piece of information. We build this as we have our conversation to document what is discovered through the discussion about the user's story.

We begin with a yellow card, which contains the name of our story itself and place this at the very top. Our blue cards represent specific rules that constrain the scope of our story. This is our acceptance criteria. With green cards, we provide concrete examples of the user's story in the context of a specific rule. So we place these under the relevant blue card. And finally, we have our red cards. These cards contain questions that cannot be immediately answered during the discussion, but are captured so that we can move on with the conversation.

6. Acceptance criteria
1. addresses what defines a working system
2. written as pass/fail
7. Scenario
1. defines the initial conditions for acceptance criteria
2. states the trigger of scenario and expected outcome

#### 2.1.4 Gherkin Syntax

1. Feature: feature story - name of the feature and possibly brief description
1. Scenario: a user story - single concrete example of how a system should behave - each feature generally have 5-20 scenarios - Scenarios describe the behaviour of the system under specific initial conditions.
2. Given: some set of initial conditions - describe the context or precondition for the scenario
3. When: an event occurs - identifies an event or actor enacted by some actor on the system
4. Then: an outcome is expected - provides the expected outcome to the scenario

#### 2.1.5 Example

1. Feature : Customer pays with a credit card
1. As a sales associate
2. I should be able to process payments
3. when given a credit card

Now we're ready to translate our conversation into scenarios that describe the concrete behavior of the application. Ideally, this is done using declared dephrasing, meaning without referencing the particulars of a user interface or sequence of steps. Remember that Gherkin is a way to phrase our acceptance criteria as an executable scenario that describes the behavior of a system. So, our conversations would describe the behavior of the system under specific initial conditions.

4. Scenario 1
1. Total charge is over the $2 credit card minimum. 2. Given: Maria orders$3 of coffee from Li.
3. When: Maria pays with a credit card.
4. Then: Lit should process the payment.
5. Scenario 2
1. Total charge is under the $2 credit card minimum. 2. Given: Maria orders$1 of coffee from Li.
3. When: Maria pays with a credit card.
4. Then: Li should not process the payment.

#### 2.1.6 Test Automation

Allows for the execution of software tests that compare the expectations for software with the actual outcomes. Testing can be repetitive process and automation can be a boon to productivity.

#### 2.1.7 Living Documentation

Is a system for dynamically generating documentation that contains information which is up to date and accurate. Cucumber provides a system that dynamically generates documentation because of the manner that tests are written. Because Cucumber tests are written in a way that can be easily interpreted by non-technical stakeholders and, at the same time, be executed by a computer, your tests themselves become a living source of documentation that reflect the accuracy of your application. Cucumber was designed to enhance the practice of test-driven development. It provides a single source of truth for an application's lifecycle by merging test automation and test documentation.

#### 2.1.8 Further

1. https://cucumber.io/school
2. https://cucumber.io/training
3. BDD in Action by John Ferguson Smart
4. The Cucomber Book by Aslak Hellesoy…

#### 2.1.9 Notes

1. BDD is a process, not a tool
2. Specialized frameworks can assist in this process by providing a common language for acceptance criteria.

To types of BDD:

1. Story - is done with Behat & functional tests
2. Spec - is done with PHPSpec & Unit tests

4 Steps to BDD 1.Define Business Value of all big features 2.Prioritize you features 3.Break feature down into user stories 4.Write the code for the feature

### 2.2Test Automation Foundations

Automated testing follows the same steps as manual testing, but it's much quicker. While there is an initial time investment to write the scripts, once the scripts are complete they can be run repeatedly without much additional cost.

1. There will be maintenance that is required, but it saves time in the long run. This makes automation have a great return on investment. In addition, the exact same steps are executed every time, which reduces any possibility of human error.
3. Test Pyramid

### 2.3Clean Application Development Adam Culp

• is easy
• fast

result:

• wasted time
• bugs
• excessive debugging
• procrastination
• technical debt
• financial losses
• company killer
• I didn't write it!

Names should be clear - functions and variables should tell a story $elapsed ->$elapsedTimeInDays

Class - nouns - Describe ex - Customer, Account, Product, Company Method - verbs - getCustomer, closeAccount, updateProduct, addCompany Function - 20 lines - 10 lines

Recognizing bad dosen't mean we know how to make good - we know a good/bad, but are not song writers

smells - are indications of problems in your code

CodeSniffer

## 3 Books

1. Taxonomy

### 3.2 Feathers, Michael; Working Effectively with Legacy Code; 2005

• To me, legacy code is simply code without tests. I’ve gotten some grief for this definition. What do tests have to do with whether code is bad? To me, the answer is straightforward, and it is a point that I elaborate throughout the book: 'Code without tests is bad code. It doesn’t matter how well written it is; it doesn’t matter how pretty or object-oriented or well-encapsulated it is. With tests, we can change the behavior of our code quickly and verifiably. Without them, we really don’t know if our code is getting better or worse.'
• being able to confidently make changes in any code base.
• Preserving existing behavior
• Changes in a system can be made in two primary ways. I like to call them Edit and Pray and Cover and Modify. Unfortunately, Edit and Pray is pretty much the industry standard. When you use Edit and Pray, you carefully plan the changes you are going to make, you make sure that you understand the code you are going to modify, and then you start to make the changes. When you’re done, you run the system to see if the change was enabled, and then you poke around further to make sure that you didn’t break anything. The poking around is essential. When you make your changes, you are hoping and praying that you’ll get them right, and you take extra time when you are done to make sure that you did.
• …testing is a tough problem, and people are often seduced by the idea that they can test through a GUI or web interface without having to do anything special to their application. It can be done, but it is usually more work than anyone on a team is prepared to admit. In addition, a user interface often isn’t the best place to write tests. UIs are often volatile and too far from the functionality being tested. When UI-based tests fail, it can be hard to figure out why. Regardless, people often spend considerable money trying to do all of their testing with those sorts of tools.
• Pay now or pay more later

### 3.3 Fowler, Martin; 2018

• With any introductory example, however, I run into a problem. If I pick a large program, describing it and how it is refactored is too complicated for a mortal reader to work through.(…) However, if I pick a program that is small enough to be comprehensible, refactoring does not look like it is worthwhile.
• Thus, if I’m faced with modifying a program with hundreds of lines of code, I’d rather it be structured into a set of functions and other program elements that allow me to understand more easily what the program is doing. If the program lacks structure, it’s usually easier for me to add structure to the program first, and then make the change I need.
• If the code works and doesn’t ever need to change, it’s perfectly fine to leave it alone. It would be nice to improve it, but unless someone needs to understand it, it isn’t causing any real harm. Yet as soon as someone does need to understand how that code works, and struggles to follow it, then you have to do something about it.
• Refactoring changes the programs in small steps, so if you make a mistake, it is easy to find where the bug is.
• Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
• The true test of good code is how easy it is to change it.
• Refactoring (noun): a change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior
• Refactoring (verb): to restructure software by applying a series of refactorings without changing its observable behavior.
• Refactoring is very similar to performance optimization, as both involve carrying out code manipulations that don’t change the overall functionality of the program. The difference is the purpose: Refactoring is always done to make the code “easier to understand and cheaper to modify.” This might speed things up or slow things down. With performance optimization, I only care about speeding up the program, and am prepared to end up with code that is harder to work with if I really need that improved performance.
• Without refactoring, the internal design—the architecture—of software tends to decay.As people change code to achieve short­term goals, often without a full comprehensionof the architecture, the code loses its structure. It becomes harder for me to see thedesign by reading the code. Loss of the structure of code has a cumulative effect. Theharder it is to see the design in the code, the harder it is for me to preserve it, and themore rapidly it decays. Regular refactoring helps keep the code in shape.
• It reminds me of a statement Kent Beck often makes about himself: “I’m not a great programmer; I’m just a good programmer with great habits.” Refactoring helps me be much more effective at writing robust code.
• Branches. As I write this, a common approach in teams is for each team member to work on abranch of the code base using a version control system, and do considerable work onthat branch before integrating with a mainline (often called master or trunk) sharedacross the team. Often, this involves building a whole feature on a branch, notintegrating into the mainline until the feature is ready to be released into production.Fans of this approach claim that it keeps the mainline clear of any in­process code,provides a clear version history of feature additions, and allows features to be revertedeasily should they cause problems.There are downsides to feature branches like this. The longer I work on an isolatedbranch, the harder the job of integrating my work with mainline is going to be when I’mdone. Most people reduce this pain by frequently merging or re­basing from mainlineto my branch. But this doesn’t really solve the problem when several people areworking on individual feature branches. I distinguish between merging and integration.If I merge mainline into my code, this is a oneway movement—my branch changes butthe mainline doesn’t. I use “integrate” to mean a two­way process that pulls changesfrom mainline into my branch and then pushes the result back into mainline, changingboth. If Rachel is working on her branch I don’t see her changes until she integrateswith mainline; at that point, I have to merge her changes into my feature branch, whichmay mean considerable work. The hard part of this work is dealing with semanticchanges. Modern version control systems can do wonders with merging complexchanges to the program text, but they are blind to the semantics of the code. If I’vechanged the name of a function, my version control tool may easily integrate mychanges with Rachel’s. But if, in her branch, she added a call to a function that I’verenamed in mine, the code will fail.The problem of complicated merges gets exponentially worse as the length of featurebranches increases. Integrating branches that are four weeks old is more than twice ashard as those that are a couple of weeks old. Many people, therefore, argue for keepingfeature branches short—perhaps just a couple of days. Others, such as me, want themeven shorter than that. This is an approach called Continuous Integration (CI), alsoknown as Trunk­Based Development. With CI, each team member integrates withmainline at least once per day. This prevents any branches diverting too far from eachother and thus greatly reduces the complexity of merges. CI doesn’t come for free: Itmeans you use practices to ensure the mainline is healthy, learn to break large featuresinto smaller chunks, and use feature toggles (aka feature flags) to switch off any in­process features that can’t be broken down.Fans of CI like it partly because it reduces the complexity of merges, but the dominantreason to favor CI is that it’s far more compatible with refactoring. Refactorings ofteninvolve making lots of little changes all over the code base—which are particularlyprone to semantic merge conflicts (such as renaming a widely used function). Many ofus have seen feature­branching teams that find refactorings so exacerbate mergeproblems that they stop refactoring. CI and re­factoring work well together, which iswhy Kent Beck combined them in Extreme Programming.I’m not saying that you should never use feature branches. If they are sufficiently short,their problems are much reduced. (Indeed, users of CI usually also use branches, butintegrate them with mainline each day.) Feature branches may be the right techniquefor open source projects where you have infrequent commits from programmers whoyou don’t know well (and thus don’t trust). But in a full­time development team, thecost that feature branches impose on refactoring is excessive. Even if you don’t go to fullCI, I certainly urge you to integrate as frequently as possible. You should also considerthe objective evidence [Forsgren et al.] that teams that use CI are more effective insoftware delivery.

131

### 3.4 Martin, Robert C.; Clean Code: A Handbook of Agile Software Craftsmanship; 2009

• There are two parts to learning craftsmanship: knowledge and work. You must gain the knowledge of principles, patterns, practices, and heuristics that a craftsman knows, and you must also grind that knowledge into your fingers, eyes, and gut by working hard and practicing.
• Do not refer to a grouping of accounts as an accountList unless it’s actually a List. The word list means something specific to programmers. If the container holding the accounts is not actually a List, it may lead to false conclusions (even if the container is a List, it’s probably better not to encode the container type into the name). So accountGroup or bunchOfAccounts or just plain accounts would be better.
• A truly awful example of disinformative names would be the use of lower-case L or uppercase O as variable names, especially in combination. The problem, of course, is that they look almost entirely like the constants one and zero, respectively.
• Certainly a loop counter may be named i or j or k (though never l!) if its scope is very small and no other names can conflict with it. This is because those single-letter names for loop counters are traditional.
int a = 1;
if ( O == 1 )
a = O1;
else
l = 01;


#### 3.4.1 Naming

1. Use Intention-Revealing Names
$d; //elapsed time in days  The name d reveals nothing. It does not evoke a sense of elapsed time, nor of days. We should choose a name that specifies what is being measured and the unit of that measure- ment: $elapsedTimeInDays;
$daysSinceCreation;$daysSinceModification;
if ( !$var ) { echo 'negation'; }  ### 8.2 Avoid Else, Return Early (Guard Clause) Return as soon as you know your method cannot do any more meaningful work.  public function foo(int$x): string
{
$result = null; if ($x === 1) {
$result = 'a'; } elseif ($x === 2) {
$result = 'b'; } else {$result = 'c';
}

return $result; }   public function foo(int$x): string
{
if ($x === 1) { return 'a'; } if ($x === 2) {
return 'b';
}

if ($x === 3) { return 'c'; } }  Refactoring: Replace Nested Conditional with Guard Clauses Guard clause provides an early exit from a subroutine. Removing one level of nesting and resulting in flatter code. ### 8.3 Avoid Negative Conditionals It is much easier, for the human mind, to comprehend positive reasoning. So if you can avoid negative conditionals, you should always take that path. if (!count){ ... }  if (count == 0){ ... }  ### 8.4 Don't Use 'clone' #### 8.4.1https://dcsg.me/articles/dont-clone-your-php-objects-deepcopy-them/ #### 8.4.2TODO show example with Doctrine ### 8.5 Don't Use 'else if' Else if is not compatible with the colon syntax for if|elseif blocks. For this reason, use elseif for conditionals <?php if ($user) { ?>
<?php } else { ?>
<span>Something went wrong! Please try again later! </span>
<?php } ?>

 if ($user) : ?> <div>OK. Your registration is successful</div> <?php else : ?> <div>Something went wr+ong! Please try again later!</div> <?php endif ?>  Most of the time the alternative (endif) syntax is used in view scripts. It's often hard to see/notice the end of an if statement since a curly brace only takes up one character, when you're at the bottom of a file, it's hard to tell if it's the end of an if or a foreach. For example: <?php if ($condition): ?>

<div>a huge block of html</div>

<?php endif; ?>


https://www.mediawiki.org/wiki/Manual:Coding_conventions/PHP And the latter has poorer performance.

// This:
if ( $foo == 'bar' ) { echo 'Hello world'; } else if ($foo == 'Bar' ) {
echo 'Hello world';
} else if ( $baz ==$foo ) {
echo 'Hello baz';
} else {
echo 'Eh?';
}

// Is actually equivalent to:
if ( $foo == 'bar' ) { echo 'Hello world'; } else { if ($foo == 'Bar' ) {
echo 'Hello world';
} else {
if ( $baz ==$foo ) {
echo 'Hello baz';
} else {
echo 'Eh?';
}
}
}


### 8.6 Don't Use Globals

EVIL in pure form ;)

### 8.7 Don't Use Magic Numbers

Raw numbers in code. Like 86400 - that's a number of seconds per day. But it is not so obvious for every one whats that number means Refactoring: Replace Magic Number with Symbolic Constant

Violating CQS

### 8.9 Don't Use Optional Dependencies

Use Constructor Injection not Setter Injection. Constructor Injection gives you a valid object with all its dependencies, upon construction.

### 8.10 Don't Use Switch Parameter

A method runs different code depending on the values of an parameter Refactoring: Replace Parameter with Method

### 8.13 Eliminate or Reduce Number of Parameters

Functions should have a small number of arguments. No argument is best, followed by one, two, and three. More than three is very questionable and should be avoided with prejudice.

### 8.18 Sprout Method

When adding new functionality, write the code in a new method with TDD and then call this method from the old code. So even if you can’t test the code where your method is being called, at least the new code has tests.

1. Identify where you need to make your code change.
2. If the change can be formulated as a single sequence of statements in one place in a method, write down a call for a new method that will do the work involved and then comment it out. (I like to do this before I even write the method so that I can get a sense of what the method call will look like in context.)
3. Determine what local variables you need from the source method, and make them arguments to the call.

4.Determine whether the sprouted method will need to return values to source method. If so, change the call so that its return value is assigned to a variable.

1. Develop the sprout method using test-driven development.
2. Remove the comment in the source method to enable the call.

### 8.19 Use parentheses

Parentheses help clarify the order of operators…etc. PHP won’t get confused if you don’t use parentheses because it knows the order of operators table very well. However, a person looking at your program has to figure out which is done first, and parentheses help group operations together.

if (age < 20 || sales < 1200 && hrsWorked > 15) {}

if ((age < 20) || ((sales < 1200) && (hrsWorked > 15))) {}


### 8.20 Wrap Class

Choosing to use Wrap Class is a whole other issue. There is a higher thresh- old for this pattern. Generally two cases tip me toward using Wrap Class: 1. The behavior that I want to add is completely independent, and I don’t want to pollute the existing class with behavior that is low level or unre- lated. 2. The class has grown so large that I really can’t stand to make it worse. In a case like this, I wrap just to put a stake in the ground and provide a roadmap for later changes.

### 8.22 Naming

#### 8.22.2 method

• isX() or hasX() for bool return type

#### 8.22.3 snakecase

1. Clients must use API with snakecase (keys in JSON object sent in request body are in snakecase).
2. Database column names are also snakecase.

Based on an eye tracking study on camelCase and snakecase (PDF) from 2010, snakecase is 20% easier to read than camelCase!

 name psr comunnity description method names camelCase() 21/22. lowerunder 1/22 camelCase() Properties names $StudlyCaps or$camelCase or $underscore$camelCase

XMLHttpRequest is still a great tragedy

Based on an (PDF) from 2010, snakecase is 20% easier to read than camelCase! eye tracking study on camelCase and snakecase https://stitcher.io/blog/have-you-thought-about-casing http://www.cs.loyola.edu/~binkley/papers/icpc09-clouds.pdf?fbclid=IwAR2lZJWpYcV-TK2HNpy-JmB3A9g0nSeCeSaDr2ZVh30hSlS41n5O48YoiWc

## 9 Principles

### 9.1 SOLID

There is a strong relationship beetween each of those principles. If you take each of those principles in isolation and try to apply them in your codebase you will get limited benefit out of that. it's only when you take enterly package apply it in it entarity. Applying it all at once. Strong sinergy efect.

#### 9.1.1 Single Responsibilty (SRP)

A class should have only one reason to change - doing one thing, and do it well The object should be able to do the job completely The class has only one well-defined responsibility which is exclusively handling user data. No more, no less.

#### 9.1.2 Open/Closed Principle (OCP)

Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. Interface is open for extension but closed for modification.

#### 9.1.3 Liskov Substitution (LSP)

Metody do klas bazowych, muszą być w stanie używać również obiektów klas dziedziczących po klasach bazowych. Program to an, interface, not an implementation.

#### 9.1.4 Interface Segregation (ISP)

A client should never be forced to implement an interface that it doesn't use or clients shouldn't be forced to depend on methods they do not use.

#### 9.1.5 Dependency Inversion (DIP)

Depend on abstractions, not concretions Program to an, interface, not an implementation.

### 9.2 GRASP General Responsibility Assignment Software Patterns

• Craig Larman 1997 - Applying UML and Patterns (BN)

### 9.3 Design

#### 9.3.1 Separation of Concerns (SoC)

The no.1 - the most important

1. opposite

Big Ball of Mud

#### 9.3.7 The Law of Demeter (LoD)

Each unit should only talk to its friends; don't talk to strangers.

• Object Calisthenics - One Arrow Per Line

### 9.4 Architectural

#### 9.4.1 Model-View-Controller

• The Model: Captures and centralizes all the domain model behaviour. This layer manages all the data, logic and business rules independently of the data representation. It can be said that the Model layer is the heart and soul of every MVC application. • The Controller: Orchestrates interactions between the other layers. Triggers actions on the model in order to update its state and refreshes the representations associated to the model. Additionally, the Controller can also send messages to the View layer in order to change the specific Model representation. • The View: A layer whose main purpose is to expose the differing representations of the Model layer and to give a way to trigger changes on the Model’s state.

## 10 Patterns

• Patterns are formalized best practices.
• is a named description of a problem and solution that can be applied to new contexts

### 10.1 Software design patterns

#### 10.1.1 Creational

Creation of objects themselves - separate the construction of a complex object from its representation

1. Factory

Separating the creation of an object from the actual implementation. If creating the object is a complicated job you can do all of the work in the factory, instead of repeating it every time you want to create a new instance.

1. Simple Factory
class Bicycle
{
}

class SimpleFactory
{
public function createBicycle(): Bicycle
{
return new Bicycle();
}
}

class SimpleFactoryTest extends TestCase
{
public function testCanCreateBicycle()
{
$bicycle = (new SimpleFactory())->createBicycle();$this->assertInstanceOf(Bicycle::class, $bicycle); } }  2. Method Factory interface CarFactory { public function makeCar(); } interface Car { public function getType(); } class SedanFactory implements CarFactory { public function makeCar() { return new Sedan(); } } class Sedan implements Car { public function getType() { return 'Sedan'; } } /* Client */$factory = new SedanFactory();
$car =$factory->makeCar();

3. Abstract Factory
2. Builder
class Car
{
...
}

class CarBuilder
{
public function __construct()
{
$car = new Car; } public function build(): Car { return$car;
}

public function setSeats(int $seats) {$car->setSeats($seats); } }  3. Prototype abstract class Prototype{ protected$name;

public function __construct($name) {$this->name=$name; } abstract function __clone(); public function getName() { return$this->name;
}
}

class ConcretePrototype extends Prototype{

public function __construct($name) { parent::__construct($name);
}
public function __clone() {}
}

// testy
$prototype = new ConcretePrototype("nazwa"); echo$prototype->getName(); // wyswietli "nazwa"
$prototype2 = clone$prototype;
echo  $prototype2->getName(); // wyswietli "nazwa"  4. Dependency Injection A class receives its dependencies from external sources rather than creating them itself. That is, following the Dependency Inversion principle. 1. Types of injection: 1. Construction injection: dependencies are injected when creating the object. It can be used for required and optional dependencies. 2. Setter injection: dependencies are injected through setters, and they are always optional. 3. Property injection: dependencies are injected directly through public properties. This type of injection is not recommended as there is no control at all of what is being injected. 2. Links #### 10.1.2 Structural They act as interconnectors between entities. It serves as a blueprint for how basic classes can be combined to form bigger entities. Structural patterns describe the static architecture of a design; 1. Bridge The Bridge pattern can be quite straightforward; it effectively allows us to decouple an abstraction from an implementation so the two can vary independently. interface FormatterInterface { public function format(string$text);
}

class PlainTextFormatter implements FormatterInterface
{
public function format(string $text) { return$text;
}
}

class HtmlFormatter implements FormatterInterface
{
public function format(string $text) { return sprintf('<p>%s</p>',$text);
}
}

abstract class Service
{
/**
* @var FormatterInterface
*/
protected $implementation; /** * @param FormatterInterface$printer
*/
public function __construct(FormatterInterface $printer) {$this->implementation = $printer; } /** * @param FormatterInterface$printer
*/
public function setImplementation(FormatterInterface $printer) {$this->implementation = $printer; } abstract public function get(); } class HelloWorldService extends Service { public function get() { return$this->implementation->format('Hello World');
}
}

class BridgeTest extends TestCase
{
public function testCanPrintUsingThePlainTextPrinter()
{
$service = new HelloWorldService(new PlainTextFormatter());$this->assertEquals('Hello World', $service->get()); // now change the implementation and use the HtmlFormatter instead$service->setImplementation(new HtmlFormatter());
$this->assertEquals('<p>Hello World</p>',$service->get());
}
}

• A Facade is meant to decouple a client and a sub-system by embedding many (but sometimes just one) interface, and of course to reduce complexity.
• That’s why a good facade has no new in it. If there are multiple creations for each method, it is not a Facade, it’s a Builder or a [Abstract|Static|Simple] Factory [Method].
• The best facade has no new and a constructor with interface-type-hinted parameters. If you need creation of new instances, use a Factory as argument.
• A Facade design pattern works providing a single class that in itself instantiates other classes and provides a simple interface to use those functions. A warning when using such pattern is that, as classes are instantiated within the Facade, you are essentially tightly coupling the classes that it utilizes. There are cases where you want this, but there are cases where you do not. Where do you do not want this behavior, you are better suited to using dependency injection. I have found this to be useful when wrapping a set of poor APIs into a single unified API. It reduces external dependencies, allowing complexity to be internalized; this process can make your code more readable. In other situations, where the various classes were loosely coupled together, we may find it better to use dependency injection. By injecting objects that perform various actions into the ToyFactory class we can benefit from making testing easier by being able to inject fake classes that the ToyFactory class can manipulate. Personally, I am a huge believer in making code as easily testable as possible; hence why I don't like this approach.
class Facade
{
/**
* @var OsInterface
*/
private $os; /** * @var BiosInterface */ private$bios;

/**
* @param BiosInterface $bios * @param OsInterface$os
*/
public function __construct(BiosInterface $bios, OsInterface$os)
{
$this->bios =$bios;
$this->os =$os;
}

public function turnOn()
{
$this->bios->execute();$this->bios->waitForKeyPress();
$this->bios->launch($this->os);
}

public function turnOff()
{
$this->os->halt();$this->bios->powerDown();
}
}

interface OsInterface
{
public function halt();

public function getName(): string;
}

interface BiosInterface
{
public function execute();

public function waitForKeyPress();

public function launch(OsInterface $os); public function powerDown(); } class FacadeTest extends TestCase { public function testComputerOn() { /** @var OsInterface|\PHPUnit_Framework_MockObject_MockObject$os */
$os =$this->createMock('DesignPatterns\Structural\Facade\OsInterface');

$os->method('getName') ->will($this->returnValue('Linux'));

$bios =$this->getMockBuilder('DesignPatterns\Structural\Facade\BiosInterface')
->setMethods(['launch', 'execute', 'waitForKeyPress'])
->getMock();

$bios->expects($this->once())
->method('launch')
->with($os);$facade = new Facade($bios,$os);

// the facade interface is simple
$facade->turnOn(); // but you can also access the underlying components$this->assertEquals('Linux', $os->getName()); } }  3. Composite To treat a group of objects the same way as a single instance of the object. Composite Imagine an audio system consisting of individual songs and also playlists of songs. Yes, playlists consist of songs, but we want both to be treated individually. Both are types of music, both can be played. The Composite design pattern can help here; it allows us to ignore the differences between compositions of objects and individual objects. It allows us to treat both with identical or nearly-identical code. Let's put together a little example; a song is our example of a leaf, with playlists being composites. Music is our abstraction of playlists and songs; therefore, we can call this our component. The client of all this is our index.php file. By not discriminating between leaf-nodes and branches, our code becomes less complex and therefore less error prone. interface RenderableInterface { public function render(): string; } /** * The composite node MUST extend the component contract. This is mandatory for building * a tree of components. */ class Form implements RenderableInterface { /** * @var RenderableInterface[] */ private$elements;

/**
* runs through all elements and calls render() on them, then returns the complete representation
* of the form.
*
* from the outside, one will not see this and the form will act like a single object instance
*
* @return string
*/
public function render(): string
{
$formCode = '<form>'; foreach ($this->elements as $element) {$formCode .= $element->render(); }$formCode .= '</form>';

return $formCode; } /** * @param RenderableInterface$element
*/
public function addElement(RenderableInterface $element) {$this->elements[] = $element; } } class InputElement implements RenderableInterface { public function render(): string { return '<input type="text" />'; } } class TextElement implements RenderableInterface { /** * @var string */ private$text;

public function __construct(string $text) {$this->text = $text; } public function render(): string { return$this->text;
}
}

class CompositeTest extends TestCase
{
public function testRender()
{
$form = new Composite\Form();$form->addElement(new Composite\TextElement('Email:'));
$form->addElement(new Composite\InputElement());$embed = new Composite\Form();
$embed->addElement(new Composite\TextElement('Password:'));$embed->addElement(new Composite\InputElement());
$form->addElement($embed);

// This is just an example, in a real world scenario it is important to remember that web browsers do not
// currently support nested forms

$this->assertEquals( '<form>Email:<input type="text" /><form>Password:<input type="text" /></form></form>',$form->render()
);
}
}

// Concrete Implementation of PayPal Class
class PayPal {

public function __construct() {
}

public function sendPayment($amount) { // Paying via Paypal // echo "Paying via PayPal: ".$amount;
}
}

// Simple Interface for each Adapter we create
public function pay($amount); } class paypalAdapter implements paymentAdapter { private$paypal;

public function __construct(PayPal $paypal) {$this->paypal = $paypal; } public function pay($amount) {
$this->paypal->sendPayment($amount);
}
}

// Client Code
$paypal = new paypalAdapter(new PayPal());$paypal->pay('2629');


getData and setData (not as “pretty”).

5. Decorator

Adding new behaviors to objects dynamically by placing them inside special wrapper objects.

class eMailBody
{
private $header = 'This is email header'; private$footer = 'This is email Footer';
public $body = ''; public function loadBody() {$this->body .= "This is Main Email body.<br />";
}

class christmasEmail extends eMailBody
{
$this->body .= "Added Content for Xmas<br />"; } }$christmasEmail = new christmasEmail();
$christmasEmail->loadBody(); echo$christmasEmail->body;

6. Container

#### 10.1.3 Behavioral

They work to explain how objects interact with each other; how they can send messages between each of the objects and how you can divide the steps of various tasks up among classes. Describe a flowing process.

1. Chain Of Responsibility

Is an object oriented version of the if … else if … else if ……. else … endif idiom

interface PurchaserInterface
{
public function setNextPurchaser(PurchaserInterface $nextPurchaser): void; public function buy($price): void;
}

final class AssociatePurchaser implements PurchaserInterface
{
/**
* @var PurchaserInterface
*/
private $nextPurchaser; public function setNextPurchaser(PurchaserInterface$nextPurchaser): void
{
$this->nextPurchaser =$nextPurchaser;
}

public function buy($price): void { if ($price < 100) {
echo('Associate purchased');
return;
}

if ($this->nextPurchaser) {$this->nextPurchaser->buy($price); return; } echo 'Associate could not buy'; } } final class ManagerPurchaser implements PurchaserInterface { /** * @var PurchaserInterface */ private$nextPurchaser;

public function setNextPurchaser(PurchaserInterface $nextPurchaser): void {$this->nextPurchaser = $nextPurchaser; } public function buy($price): void
{
if ($price < 200) { echo('Manager purchased'); return; } if($this->nextPurchaser) {
$this->nextPurchaser->buy($price);
return;
}

}
}

final class DirectorPurchaser implements PurchaserInterface
{
/**
* @var PurchaserInterface
*/
private $nextPurchaser; public function setNextPurchaser(PurchaserInterface$nextPurchaser): void
{
$this->nextPurchaser =$nextPurchaser;
}

public function buy($price): void { if ($price < 300) {
echo('Director purchased');
return;
}

if($this->nextPurchaser) {$this->nextPurchaser->buy($price); return; } echo 'Director could not buy'; } } class ChainOfResponsibilityTest extends TestCase { public function testOne() {$this->expectOutputString('Director purchased');

$associate = new AssociatePurchaser();$manager = new ManagerPurchaser();
$director = new DirectorPurchaser();$associate->setNextPurchaser($manager);$manager->setNextPurchaser($director);$associate->buy(299);
}
}


2. Observer

The Observer design pattern essentially allows an object (the subject) to maintain a list of observers that are automatically notified when the state of the that object changes. This pattern applies a one-to-many dependency between objects; there is always one subject that updates many observers. This pattern applies a one-to-many dependency between objects; there is always one subject that updates many observers.

class User implements \SplSubject
{
/**
* @var string
*/
private $email; /** * @var \SplObjectStorage */ private$observers;

public function __construct()
{
$this->observers = new \SplObjectStorage(); } public function attach(\SplObserver$observer)
{
$this->observers->attach($observer);
}

public function detach(\SplObserver $observer) {$this->observers->detach($observer); } public function changeEmail(string$email)
{
$this->email =$email;
$this->notify(); } public function notify() { /** @var \SplObserver$observer */
foreach ($this->observers as$observer) {
$observer->update($this);
}
}
}

class UserObserver implements \SplObserver
{
/**
* @var User[]
*/
private $changedUsers = []; /** * It is called by the Subject, usually by SplSubject::notify() * * @param \SplSubject$subject
*/
public function update(\SplSubject $subject) {$this->changedUsers[] = clone $subject; } /** * @return User[] */ public function getChangedUsers(): array { return$this->changedUsers;
}
}

class ObserverTest extends TestCase
{
{
$observer = new UserObserver();$user = new User();
$user->attach($observer);

$user->changeEmail('foo@bar.com');$this->assertCount(1, $observer->getChangedUsers()); } }  3. Strategy Allow us to alter the behavior of an object at runtime. We defined a family of algorithms, bound by one common interface These algorithms are interchangeable; they can be swapped in and out without affecting the client implementation We encapsulated each algorithm within a class class Customer { /** * @var float */ private$bill;

/**
* @var BillingStrategyInterface
*/
private $strategy; public function __construct(BillingStrategyInterface$strategy)
{
$this->strategy =$strategy;
}

public function setStrategy(BillingStrategyInterface $strategy) {$this->strategy = $strategy; } public function addBeer(float$price): void
{
$this->bill +=$this->strategy->getPrice($price); } public function printBill(): void { echo "Total:$this->bill";
}
}

interface BillingStrategyInterface
{
public function getPrice(float $rawPrice): float; } class NormalStrategy implements BillingStrategyInterface { public function getPrice(float$rawPrice): float
{
return $rawPrice; } } class HappyHourStrategy implements BillingStrategyInterface { public function getPrice(float$rawPrice): float
{
return $rawPrice * 0.5; } } class StrategyTest extends TestCase { public function testOne() {$this->expectOutputString('Total: 15');

//Normal billing
$customer = new Customer(new NormalStrategy());$customer->addBeer(10);

//Start Happy Hour
$customer->setStrategy(new HappyHourStrategy());$customer->addBeer(10);

$customer->printBill(); } }  4. Command Command objects encapsulate an action and its parameters. We have an Invoker and a Receiver 5. Iterator Iterators are used to access the elements of an aggregate object sequentially without exposing its underlying representation 6. Null Object Designed to act as a default value of an object 7. Template method: Describes the program skeleton of a program #### 10.1.4 Concurrency ### 10.2 Architectural patterns This is not strictly a design pattern (but the Gang of Four didn't cover Architectural patterns in their book); but it is incredibly relevant for PHP developers due to the web-oriented nature of PHP. Architectural patterns address various different constraints in computer systems through addressing performance limitations, high availability, and also minimization of business risk. Most developers will be familiar with the Model-View-Controller architecture when it comes to web frameworks, more recently other architectures have started to emerge; for example, a microservices architecture works by a set of RESTful APIs that are independent and interconnected. Some people believe microservices move problems from the software development layer to the systems architecture layer. The opposite of microservices often referred to as a monolithic architecture, is where all the code is together in one application. #### 10.2.1 Active Record Problem: Accessing data in a database prevent duplication & centralize access don't have to add any properties to class, just add new column to table objects are tightly coupled to the database schema - hard to test without actually using database breaking SOLID's Single Responsibility Principle - object is responsible for knowing how to create, retrieve, update and delete database entry <?php declare(stricttypes=1); class User { /** • @var int */ private$id;

/**

• @var string

*/ private $name; public function getId(): int { return$this->id; }

public function setId(int $id) {$this->id = $id; } public function getName(): string { return$this->name; }

public function setName(string $name) {$this->name = $name; } }$id = 1; $pdo = new PDO('sqlite:test.db');$sth = $pdo->prepare("SELECT * FROM user WHERE id =:id");$sth->bindParam(":id", $id, PDO::PARAMINT);$sth->execute(); $row =$sth->fetch(PDO::FETCHASSOC); $user = new User();$user->SetId((int) $row['id']);$user->SetName($row['name']); cons: hardcoded columns name, every time we add new column to database we have to manually add it in code in multiple places, hard to maintain, <?php declare(stricttypes=1); class User { private$pdo;

public function _construct(PDO $pdo) {$this->pdo = $pdo; } public function load(int$id) { $sth =$this->pdo->prepare("SELECT * FROM user WHERE id =:id");

$sth->bindParam(":id",$id, PDO::PARAMINT); $sth->execute();$row = $sth->fetch(PDO::FETCHASSOC);$i = 0; foreach($row as$column => $value) {$meta = $sth->getColumnMeta($i);

if($meta['sqlite:decltype'] = 'INTEGER') {$this->$column = (int)$value; }else{ $this->$column = $value; }$i++; } } }

$pdo = new PDO('sqlite:test.db');$user = new User($pdo);$user->load(1);

pros: you don’t have to specify the properties of the object and how they relate to the database. The model is able to determine the properties automatically by looking at the schema of the database.

#### 10.2.2 Data Transfer Object DTO

class IssResponse { /**

• @var float

*/ private $latitude; /** • @var float */ private$longitude;

public function _construct(array $array) {$this->latitude = $array['latitude'];$this->longitude = $array['longitude']; } public function getLatitude(): float { return$this->latitude; }

public function getLongitude(): float { return $this->longitude; } } final class PositionDTO { /** @var float */ private$latitude;

/** @var float */ private $longitude; public function _construct(float$latitude, float $longitude) {$this->latitude = $latitude;$this->longitude = $longitude; } public function getLatitude(): float { return$this->latitude; }

public function getLongitude(): float { return $this->longitude; } } "a class with public variables and no functions" clean code str. 100. But in PHP we still can't declare type of variable, just type-hint parameters of methods. Like setters, so we can do it indirectly. Another great benefit it the standard rule is to not have public properties so we can stay consisten with this one. But more of great adventage of if we can make our DTO object immutable. So create only getters, without setters. Add all in constructor. #### 10.2.3 ADR #### 10.2.4 MVC 1. Controllers 1. are what the user interacts with 2. they receive a request from the user, decide what to do, and send request back 3. it's the only component that interacts with the models 2. Models 1. are where an anpplication's data are stored 2. responsible for storing and retrieving data 3. kno nothing about the user interface 3. Views 1. are what the user sees on the screen 2. they present the data to the user 3. kno nothing about the models 4. Why use MVC? 1. business logic separate from presentation: Separation Of Concerns 2. developer specialisation 1. designers can focus on the front end without worrying about the business logic 2. developers of the models can focus on the business logic or back end without worrying about the look and feel 5. Front controller 1. provide a central entry point for all request. All request are sent through one page 6. Action suffix 1. _call is exectued for a non-existent or non-public method call 2. Stack No it wasn't just a naming convention. It was used to execute some code before or after every controller 'action' method. Like checking is user has logged in. It is based on magic _call function which is executed for a non-existent or non-public method call. $controller = new Posts();
$controller->index(); class Posts { public function __call($name, $args) { //run code before call_user_func_array()[$this, "$nameAction"],$args);
//run code after
}
public function indexAction()
{
}
}


tutorial ended on 31 video

#### 10.2.5 MVVM

Magento was here.

### 10.3 Antipatterns

God objects Essentially, a God object is an object with either too many methods or too many properties; essentially, it's a class that knows too much or does too much. The God object soon becomes tightly coupled to (referenced by) lots of other bits of code in the application. So what's actually wrong with this? Well, in short, when you have one bit of code tied into every single other bit of code, you quickly find a maintenance disaster. If you adjust the logic for a method in a God object for one use case, you might find it having unintended consequences for another element.

The flip side to God objects being an anti-pattern is when developing embedded systems. Embedded systems are used to process data on anything from a calculator to LED signage; they are small chips that are essentially self-contained computers and quite low cost. In this use case, with restricted computational power you can often find that programming elegance and maintainability become peripheral concerns. Slight performance increase and centralization of control can be more important, meaning using God objects can be somewhat sensible. Fortunately, PHP is incredibly seldom used to program embedded systems, so you are incredibly unlikely to find yourself in this particular situation.

Another anti-pattern, called Fear of Adding Classes,

Singleton

<?php class{ Singleton private static $instance; public static function getInstance() { if (null = static::$instance) { static::$instance = new static(); } } return static::$instance; protected function _construct() { } private function _clone() { } private function _wakeup() { } }

So here are the reasons why this should be avoided: They are inherently tightly coupled meaning they are difficult to test, for example using unit tests. They even maintain their state throughout the life cycle of the application. They violate the Single Responsibility Principle by controlling their own creation and life cycle. Fundamentally, it results in you hiding the dependencies of your application in a global instance. You can no longer effectively follow your dependencies around your code as you can't follow where they are injected as function arguments. They make it ineffective to find the dependency chain should you need to analyze it.

Objects should typically be self-contained; they should only know problems about themselves and also should only solve one set of problems, its own problems. Anything that isn't relevant to this aim doesn't belong in that class.

Database as IPC Let me clear this up for you; your database isn't a message queuing system. You don't use it schedule jobs or queue up tasks to be completed. If you need something to do that, use a queuing system. Your database is for data…the clue is in the name; don't shove temporary messages in there. There are many reasons why this is a bad idea. One major issue is the fact that in databases there is no real way to not enforce a policy by which you can guarantee that a double-read will not occur, and that is by utilizing row locks. This in turn, results in processes (either incoming out outgoing) being blocked, which in turn results in processing only being able to be done in a serial fashion. Furthermore, in order to check if there is any work to do you end up essentially counting the rows of data in the database to see if there is work to do; you run this on a continuous basis. MySQL doesn't support push notifications; unlike PostgreSQL it doesn't have the NOTIFY command to pair with a LISTEN channel. Also note that when you merge a job queue with a database table that stores real data, you also invalidate the cache every time you complete a job and update a flag, in turn making MySQL far slower. In short, it results in your database performing worse and can force it to slow critical messages to a standstill. You must be careful not to turn your database into a job queue by having this functionality sneak up on you; instead, use the database exclusively for data, and bear this in mind when extending your database. RabbitMQ provides an open source queuing system with some great PHP SDKs.

Interface Bloat Interfaces shouldn't contain thousands of methods that reference internal operations of the class. They should be lightweight and considered a way of guaranteeing that when something is queried that it is definitely there.

Interfaces should be used sparingly; do you actually need an interface if the class is only ever going to be implemented once and once alone (and realistically, no one is never going to need to tamper with such code?). If so, you might want to consider avoiding an interface in such a situation.

So, let me draw you to one implementation of Interface Bloat. Let's take a look at the Pheanstalk interface class in the Pheanstalk open source library (note I have stripped the comments to make it more readable): <?php namespace Pheanstalk; interface PheanstalkInterface { const DEFAULTPORT = 11300; const DEFAULTDELAY = 0; const DEFAULTPRIORITY = 1024; const DEFAULTTTR = 60; const DEFAULTTUBE = 'default'; public function setConnection(Connection $connection); public function getConnection(); public function bury($job, $priority = self::DEFAULTPRIORITY); public function delete($job); [ 49 ] Anti-Patterns public function ignore($tube); public function kick($max); public function kickJob($job); public function listTubes(); public function listTubesWatched($askServer = false); public function listTubeUsed($askServer = false); public function pauseTube($tube, $delay); public function resumeTube($tube); public function peek($jobId); public function peekReady($tube = null); public function peekDelayed($tube = null); public function peekBuried($tube = null); public function put($data,$priority = self::DEFAULTPRIORITY, $delay = self::DEFAULTDELAY,$ttr = self::DEFAULTTTR); public function putInTube($tube,$data, $priority = self::DEFAULTPRIORITY,$delay = self::DEFAULTDELAY, $ttr = self::DEFAULTTTR); public function release($job, $priority = self::DEFAULTPRIORITY,$delay = self::DEFAULTDELAY); public function reserve($timeout = null); public function reserveFromTube($tube, $timeout = null); public function statsJob($job); public function statsTube($tube); public function stats(); public function touch($job); public function useTube($tube); public function watch($tube); public function watchOnly($tube); } Yuck! Notice how even constants have been put in the implement, the one thing you might actually want to change. Clearly, this is an interface for a class that can only be implemented one way, making the Interface useless. Bloated optimization Often, developers may trip over themselves trying to optimize their code or their design artifacts to a ridiculous extent, often before their code even performs basic functions, or even before any code has been created at all. This can rapidly perform issues in production. In this section, I wish to discuss three anti-patterns specifically relating to this topic: Analysis paralysis Bikeshedding Premature optimization [ 62 ] Anti-Patterns Analysis paralysis In short, this is where a strategy is over-analyzed to the point where progress is slowed down, or even stopped entirely in extreme cases. Not only can such solutions become obsolete rapidly, they can be made in under-educated circumstances, for example, in a meeting where an over-analytic boss tries to dig too deep into detail in advance without allowing their developers to actually do some research. Over-analyzing a problem and seeking a perfect solution upfront just does not work; programmers should seek to refine their solution, not come up with the refined solution up front. Bikeshedding Essentially, this is where analysis paralysis can occur on the basis of some very trivial decisions, for example, the color of a log in page. The only fix that's required is to not waste time on trivial decisions. Avoid design by committee where possible as the majority of people, regardless of how good they think their design skills are, are largely incompetent at design. Premature optimization In this section, so far, I've largely beaten up project managers; no time to beat up developers. Often, developers will seek to optimize their code prematurely without having educated data-led conclusions to drive where and when optimizations should be made. Writing clean and readable code is your first priority; then you can use some great profiling tools to determine where your bottlenecks are. XDebug and New Relic are just some of the tools that are good at this. That said, there are some cases where optimization must be done, particularly on some long computational tasks where it can be mission-critical to reduce something from O(N2) time to O(N). This said, most simple PHP web apps will have no real need to use this consideration. ### 10.4 Links ### 10.5 Is it a pattern? #### 10.5.1 Cache ## 11 Tests ### 11.2 TDD Tests Focus on Require Speed Complexity Setup Needed Unit Tests a class/method the source code very fast low no Integration Tests a component/service part of the running system slow medium yes ## 12 Tools ### 12.2 Symfony Form 'https://webmozart.io/blog/2015/09/09/value-objects-in-symfony-forms/#data-mappers', 'https://stovepipe.systems/post/rethinking-form-development', 'https://blog.martinhujer.cz/symfony-forms-with-request-objects/', 'https://speakerdeck.com/webmozart/symfony-forms-101', 'http://verraes.net/2013/04/decoupling-symfony2-forms-from-entities/' ### 12.3 Code City ### 12.5 Git ## 13 Jokes “There is so much spaghetti I might as well open a restaurant!” ## 14 Metrics ### 14.1 Cyclomatic Complexity Number (CCN) Counts the available decision paths in a source code to determine it's complexity. Each decision path starts with one of the conditional statements from the following list: • ? • && • || • or • and • xor • case • catch • elseif • for • foreach • if • while Cyclomatic Complexity Number is never less than 1, because there’s always at least one code path. • 1-4 has low complexity. • 5-7 is moderate and still easy to understand. • 6-10 has a high complexity. • 10+ is very complex and hard to understand. final class CyclomaticComplexityNumber { // Class Cyclomatic Complexity = 1 } final class CyclomaticComplexityNumber { public function one() { // Function Cyclomatic Complexity = 1 } public function two() { // Function Cyclomatic Complexity = 1 } // Class Cyclomatic Complexity = 1 } final class CyclomaticComplexityNumber { public function one() { if(true){ } // Function Cyclomatic Complexity = 2 } public function two() { // Function Cyclomatic Complexity = 1 } // Class Cyclomatic Complexity = 1 + 1 = 2 } final class CyclomaticComplexityNumber { public function one() { if(true){ } // Function Cyclomatic Complexity = 2 } public function two() { if(true){ } // Function Cyclomatic Complexity = 2 } // Class Cyclomatic Complexity = 1 + 1 + 1 = 3 }  ### 14.2 NPath Complexity function foo($a, $b) { if ($a > 10) {
echo 1;
} else {
echo 2;
}
if ($a >$b) {
echo 3;
} else {
echo 4;
}
}


So here we have function with 4 possible outcomes, since we have 2 statements that have 2 possible outcomes each (2 * 2 = 4). That means that the functions Npath complexity is 4. If we would add another statement with 2 possible outcomes we would get a complexity of 8 since 2 * 2 * 2 = 8.

1. Accurate predictions are an oxymoron in the real world. You can't predict accurately for things that aren't certain, and in almost all cases, developers won't know the systems they are dealing with fully enough. Moreover, they don't know their own personal efficiency from day to day; it just can't be foreseen accurately.
2. A good property of software is the ability to change
3. Anyone can take a chance at improving code, but refactoring brings a discipline

of safely making changes (with tests) and leveraging the knowledge accumulated by the software development community (through refactorings).

• After all, like beauty, complexity is in the eye of the beholder.
• Using new programming languages will bring you new insights and ideas to already known languages. You get a better understanding.
• It's not about clever, crAFTY, PREETY CODE. iT'S ABOUT FAST AND EFFECTIVE COMMUNICATION. It's about communication beetween people.
• Any time someone sees some code that isn't as clear as it should be, they should take the opportunity to fix it right there and then — or at least within a few minutes. This opportunistic refactoring is referred to by Uncle Bob as following the boy-scout rule — always leave the code behind in a better state than you found it.

## 17 Software Architecture

### 17.1 Api

#### 17.1.3 Info

Pluralization of resource names in REST URIs is the widely adopted standard followed by the overwhelming majority of public and private APIs. Beyond being "the standard approach" it also makes sense and is the most simple.

For example:

GET /resources returns a list of resource items POST /resources creates one or many resource items PUT /resources updates one or many resource items PATCH /resources partially updates one or many resource items DELETE resources deletes all resource items And for single resource items: GET /resources:id returns a specific resource item based on :id parameter POST resources:id creates one resource item with specified id (requires validation) PUT resources:id updates a specific resource item PATCH resources:id partially updates a specific resource item DELETE resources:id deletes a specific resource item

1. Sorting

We can also add a sort parameter to sort by field. The sort field in turn contains a list of comma separated columns to sort on; the first in the list is the highest sort priority. In order to negatively sort you prefix a column with a negative sign - GET /tickets?sort=-amount: sort orders by descending order of amount (highest first). GET /tickets?sort=-amount,createdat: sort orders by descending order of amount (highest first). Within those amounts (with orders of equal amounts), older orders are listed first.

2. Searching

We can then search using a simple parameter that applies a search query that can then be routed through a search service (for example, ElasticSearch). Suppose we want to search orders for the phrase refund, we can define a field for search queries: GET /orders?q=refund

3. Limiting fields

Additionally, using a fields parameter we can query for specific fields: GET /orders?fields=amount,createdat,customername,shippingaddress

#### 17.1.4 How to pack data

A JSON object MUST be at the root of every JSON:API request and response containing data. This object defines a document’s “top level”.

A document MUST contain at least one of the following top-level members:

data: the document’s “primary data” errors: an array of error objects meta: a meta object that contains non-standard meta-information.

The members data and errors MUST NOT coexist in the same document.

It's a simple site about refactoring in PHP.

You can contact me at slawomir.grochowski@gmail.com, https://twitter.com/s_grochowski, https://www.facebook.com/SlawomirGrochowski You can support this site: send some BitCoins 1D8xeRkxssTTLESfGZtPVoqVJDq7MJSqNx , send/buy one of the books I would like to read or just say Hello!

Created: 2019-08-18 Sun 11:15

Validate