7. It's a fancy term for measuring the complexity of a method.
Decision points in a method increase complexity.
(e.g. if, else, foreach, etc.)
Plugins will calculate it for you.
(PHP Mess Detector, JSHint, Grunt!)
10. N-path complexity
The number of acyclic execution paths through a function; an
objective measure of complexity related to the ease with which
software can be comprehensively tested
12. It's a lot like cyclomatic complexity.
It measures how many straight lines you can draw through a
method.
A method with a single IFstatement has an N-path of 2.
A method with 2 IFstatements has an N-path of 4.
3 IFstatements would make the N-path 8.
13. Another way to look at it
The value of a method's N-path complexity is equal to the number
of unit tests needed to ensure that you have 100% code coverage.
A "quick estimate" for N-Path:
2^(cyclomaticComplexity - 1)
15. Things to avoid
Violating the Single Responsibility Principle
A Controller method with logic to perform CRUD operations.
A Product Model with logic for formatting currency.
Seperation of Concerns
Too complex: A single method that executes four business
rules to perform a task.
Better: Four methods that each execute a single business rule.
16. Plan Ahead
It's common to be handed a user story that is simple to describe but
complex to implement.
Take time to break the logic into the smallest possible units before
writing code.
24. in ruby everything is an object
and all objects are open
Also, monkey patching code at runtime is a typical practice in the Ruby world.
blowling.score.should eq(0)
25. an early PHPSpec syntax example
Trying to emulate ruby in PHP looks ugly
$this->spec($bowling->getScore())->shouldEqual(0);
28. How PHPUnit handles the Yellow step
PHPUnit 3.7.14 by Sebastian Bergmann.
PHP Fatal error: Class 'Markdown' not found in /Users/stephenyoung/Documents/projects/Lab/phpuni
t/tests/MarkdownTest.php on line 8
Fatal error: Class 'Markdown' not found in /Users/stephenyoung/Documents/projects/Lab/phpunit/te
sts/MarkdownTest.php on line 8
29. How PHPSpec handles the Yellow step
it does this for missing methods too.
> specCustomer
✘ it converts plain text to html paragraphs
Class Markdown does not exist.
Do you want me to create it for you? [Y/n]
30. Mocking
It suffices to say that mocking is painful in PHPUnit.
PHPSpec has a very easy-to-use Mocking library.
Too much to go into here.
36. Alan Kay on Messaging
"The key in making great and growable systems is
much more to design how its modules
communicate rather than what their internal
properties and behaviors should be."
42. Big Design Up Front
It's hard to change later.
We need to think about things before developing.
We need to make sure we don't miss anything.
This is just the way we do it.
76. Single Responsibility Principle
class Email {
private $email;
public function __construct($email) {
if( /* ugly regex here */) {
throw new InvalidArgumentException();
}
$this->email = $email;
}
public function __toString() {
return $this->email;
}
}
81. Improve it with object for
consistency
$order = new Order;
$order->setCustomer($customer);
$order->setProducts($products);
$order->setStatus(
new PaymentStatus(PaymentStatus::UNPAID)
);
$order->setPaidAmount(500);
$order->setPaidCurrency(‘EUR’);
$order->setStatus(
new PaymentStatus(PaymentStatus::PAID)
);
82. Improve it with more
consistency
$order = new Order;
$order->setCustomer($customer);
$order->setProducts($products);
$order->setStatus(
new PaymentStatus(PaymentStatus::UNPAID)
);
$order->setPaidMonetary(
new Money(500, new Currency(‘EUR’))
);
$order->setStatus(
new PaymentStatus(PaymentStatus::PAID)
);
83. Even more
$order = new Order($customer, $products);
// set PaymentStatus in Order::__construct()
$order->setPaidMonetary(
new Money(500, new Currency(‘EUR’))
);
$order->setStatus(
new PaymentStatus(PaymentStatus::PAID)
);
84. Getting ridiculous now
$order = new Order($customer, $products);
$order->pay(
new Money(500, new Currency(‘EUR’))
);
// set PaymentStatus in Order#pay()
85. Encapsulation through
specification
"I want to give a discount to a customer that has at least 3 orders."
interface CustomerSpecification {
/** @return bool */
public function isSatisfiedBy(Customer $customer);
}
86. class CustomerIsPremium implements CustomerSpecification {
private $orderRepository;
public function __construct(
OrderRepository $orderRepository
) {...}
/** @return bool */
public function isSatisfiedBy(Customer $customer) {
$count = $this->orderRepository->countFor($customer);
return $count >= 3;
}
}
$customerIsPremium = new CustomerIsPremium($orderRepository)
if($customerIsPremium->isSatisfiedBy($customer)) {
// send special offer
}
87. Credits
PHP By the numbers - Anthony Ferrara
Emergent Design with phpspec - Marcello Duarte
Unbreakable Domain Models - Mathias Verraes
Let's have a look at PHP 5.5 - Julien Pauli