Real world implementation of

The Clean Architecture


Created by Jeroen De Dauw for Wikimedia Deutschland
Licensed CC BY-SA 3.0


entropywins.wtf/slides/fun-architecture

IvoryTower.jpg

They did it by making the single worst strategic mistake that any software company can make: [...] rewrite the code from scratch.

-- Joel Spolsky

[...] the classic approach to dealing with software's esential complexity: low-dependency-architecture

-- Leading Lean Software Development

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( /* ... */ );
    }
}
					

Source: CleanCoders.com


$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 ) );
    }
);
					

Lessons learned                        

Validation & Use Case boundary                        










class Domain\Donation {
    private /* int|null */            $id
    private /* Donor|null */          $donor
    private /* DonationPayment */     $payment
    /* ... */
}					

class Domain\Donor {
    private /* PersonName */          $name
    private /* PhysicalAddress */     $address
    private /* string */              $emailAddress
}
					

class UseCases\AddDonation\AddDonationRequest {
    private /* Donor|null */          $donor
    /* ... */
}
					

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 );

        // ...
    }

}
					

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 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

This presentation

URL: entropywins.wtf/slides/fun-architecture

The Fundraising Frontend application source

The Fundraising Frontend application

Recommended material

The Clean Architecture (blog by Robert C Martin)

Architecture, Use Cases, and High Level Design (Clean Coders video)

Questions?

Cattribution