TDD, DDD & Teamwork v2

B84af63b07f297643ab1fd943c9ac59c?s=47 pelshoff
October 09, 2019

TDD, DDD & Teamwork v2

#wczg

B84af63b07f297643ab1fd943c9ac59c?s=128

pelshoff

October 09, 2019
Tweet

Transcript

  1. 1.
  2. 6.

    final class PresentationTest extends TestCase { /** * @test */

    public function presentationsShouldHaveTitles(): void { $this->expectException(InvalidPresentation::class); new Presentation('', '', ''); } }
  3. 8.

    final class PresentationTest extends TestCase { /** * @test */

    public function presentationsShouldAllowNewSubtitles(): void { $actual = new Presentation('With', 'a', 'title'); $expectation = new Presentation('With', 'another', 'title'); $actual->changeSubtitleTo('another'); $this->assertEquals($expectation, $actual); } }
  4. 15.

    “Test-Driven Development (TDD) is a technique for building software that

    guides software development by writing tests.” - Martin Fowler
  5. 22.
  6. 27.
  7. 31.

    final class Name { private $lastName; private $firstName; private $insertion;

    public function __construct(string $lastName, string $firstName, string $insertion) { $this->lastName = $lastName; $this->firstName = $firstName; $this->insertion = $insertion; $this->nameMustHaveLastName(); } private function nameMustHaveLastName(): void { if (!$this->lastName) { throw InvalidName::becauseLastNameIsMissing(); } } public function getLastName(): string { /**/ } public function getFirstName(): string { /**/ } public function getInsertion(): string { /**/ } }
  8. 32.

    final class EmailAddress { private $emailAddress; public function __construct(string $emailAddress)

    { $this->emailAddress = $emailAddress; $this->emailAddressMustBeAnActualEmailAddress(); } private function emailAddressMustBeAnActualEmailAddress(): void { if (!filter_var($this->emailAddress, FILTER_VALIDATE_EMAIL)) { throw InvalidEmailAddress::becauseThisIsNotAnEmailAddress(); } } public function asString(): string { return $this->emailAddress; } }
  9. 33.

    Value objects • Express a value • Define allowed values

    • Are immutable • Are easy to test
  10. 34.
  11. 35.

    final class Attendee { private $id; private $name; private $emailAddress;

    public function __construct(Uuid $id, Name $name, EmailAddress $emailAddress) { $this->id = $id; $this->name = $name; $this->emailAddress = $emailAddress; } public function getId(): Uuid { /**/ } public function getName(): Name { /**/ } public function setName(Name $name): Attendee { /**/ } public function getEmailAddress(): EmailAddress { /**/ } public function setEmailAddress(EmailAddress $emailAddress): Attendee { $this->emailAddress = $emailAddress; return $this; } }
  12. 36.

    Entities • Have identity • Are more than their attributes

    • Evolve over time • Are slightly harder to test
  13. 37.
  14. 38.

    final class Registration { private $repository; public function __construct(AttendeeRepository $repository)

    { $this->repository = $repository; } public function registerNew(Attendee $attendee): void { $this->emailAddressMustBeUnique($attendee->getEmailAddress()); $this->repository->add($attendee); } private function emailAddressMustBeUnique(EmailAddress $emailAddress): void { try { $this->repository->findByEmailAddress($emailAddress); } catch (AttendeeNotFound $e) { return; } throw RegistrationFailed::becauseEmailAddressIsNotUnique(); } }
  15. 39.

    Services • Have no identity or attributes (Are not a

    “thing”) • Tackle cross-concern operations • Are harder to test