Real world implementation of
Created by
Jeroen De Dauw
for Wikimedia Deutschland
Licensed CC BY-SA 3.0
IvoryTower.jpg
Real world implementation of
Created by
Jeroen De Dauw
for Wikimedia Deutschland
Licensed CC BY-SA 3.0
IvoryTower.jpg
They did it by making the single worst strategic mistake that any software company can make: [...] rewrite the code from scratch.
Size: complexity Color: maintainability
[...] the classic approach to dealing with software's essential complexity: low-dependency-architecture
Source: CleanCoders.com
Source: CleanCoders.com
class CancelDonationUseCase {
private /* DonationRepository */ $repository;
private /* Mailer */ $mailer;
public function cancelDonation( CancelDonationRequest $r ): CancelDonationResponse {
$this->validateRequest( $r );
$donation = $this->repository->getDonationById( $r->getDonationId() );
$donation->cancel();
$this->repository->storeDonation( $donation );
$this->sendConfirmationEmail( $donation );
return new CancelDonationResponse( /* ... */ );
}
}
$app->post(
'/cancel-donation',
function( Request $httpRequest ) use ( $factory ) {
$requestModel = new CancelDonationRequest(
$httpRequest->request->get( 'donation_id' ),
$httpRequest->request->get( 'update_token' )
);
$useCase = $factory->newCancelDonationUseCase();
$responseModel = $useCase->cancelDonation( $requestModel );
$presenter = $factory->newNukeLaunchingResultPresenter();
return new Response( $presenter->present( $responseModel ) );
}
);
Source: CleanCoders.com
Source: CleanCoders.com
Source: CleanCoders.com
Source: CleanCoders.com
Validation & Use Case boundary
class UseCases\AddDonation\AddDonationRequest {
private $donorType;
private $donorFirstName;
private $donorLastName;
private $donorSalutation;
private $donorTitle;
private $donorCompany;
private $donorStreetAddress;
private $donorPostalCode;
private $donorCity;
private $donorCountryCode;
private $donorEmailAddress;
/* ... */
}
|
class AddDonationUseCase {
public function addDonation( AddDonationRequest $request ) {
$donation = $this->newDonationFromRequest( $request );
$validationResult = $this->validator->validateDonation( $donation );
// ...
}
}
class AddDonationUseCase {
public function addDonation( AddDonationRequest $request ) {
$validationResult = $this->validateRequest( $request );
// ...
$donation = $this->newDonationFromRequest( $request );
// ...
}
}
Bounded Contexts
class Donation {
private /* int|null */ $id
private /* PersonalInfo|null */ $personalInfo
/* ... */
}
class PersonalInfo {
private /* PersonName */ $name
private /* PhysicalAddress */ $address
private /* string */ $emailAddress
}
class MembershipApplication {
private /* int|null */ $id
private /* PersonalInfo|null */ $personalInfo
/* ... */
}
class PersonalInfo {
private /* PersonName */ $name
private /* PhysicalAddress */ $address
private /* string */ $emailAddress
private /* PhoneNumber|null */ $phone
private /* DateTime|null */ $dateOfBirth
private /* int|null */ $membershipNumber
private /* PhysicalAddress|null */ $shippingAddress
private /* string|null */ $shirtSize
class Donor {
private /* PersonName */ $name
private /* PhysicalAddress */ $address
private /* string */ $emailAddress
}
class Applicant {
private /* PersonName */ $name
private /* PhysicalAddress */ $address
private /* EmailAddress */ $email
private /* PhoneNumber */ $phone
private /* DateTime|null */ $dateOfBirth
}
Duplication is far cheaper than the wrong abstraction
-- Sandi Metz
class Donor {
private /* PersonName */ $name
private /* PhysicalAddress */ $address
private /* string */ $emailAddress
}
class Applicant {
private /* PersonName */ $name
private /* PhysicalAddress */ $address
private /* EmailAddress */ $email
private /* PhoneNumber */ $phone
private /* DateTime|null */ $dateOfBirth
}
The Clean Architecture (blog by Robert C Martin)
Architecture, Use Cases, and High Level Design (CleanCoders.com video)
Questions?