SlideShare a Scribd company logo
1 of 71
Download to read offline
„KTO TO PISAŁ?!… A, TO JA.”
czyli sposoby, żeby znienawidzić
siebie z przeszłości
🔥🔥🔥
„KTO TO PISAŁ?! A, TO JA…”
czyli jak wiedźmin i angielski teolog
„KTO TO PISAŁ?! A, TO JA…”
czyli jak wiedźmin i angielski teolog
mogą pomóc Ci pisać lepszy kod
„KTO TO PISAŁ?! A, TO JA…”
„KTO TO PISAŁ?! A, TO JA…”
czyli jak wiedźmin i angielski teolog
mogą pomóc Ci pisać lepszy kod
albo przynajmniej zrozumieć, czemu nie
jest tak dobry, jak byś chciał(a)
✅
❌
S P Ó J N O Ś Ć
😕
😕
😠
😕
😠
😕
😠
🤬🤬🤬🤬
final class ProductVariantPriceCalculatorSpec extends ObjectBehavior
{
function it_implements_product_variant_price_calculator_interface(): void
{
$this->shouldImplement(ProductVariantPricesCalculatorInterface::class);
}
function it_gets_price_for_product_variant_in_given_channel(
ChannelInterface $channel,
ChannelPricingInterface $channelPricing,
ProductVariantInterface $productVariant,
): void {
$productVariant->getChannelPricingForChannel($channel)->willReturn($channelPricing);
$channelPricing->getPrice()->willReturn(1000);
$this->calculate($productVariant, ['channel' => $channel])->shouldReturn(1000);
}
}
final class ProductVariantPriceCalculatorSpec extends ObjectBehavior
{
function it_implements_product_variant_price_calculator_interface(): void
{
$this->shouldImplement(ProductVariantPricesCalculatorInterface::class);
}
function it_gets_price_for_product_variant_in_given_channel(
ChannelInterface $channel,
ChannelPricingInterface $channelPricing,
ProductVariantInterface $productVariant,
): void {
$productVariant->getChannelPricingForChannel($channel)->willReturn($channelPricing);
$channelPricing->getPrice()->willReturn(1000);
$this->calculate($productVariant, ['channel' => $channel])->shouldReturn(1000);
}
}
😡
1 . P O P R A W N O Ś Ć
2 . S P Ó J N O Ś Ć
S T A N D A R D Y
P U Ł A P K A
S P Ó J N O Ś C I
D O K U M E N T A C J A
T E S T Y
A D R
K O N T E K S T
P Ł O T C H E S T E R T O N A
final class GrossPriceCalculatorTest extends TestCase
{
/** @dataProvider provideGrossCalculationData */
public function testItCountsGrossPriceForGivenNetPriceAndTaxRate(
int $netPrice,
float $taxRate,
int $expectedGrossPrice
): void {
self::assertSame(
$expectedGrossPrice,
GrossPriceCalculator::calculateGrossPrice($netPrice, $taxRate)
);
}
private function provideGrossCalculationData(): iterable
{
yield 'net price 500, tax rate 7.0%' => [
'netPrice' => 500,
'taxRate' => 0.07,
'expectedGrossPrice' => 535,
];
yield 'net price 750, tax rate 7.7%' => [
'netPrice' => 750,
'taxRate' => 0.077,
'expectedGrossPrice' => 808,
];
yield 'net price 1500, tax rate 8.5%' => [
'netPrice' => 1500,
'taxRate' => 0.085,
'expectedGrossPrice' => 1628,
];
}
}
final class GrossPriceCalculatorTest extends TestCase
{
/** @dataProvider provideGrossCalculationData */
public function testItCountsGrossPriceForGivenNetPriceAndTaxRate(
int $netPrice,
float $taxRate,
int $expectedGrossPrice
): void {
self::assertSame(
$expectedGrossPrice,
GrossPriceCalculator::calculateGrossPrice($netPrice, $taxRate)
);
}
private function provideGrossCalculationData(): iterable
{
yield 'net price 500, tax rate 7.0%' => [
'netPrice' => 500,
'taxRate' => 0.07,
'expectedGrossPrice' => 535,
];
yield 'net price 750, tax rate 7.7%' => [
'netPrice' => 750,
'taxRate' => 0.077,
'expectedGrossPrice' => 808,
];
yield 'net price 1500, tax rate 8.5%' => [
'netPrice' => 1500,
'taxRate' => 0.085,
'expectedGrossPrice' => 1628,
];
}
}
❗
❗
final class GrossPriceCalculatorTest extends TestCase
{
/** @dataProvider provideGrossCalculationData */
public function testItCountsGrossPriceForGivenNetPriceAndTaxRate(
int $netPrice,
float $taxRate,
int $expectedGrossPrice
): void {
self::assertSame(
$expectedGrossPrice,
GrossPriceCalculator::calculateGrossPrice($netPrice, $taxRate)
);
}
private function provideGrossCalculationData(): iterable
{
yield 'net price 500, tax rate 7.0%' => [
'netPrice' => 500,
'taxRate' => 0.07,
'expectedGrossPrice' => 535,
];
yield 'net price 750, tax rate 7.7%' => [
'netPrice' => 750,
'taxRate' => 0.077,
'expectedGrossPrice' => 810,
];
yield 'net price 1500, tax rate 8.5%' => [
'netPrice' => 1500,
'taxRate' => 0.085,
'expectedGrossPrice' => 1630,
];
}
}
✅
✅
🤨
😡
K O N T E K S T
W I E D Z Y I
C Z A S U
D Ł U G
T E C H N I C Z N Y
https://twitter.com/vincentdnl/status/1647630936060600322
final class OrderTaxesProcessor implements OrderProcessorInterface
{
public function __construct(
private ZoneProviderInterface $defaultTaxZoneProvider,
private ZoneMatcherInterface $zoneMatcher,
private PrioritizedServiceRegistryInterface $strategyRegistry,
private ?TaxationAddressResolverInterface $taxationAddressResolver = null,
) {
}
public function process(BaseOrderInterface $order): void
{
if (OrderInterface::STATE_CART !== $order->getState()) {
return;
}
$this->clearTaxes($order);
if ($order->isEmpty()) {
return;
}
$zone = $this->getTaxZone($order);
if (null === $zone) {
return;
}
/** @var TaxCalculationStrategyInterface $strategy */
foreach ($this->strategyRegistry->all() as $strategy) {
if ($strategy->supports($order, $zone)) {
$strategy->applyTaxes($order, $zone);
public function process(BaseOrderInterface $order): void
{
if (OrderInterface::STATE_CART !== $order->getState()) {
return;
}
$this->clearTaxes($order);
if ($order->isEmpty()) {
return;
}
😡
public function process(BaseOrderInterface $order): void
{
if ($order->canBeProcessed()) {
return;
}
$this->clearTaxes($order);
if ($order->isEmpty()) {
return;
}
if ($order->canBeProcessed()) {
return;
}
2 0 2 0
2 0 2 0
/api/v2 header /new-api
😂
2 0 2 0
/api/v2 header
/new-api
🤡
P O S T Ę P J E S T
J A K S T A D O
Ś W I Ń
R E F A C T O R I N G
Z A S A D A S K A U T A
16608
38469
Z A S A D Y
S O L I D
K I S S
D R Y
Y A G N I
C U P I D
S R P
public function process(BaseOrderInterface $order): void
{
/** @var OrderInterface $order */
Assert::isInstanceOf($order, OrderInterface::class);
if (OrderInterface::STATE_CART !== $order->getState()) {
return;
}
$this->clearTaxes($order);
if ($order->isEmpty()) {
return;
}
$zone = $this->getTaxZone($order);
if (null === $zone) {
return;
}
/** @var TaxCalculationStrategyInterface $strategy */
foreach ($this->strategyRegistry->all() as $strategy) {
if ($strategy->supports($order, $zone)) {
$strategy->applyTaxes($order, $zone);
return;
}
}
throw new UnsupportedTaxCalculationStrategyException();
}
private function getTaxZone(OrderInterface $order): ?ZoneInterface
{
$taxationAddress = $order->getBillingAddress();
$zone = $this->zoneMatcher->match($taxationAddress, Scope::TAX);
return $zone ?: $this->defaultTaxZoneProvider->getZone($order);
}
private function clearTaxes(OrderInterface $order): void
{
$order->removeAdjustments(AdjustmentInterface::TAX_ADJUSTMENT);
foreach ($order->getItems() as $item) {
$item->removeAdjustmentsRecursively(AdjustmentInterface::TAX_ADJUSTMENT);
}
/** @var ShipmentInterface $shipment */
foreach ($order->getShipments() as $shipment) {
$shipment->removeAdjustments(AdjustmentInterface::TAX_ADJUSTMENT);
}
}
public function process(BaseOrderInterface $order): void
{
/** @var OrderInterface $order */
Assert::isInstanceOf($order, OrderInterface::class);
if (OrderInterface::STATE_CART !== $order->getState()) {
return;
}
$this->clearTaxes($order);
if ($order->isEmpty()) {
return;
}
$zone = $this->getTaxZone($order);
if (null === $zone) {
return;
}
/** @var TaxCalculationStrategyInterface $strategy */
foreach ($this->strategyRegistry->all() as $strategy) {
if ($strategy->supports($order, $zone)) {
$strategy->applyTaxes($order, $zone);
return;
}
}
throw new UnsupportedTaxCalculationStrategyException();
}
private function getTaxZone(OrderInterface $order): ?ZoneInterface
{
$taxationAddress = $order->getBillingAddress();
$zone = $this->zoneMatcher->match($taxationAddress, Scope::TAX);
return $zone ?: $this->defaultTaxZoneProvider->getZone($order);
}
private function clearTaxes(OrderInterface $order): void
{
$order->removeAdjustments(AdjustmentInterface::TAX_ADJUSTMENT);
foreach ($order->getItems() as $item) {
$item->removeAdjustmentsRecursively(AdjustmentInterface::TAX_ADJUSTMENT);
}
/** @var ShipmentInterface $shipment */
foreach ($order->getShipments() as $shipment) {
$shipment->removeAdjustments(AdjustmentInterface::TAX_ADJUSTMENT);
}
}
public function process(BaseOrderInterface $order): void
{
/** @var OrderInterface $order */
Assert::isInstanceOf($order, OrderInterface::class);
if (OrderInterface::STATE_CART !== $order->getState()) {
return;
}
$this->clearTaxes($order);
if ($order->isEmpty()) {
return;
}
$zone = $this->getTaxZone($order);
if (null === $zone) {
return;
}
/** @var TaxCalculationStrategyInterface $strategy */
foreach ($this->strategyRegistry->all() as $strategy) {
if ($strategy->supports($order, $zone)) {
$strategy->applyTaxes($order, $zone);
return;
}
}
throw new UnsupportedTaxCalculationStrategyException();
}
private function getTaxZone(OrderInterface $order): ?ZoneInterface
{
$taxationAddress = $order->getBillingAddress();
$zone = $this->zoneMatcher->match($taxationAddress, Scope::TAX);
return $zone ?: $this->defaultTaxZoneProvider->getZone($order);
}
private function clearTaxes(OrderInterface $order): void
{
$order->removeAdjustments(AdjustmentInterface::TAX_ADJUSTMENT);
foreach ($order->getItems() as $item) {
$item->removeAdjustmentsRecursively(AdjustmentInterface::TAX_ADJUSTMENT);
}
/** @var ShipmentInterface $shipment */
foreach ($order->getShipments() as $shipment) {
$shipment->removeAdjustments(AdjustmentInterface::TAX_ADJUSTMENT);
}
}
I M P L E M E N T A C J A
Z P R Z Y P A D K U
Excellence lives inside pragmatic boundaries
D D D
D I S C O M F O R T
D R I V E N
D E V E L O P M E N T
@mpzalewski Zales0123
https://mpzalewski.com
Mateusz Zalewski
@mpzalewski Zales0123
https://mpzalewski.com
Mateusz Zalewski
@CommerceWeavers @Sylius
@mpzalewski Zales0123
https://mpzalewski.com
Mateusz Zalewski
THANK YOU
@CommerceWeavers
@mpzalewski Zales0123
https://mpzalewski.com
Mateusz Zalewski
WE’RE
HIRING!

More Related Content

Similar to [PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić siebie z przeszłości

C A S Sample Php
C A S Sample PhpC A S Sample Php
C A S Sample Php
JH Lee
 
R57shell
R57shellR57shell
R57shell
ady36
 
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Masahiro Nagano
 

Similar to [PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić siebie z przeszłości (20)

Intermediate PHP
Intermediate PHPIntermediate PHP
Intermediate PHP
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
C A S Sample Php
C A S Sample PhpC A S Sample Php
C A S Sample Php
 
Php Enums
Php EnumsPhp Enums
Php Enums
 
Database api
Database apiDatabase api
Database api
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
R57shell
R57shellR57shell
R57shell
 
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
 
PHP Enums - PHPCon Japan 2021
PHP Enums - PHPCon Japan 2021PHP Enums - PHPCon Japan 2021
PHP Enums - PHPCon Japan 2021
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and Hobgoblins
 
PHP 8.1: Enums
PHP 8.1: EnumsPHP 8.1: Enums
PHP 8.1: Enums
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
Refactoring using Codeception
Refactoring using CodeceptionRefactoring using Codeception
Refactoring using Codeception
 
Things I Believe Now That I'm Old
Things I Believe Now That I'm OldThings I Believe Now That I'm Old
Things I Believe Now That I'm Old
 
The Art of Transduction
The Art of TransductionThe Art of Transduction
The Art of Transduction
 
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needDutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
Gta v savegame
Gta v savegameGta v savegame
Gta v savegame
 

More from Mateusz Zalewski

More from Mateusz Zalewski (9)

[PHPCon 2023] Blaski i cienie BDD
[PHPCon 2023] Blaski i cienie BDD[PHPCon 2023] Blaski i cienie BDD
[PHPCon 2023] Blaski i cienie BDD
 
[ForumPHP 2023] Lights and shadows of BDD in Sylius (and probably other compa...
[ForumPHP 2023] Lights and shadows of BDD in Sylius (and probably other compa...[ForumPHP 2023] Lights and shadows of BDD in Sylius (and probably other compa...
[ForumPHP 2023] Lights and shadows of BDD in Sylius (and probably other compa...
 
[PHPers Summit 2023] Business logic testing
[PHPers Summit 2023] Business logic testing[PHPers Summit 2023] Business logic testing
[PHPers Summit 2023] Business logic testing
 
Confoo 2023 - BDD revolution, or how we came back from hell
Confoo 2023 - BDD revolution, or how we came back from hellConfoo 2023 - BDD revolution, or how we came back from hell
Confoo 2023 - BDD revolution, or how we came back from hell
 
Confoo 2023 - Business logic testing with Behat, Twig and Api Platform
Confoo 2023 - Business logic testing with Behat, Twig and Api PlatformConfoo 2023 - Business logic testing with Behat, Twig and Api Platform
Confoo 2023 - Business logic testing with Behat, Twig and Api Platform
 
What is Sylius and why should you know it?
What is Sylius and why should you know it?What is Sylius and why should you know it?
What is Sylius and why should you know it?
 
BDD Revolution - or how we came back from hell
BDD Revolution - or how we came back from hellBDD Revolution - or how we came back from hell
BDD Revolution - or how we came back from hell
 
BDD revolution - or how we came back from hell
BDD revolution - or how we came back from hellBDD revolution - or how we came back from hell
BDD revolution - or how we came back from hell
 
Why you should be doing BDD
Why you should be doing BDDWhy you should be doing BDD
Why you should be doing BDD
 

Recently uploaded

JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)
Max Lee
 

Recently uploaded (20)

how-to-download-files-safely-from-the-internet.pdf
how-to-download-files-safely-from-the-internet.pdfhow-to-download-files-safely-from-the-internet.pdf
how-to-download-files-safely-from-the-internet.pdf
 
A Comprehensive Appium Guide for Hybrid App Automation Testing.pdf
A Comprehensive Appium Guide for Hybrid App Automation Testing.pdfA Comprehensive Appium Guide for Hybrid App Automation Testing.pdf
A Comprehensive Appium Guide for Hybrid App Automation Testing.pdf
 
JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)
 
CompTIA Security+ (Study Notes) for cs.pdf
CompTIA Security+ (Study Notes) for cs.pdfCompTIA Security+ (Study Notes) for cs.pdf
CompTIA Security+ (Study Notes) for cs.pdf
 
10 Essential Software Testing Tools You Need to Know About.pdf
10 Essential Software Testing Tools You Need to Know About.pdf10 Essential Software Testing Tools You Need to Know About.pdf
10 Essential Software Testing Tools You Need to Know About.pdf
 
GraphSummit Stockholm - Neo4j - Knowledge Graphs and Product Updates
GraphSummit Stockholm - Neo4j - Knowledge Graphs and Product UpdatesGraphSummit Stockholm - Neo4j - Knowledge Graphs and Product Updates
GraphSummit Stockholm - Neo4j - Knowledge Graphs and Product Updates
 
Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...
Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...
Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...
 
The Impact of PLM Software on Fashion Production
The Impact of PLM Software on Fashion ProductionThe Impact of PLM Software on Fashion Production
The Impact of PLM Software on Fashion Production
 
IT Software Development Resume, Vaibhav jha 2024
IT Software Development Resume, Vaibhav jha 2024IT Software Development Resume, Vaibhav jha 2024
IT Software Development Resume, Vaibhav jha 2024
 
COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...
COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...
COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...
 
How to install and activate eGrabber JobGrabber
How to install and activate eGrabber JobGrabberHow to install and activate eGrabber JobGrabber
How to install and activate eGrabber JobGrabber
 
KLARNA - Language Models and Knowledge Graphs: A Systems Approach
KLARNA -  Language Models and Knowledge Graphs: A Systems ApproachKLARNA -  Language Models and Knowledge Graphs: A Systems Approach
KLARNA - Language Models and Knowledge Graphs: A Systems Approach
 
What need to be mastered as AI-Powered Java Developers
What need to be mastered as AI-Powered Java DevelopersWhat need to be mastered as AI-Powered Java Developers
What need to be mastered as AI-Powered Java Developers
 
AI Hackathon.pptx
AI                        Hackathon.pptxAI                        Hackathon.pptx
AI Hackathon.pptx
 
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
 
INGKA DIGITAL: Linked Metadata by Design
INGKA DIGITAL: Linked Metadata by DesignINGKA DIGITAL: Linked Metadata by Design
INGKA DIGITAL: Linked Metadata by Design
 
OpenChain @ LF Japan Executive Briefing - May 2024
OpenChain @ LF Japan Executive Briefing - May 2024OpenChain @ LF Japan Executive Briefing - May 2024
OpenChain @ LF Japan Executive Briefing - May 2024
 
SQL Injection Introduction and Prevention
SQL Injection Introduction and PreventionSQL Injection Introduction and Prevention
SQL Injection Introduction and Prevention
 
Crafting the Perfect Measurement Sheet with PLM Integration
Crafting the Perfect Measurement Sheet with PLM IntegrationCrafting the Perfect Measurement Sheet with PLM Integration
Crafting the Perfect Measurement Sheet with PLM Integration
 
APVP,apvp apvp High quality supplier safe spot transport, 98% purity
APVP,apvp apvp High quality supplier safe spot transport, 98% purityAPVP,apvp apvp High quality supplier safe spot transport, 98% purity
APVP,apvp apvp High quality supplier safe spot transport, 98% purity
 

[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić siebie z przeszłości

  • 1. „KTO TO PISAŁ?!… A, TO JA.” czyli sposoby, żeby znienawidzić siebie z przeszłości
  • 3. „KTO TO PISAŁ?! A, TO JA…”
  • 4. czyli jak wiedźmin i angielski teolog „KTO TO PISAŁ?! A, TO JA…”
  • 5. czyli jak wiedźmin i angielski teolog mogą pomóc Ci pisać lepszy kod „KTO TO PISAŁ?! A, TO JA…”
  • 6. „KTO TO PISAŁ?! A, TO JA…” czyli jak wiedźmin i angielski teolog mogą pomóc Ci pisać lepszy kod albo przynajmniej zrozumieć, czemu nie jest tak dobry, jak byś chciał(a)
  • 7.
  • 9. S P Ó J N O Ś Ć
  • 10.
  • 11.
  • 12.
  • 13. 😕
  • 17. final class ProductVariantPriceCalculatorSpec extends ObjectBehavior { function it_implements_product_variant_price_calculator_interface(): void { $this->shouldImplement(ProductVariantPricesCalculatorInterface::class); } function it_gets_price_for_product_variant_in_given_channel( ChannelInterface $channel, ChannelPricingInterface $channelPricing, ProductVariantInterface $productVariant, ): void { $productVariant->getChannelPricingForChannel($channel)->willReturn($channelPricing); $channelPricing->getPrice()->willReturn(1000); $this->calculate($productVariant, ['channel' => $channel])->shouldReturn(1000); } }
  • 18. final class ProductVariantPriceCalculatorSpec extends ObjectBehavior { function it_implements_product_variant_price_calculator_interface(): void { $this->shouldImplement(ProductVariantPricesCalculatorInterface::class); } function it_gets_price_for_product_variant_in_given_channel( ChannelInterface $channel, ChannelPricingInterface $channelPricing, ProductVariantInterface $productVariant, ): void { $productVariant->getChannelPricingForChannel($channel)->willReturn($channelPricing); $channelPricing->getPrice()->willReturn(1000); $this->calculate($productVariant, ['channel' => $channel])->shouldReturn(1000); } } 😡
  • 19. 1 . P O P R A W N O Ś Ć 2 . S P Ó J N O Ś Ć
  • 20. S T A N D A R D Y
  • 21. P U Ł A P K A S P Ó J N O Ś C I
  • 22. D O K U M E N T A C J A
  • 23. T E S T Y
  • 24.
  • 25.
  • 26.
  • 27. A D R
  • 28.
  • 29.
  • 30. K O N T E K S T
  • 31. P Ł O T C H E S T E R T O N A
  • 32. final class GrossPriceCalculatorTest extends TestCase { /** @dataProvider provideGrossCalculationData */ public function testItCountsGrossPriceForGivenNetPriceAndTaxRate( int $netPrice, float $taxRate, int $expectedGrossPrice ): void { self::assertSame( $expectedGrossPrice, GrossPriceCalculator::calculateGrossPrice($netPrice, $taxRate) ); } private function provideGrossCalculationData(): iterable { yield 'net price 500, tax rate 7.0%' => [ 'netPrice' => 500, 'taxRate' => 0.07, 'expectedGrossPrice' => 535, ]; yield 'net price 750, tax rate 7.7%' => [ 'netPrice' => 750, 'taxRate' => 0.077, 'expectedGrossPrice' => 808, ]; yield 'net price 1500, tax rate 8.5%' => [ 'netPrice' => 1500, 'taxRate' => 0.085, 'expectedGrossPrice' => 1628, ]; } }
  • 33. final class GrossPriceCalculatorTest extends TestCase { /** @dataProvider provideGrossCalculationData */ public function testItCountsGrossPriceForGivenNetPriceAndTaxRate( int $netPrice, float $taxRate, int $expectedGrossPrice ): void { self::assertSame( $expectedGrossPrice, GrossPriceCalculator::calculateGrossPrice($netPrice, $taxRate) ); } private function provideGrossCalculationData(): iterable { yield 'net price 500, tax rate 7.0%' => [ 'netPrice' => 500, 'taxRate' => 0.07, 'expectedGrossPrice' => 535, ]; yield 'net price 750, tax rate 7.7%' => [ 'netPrice' => 750, 'taxRate' => 0.077, 'expectedGrossPrice' => 808, ]; yield 'net price 1500, tax rate 8.5%' => [ 'netPrice' => 1500, 'taxRate' => 0.085, 'expectedGrossPrice' => 1628, ]; } } ❗ ❗
  • 34. final class GrossPriceCalculatorTest extends TestCase { /** @dataProvider provideGrossCalculationData */ public function testItCountsGrossPriceForGivenNetPriceAndTaxRate( int $netPrice, float $taxRate, int $expectedGrossPrice ): void { self::assertSame( $expectedGrossPrice, GrossPriceCalculator::calculateGrossPrice($netPrice, $taxRate) ); } private function provideGrossCalculationData(): iterable { yield 'net price 500, tax rate 7.0%' => [ 'netPrice' => 500, 'taxRate' => 0.07, 'expectedGrossPrice' => 535, ]; yield 'net price 750, tax rate 7.7%' => [ 'netPrice' => 750, 'taxRate' => 0.077, 'expectedGrossPrice' => 810, ]; yield 'net price 1500, tax rate 8.5%' => [ 'netPrice' => 1500, 'taxRate' => 0.085, 'expectedGrossPrice' => 1630, ]; } } ✅ ✅ 🤨
  • 35.
  • 36. 😡
  • 37. K O N T E K S T W I E D Z Y I C Z A S U
  • 38. D Ł U G T E C H N I C Z N Y
  • 40. final class OrderTaxesProcessor implements OrderProcessorInterface { public function __construct( private ZoneProviderInterface $defaultTaxZoneProvider, private ZoneMatcherInterface $zoneMatcher, private PrioritizedServiceRegistryInterface $strategyRegistry, private ?TaxationAddressResolverInterface $taxationAddressResolver = null, ) { } public function process(BaseOrderInterface $order): void { if (OrderInterface::STATE_CART !== $order->getState()) { return; } $this->clearTaxes($order); if ($order->isEmpty()) { return; } $zone = $this->getTaxZone($order); if (null === $zone) { return; } /** @var TaxCalculationStrategyInterface $strategy */ foreach ($this->strategyRegistry->all() as $strategy) { if ($strategy->supports($order, $zone)) { $strategy->applyTaxes($order, $zone);
  • 41. public function process(BaseOrderInterface $order): void { if (OrderInterface::STATE_CART !== $order->getState()) { return; } $this->clearTaxes($order); if ($order->isEmpty()) { return; } 😡
  • 42. public function process(BaseOrderInterface $order): void { if ($order->canBeProcessed()) { return; } $this->clearTaxes($order); if ($order->isEmpty()) { return; } if ($order->canBeProcessed()) { return; }
  • 43.
  • 44.
  • 45. 2 0 2 0
  • 46. 2 0 2 0 /api/v2 header /new-api 😂
  • 47. 2 0 2 0 /api/v2 header /new-api 🤡
  • 48.
  • 49. P O S T Ę P J E S T J A K S T A D O Ś W I Ń
  • 50. R E F A C T O R I N G
  • 51.
  • 52.
  • 53. Z A S A D A S K A U T A
  • 54. 16608
  • 55. 38469
  • 56. Z A S A D Y
  • 57. S O L I D K I S S D R Y Y A G N I C U P I D
  • 58. S R P
  • 59. public function process(BaseOrderInterface $order): void { /** @var OrderInterface $order */ Assert::isInstanceOf($order, OrderInterface::class); if (OrderInterface::STATE_CART !== $order->getState()) { return; } $this->clearTaxes($order); if ($order->isEmpty()) { return; } $zone = $this->getTaxZone($order); if (null === $zone) { return; } /** @var TaxCalculationStrategyInterface $strategy */ foreach ($this->strategyRegistry->all() as $strategy) { if ($strategy->supports($order, $zone)) { $strategy->applyTaxes($order, $zone); return; } } throw new UnsupportedTaxCalculationStrategyException(); } private function getTaxZone(OrderInterface $order): ?ZoneInterface { $taxationAddress = $order->getBillingAddress(); $zone = $this->zoneMatcher->match($taxationAddress, Scope::TAX); return $zone ?: $this->defaultTaxZoneProvider->getZone($order); } private function clearTaxes(OrderInterface $order): void { $order->removeAdjustments(AdjustmentInterface::TAX_ADJUSTMENT); foreach ($order->getItems() as $item) { $item->removeAdjustmentsRecursively(AdjustmentInterface::TAX_ADJUSTMENT); } /** @var ShipmentInterface $shipment */ foreach ($order->getShipments() as $shipment) { $shipment->removeAdjustments(AdjustmentInterface::TAX_ADJUSTMENT); } }
  • 60. public function process(BaseOrderInterface $order): void { /** @var OrderInterface $order */ Assert::isInstanceOf($order, OrderInterface::class); if (OrderInterface::STATE_CART !== $order->getState()) { return; } $this->clearTaxes($order); if ($order->isEmpty()) { return; } $zone = $this->getTaxZone($order); if (null === $zone) { return; } /** @var TaxCalculationStrategyInterface $strategy */ foreach ($this->strategyRegistry->all() as $strategy) { if ($strategy->supports($order, $zone)) { $strategy->applyTaxes($order, $zone); return; } } throw new UnsupportedTaxCalculationStrategyException(); } private function getTaxZone(OrderInterface $order): ?ZoneInterface { $taxationAddress = $order->getBillingAddress(); $zone = $this->zoneMatcher->match($taxationAddress, Scope::TAX); return $zone ?: $this->defaultTaxZoneProvider->getZone($order); } private function clearTaxes(OrderInterface $order): void { $order->removeAdjustments(AdjustmentInterface::TAX_ADJUSTMENT); foreach ($order->getItems() as $item) { $item->removeAdjustmentsRecursively(AdjustmentInterface::TAX_ADJUSTMENT); } /** @var ShipmentInterface $shipment */ foreach ($order->getShipments() as $shipment) { $shipment->removeAdjustments(AdjustmentInterface::TAX_ADJUSTMENT); } }
  • 61. public function process(BaseOrderInterface $order): void { /** @var OrderInterface $order */ Assert::isInstanceOf($order, OrderInterface::class); if (OrderInterface::STATE_CART !== $order->getState()) { return; } $this->clearTaxes($order); if ($order->isEmpty()) { return; } $zone = $this->getTaxZone($order); if (null === $zone) { return; } /** @var TaxCalculationStrategyInterface $strategy */ foreach ($this->strategyRegistry->all() as $strategy) { if ($strategy->supports($order, $zone)) { $strategy->applyTaxes($order, $zone); return; } } throw new UnsupportedTaxCalculationStrategyException(); } private function getTaxZone(OrderInterface $order): ?ZoneInterface { $taxationAddress = $order->getBillingAddress(); $zone = $this->zoneMatcher->match($taxationAddress, Scope::TAX); return $zone ?: $this->defaultTaxZoneProvider->getZone($order); } private function clearTaxes(OrderInterface $order): void { $order->removeAdjustments(AdjustmentInterface::TAX_ADJUSTMENT); foreach ($order->getItems() as $item) { $item->removeAdjustmentsRecursively(AdjustmentInterface::TAX_ADJUSTMENT); } /** @var ShipmentInterface $shipment */ foreach ($order->getShipments() as $shipment) { $shipment->removeAdjustments(AdjustmentInterface::TAX_ADJUSTMENT); } }
  • 62. I M P L E M E N T A C J A Z P R Z Y P A D K U
  • 63.
  • 64.
  • 65. Excellence lives inside pragmatic boundaries
  • 66. D D D
  • 67. D I S C O M F O R T D R I V E N D E V E L O P M E N T