Slide 1

Slide 1 text

Effortless Software Development PHP CONFERENCE BRAZIL | DEC 05, 2020 @afilina

Slide 2

Slide 2 text

Waiting for user tests Merge conflicts Adding missing requirements Waiting on someone else Someone you never heard of
 disagrees with requirements Redesign Writing code Figuring out requirements 50-page document Approving the document 20 levels of inheritance 800-line methods 6 levels of nested IFs What does $array2 contain? How to unit-test it? Is this null right now?

Slide 3

Slide 3 text

Anna Filina ‣ Coding since 1997. ‣ PHP since 2003. ‣ Legacy archaeology. ‣ Test automation. ‣ Talks and workshops. ‣ YouTube videos. ‣ Filina Consulting.

Slide 4

Slide 4 text

1/3
 Better Specifications

Slide 5

Slide 5 text

Getting an answer Dev Requirements User testing 50-page
 document

Slide 6

Slide 6 text

Question 2 Missing use cases / redesign More testing er User testing

Slide 7

Slide 7 text

Solution ‣ Get a product owner. ‣ With direct & quick access. ‣ Should not have other roles in the org. ‣ Should not delegate questions. ‣ Communicate requirements using acceptance tests.

Slide 8

Slide 8 text

Scenario: User can subscribe with a credit card Given I selected a membership option When I enter valid credit card details Then I should see a payment receipt

Slide 9

Slide 9 text

Scenario: Discounts are matched based on current date Given A 5% discount "FIVE" active on 2019-01-01 through 2019-01-31 And A 10% discount "TEN" active on 2019-02-01 through 2019-02-28 And The current date is 2019-01-15 When I check for discounts Then The "FIVE" discount should be found

Slide 10

Slide 10 text

Requirements
 Collection of use cases
 that need to be accounted for.

Slide 11

Slide 11 text

I select a membership option I enter valid credit card details I should see a payment receipt Requirements Use cases (scenarios)

Slide 12

Slide 12 text

Scenario Dev Requirements User testing Use cases (scenarios)

Slide 13

Slide 13 text

2/3 Iterative Design

Slide 14

Slide 14 text

Design Dev Approval Mistake in 
 design

Slide 15

Slide 15 text

The map is not the territory.
 — Alfred Korzybski

Slide 16

Slide 16 text

Solution ‣ Sequence or activity diagram. ‣ Minimal code to validate design.

Slide 17

Slide 17 text

API UI User Select membership Order Create order {product_code} Payment screen Enter payment details Receipt {confirmation_num} Finalize order {card} Receipt

Slide 18

Slide 18 text

3/3 More Cooks
 in the Kitchen

Slide 19

Slide 19 text

Solution ‣ Mob programming: validate the design. ‣ Split the work: implementation + tests.

Slide 20

Slide 20 text

API UI User Select membership Order Create order {product_code} Payment screen Enter payment details Receipt {confirmation_num} Finalize order {card} Receipt

Slide 21

Slide 21 text

final class CreateOrderHandler { public function handle(Request $request) : Response { $productCode = new ProductCode( $request->getAttribute('product_code') ); $product = $this->products->getByCode($productCode); $order = $this->orders->create($product); return new JsonResponse([ 'order' => $order->toArray(), ]); } }

Slide 22

Slide 22 text

final class CreateOrderHandler { public function handle(Request $request) : Response { $productCode = new ProductCode( $request->getAttribute('product_code') ); $product = $this->products->getByCode($productCode); $order = $this->orders->create($product); return new JsonResponse([ 'order' => $order->toArray(), ]); } }

Slide 23

Slide 23 text

public function __construct( ProductStorage $products, OrderStorage $orders )

Slide 24

Slide 24 text

interface ProductStorage { public function getByCode(ProductCode $code) : Product; } interface OrderStorage { public function create(Product $product) : Order; }

Slide 25

Slide 25 text

interface ProductStorage { public function getByCode(ProductCode $code) : Product; } interface OrderStorage { public function create(Product $product) : Order }

Slide 26

Slide 26 text

final class ProductCode { private $code; public function __construct(string $code) { Assert::that($code) ->notBlank() ->maxLength(15); $this->code = $code; } public function getCode() : string { return $this->code; } }

Slide 27

Slide 27 text

Mob Programming ‣ Handler: 13 lines. ‣ Interfaces: 8 lines. ‣ Value objects: 46 lines. ‣ = 67 ‣ Shared vision.

Slide 28

Slide 28 text

Split the Work ‣ Test handler. ‣ Implement interfaces + tests. ‣ Implement validation of value object + tests. ‣ Implement steps of acceptance tests.

Slide 29

Slide 29 text

interface OrderStorage { public function create(Product $product, Country $country) : Order }

Slide 30

Slide 30 text

Acceptance Tests ‣ Both for backend and frontend. ‣ Just for the backend.

Slide 31

Slide 31 text

@wip Scenario: User can subscribe with a credit card Given I selected a membership option When I enter valid credit card details Then I should see a payment receipt Call 1 Call 2 Assertion

Slide 32

Slide 32 text

Mission Accomplished

Slide 33

Slide 33 text

Lessons Learned ‣ Code is living documentation. ‣ Don't try to figure everything out upfront (unknowns). ‣ Mistakes are normal (fail fast). ‣ Work together more often.

Slide 34

Slide 34 text

Further Topics ‣ Domain-driven design. ‣ Test-driven development. ‣ Acceptance tests. ‣ SOLID principles. ‣ Clean code. ‣ Extreme programming. ‣ Scrum.

Slide 35

Slide 35 text

@afilina