SlideShare uma empresa Scribd logo
@lukaszchrusciel
Is
Is SOLID
SOLID
dead?
dead?
Let's discuss reusable
Let's discuss reusable
software design
software design
@lukaszchrusciel
@lukaszchrusciel
Context
Context is a King
is a King
@lukaszchrusciel
Story
Story
@lukaszchrusciel
S
Single
ingle
Responsibility
Responsibility
Principle
Principle
@lukaszchrusciel
public function __invoke(string $orderNumber, int $unitId, int $amount,
RefundTypeInterface $refundType): void
{
/** @var OrderInterface|null $order */
$order = $this->orderRepository->findOneByNumber($orderNumber);
Assert::notNull($order);
$remainingTotal = $this->remainingTotalProvider->getTotalLeftToRefund($unitId,
$refundType);
if ($remainingTotal === 0) {
throw UnitAlreadyRefunded::withIdAndOrderNumber($unitId, $orderNumber);
}
$refund = $this->refundFactory->createWithData($order, $unitId, $amount,
$refundType);
$this->refundManager->persist($refund);
$this->refundManager->flush();
}
@lukaszchrusciel
Types of classes
Types of classes
@lukaszchrusciel
Types of classes
Types of classes
Data structures
Data structures
@lukaszchrusciel
Data structures
Data structures
ValueObjects
–
@lukaszchrusciel
Data structures
Data structures
ValueObjects
–
DataTransferObjects
–
@lukaszchrusciel
Data structures
Data structures
ValueObjects
–
DataTransferObjects
–
Models
–
@lukaszchrusciel
Data structures
Data structures
ValueObjects
–
DataTransferObjects
–
Models
–
Entities
–
@lukaszchrusciel
Data structures
Data structures
readonly class BlameCart
{
public function __construct(
public string $shopUserEmail,
public string $orderTokenValue
) {
}
}
@lukaszchrusciel
Types of classes
Types of classes
Data structures
Data structures
Calculations
Calculations
@lukaszchrusciel
Calculations
Calculations
F(X) →
F(X) → Y
Y
@lukaszchrusciel
Calculations (pure functions)
Calculations (pure functions)
final class PerUnitRateCalculator implements CalculatorInterface
{
public function calculate(ShipmentInterface $subject, array
$configuration): int
{
return (int) ($configuration['amount'] * $subject-
>getShippingUnitCount());
}
public function getType(): string
{
return 'per_unit_rate';
}
}
@lukaszchrusciel
Calculations (impure functions)
Calculations (impure functions)
final class PromotionApplicator implements PromotionApplicatorInterface
{
public function __construct(private ServiceRegistryInterface $registry)
{
}
public function apply(PromotionSubjectInterface $subject, PromotionInterface $promotion): void
{
$applyPromotion = false;
foreach ($promotion->getActions() as $action) {
$result = $this->registry->get($action->getType())->execute($subject, $action-
>getConfiguration(), $promotion);
$applyPromotion = $applyPromotion || $result;
}
if ($applyPromotion) {
$subject->addPromotion($promotion);
}
}
}
@lukaszchrusciel
Calculations (impure functions)
Calculations (impure functions)
final class PromotionApplicator implements PromotionApplicatorInterface
{
public function __construct(private ServiceRegistryInterface $registry)
{
}
public function apply(PromotionSubjectInterface $subject, PromotionInterface $promotion): void
{
$applyPromotion = false;
foreach ($promotion->getActions() as $action) {
$result = $this->registry->get($action->getType())->execute($subject, $action-
>getConfiguration(), $promotion);
$applyPromotion = $applyPromotion || $result;
}
if ($applyPromotion) {
$subject->addPromotion($promotion);
}
}
}
@lukaszchrusciel
Types of classes
Types of classes
Data structures
Data structures
Calculations
Calculations
Side effects
Side effects
@lukaszchrusciel
Communication outside of the local
Communication outside of the local
scope
scope
Mailing
–
@lukaszchrusciel
Communication outside of the local
Communication outside of the local
scope
scope
Mailing
–
Transaction committing
–
@lukaszchrusciel
Communication outside of the local
Communication outside of the local
scope
scope
Mailing
–
Transaction committing
–
Making request
–
@lukaszchrusciel
public function __invoke(string $orderNumber, int $unitId, int $amount,
RefundTypeInterface $refundType): void
{
/** @var OrderInterface|null $order */
$order = $this->orderRepository->findOneByNumber($orderNumber);
Assert::notNull($order);
$remainingTotal = $this->remainingTotalProvider->getTotalLeftToRefund($unitId,
$refundType);
if ($remainingTotal === 0) {
throw UnitAlreadyRefunded::withIdAndOrderNumber($unitId, $orderNumber);
}
$refund = $this->refundFactory->createWithData($order, $unitId, $amount,
$refundType);
$this->refundManager->persist($refund);
$this->refundManager->flush();
}
@lukaszchrusciel
Communication outside of the local scope
Communication outside of the local scope
public function __invoke(string $orderNumber, int $unitId, int $amount, RefundTypeInterface
$refundType): void
{
$order = $this->orderRepository->findOneByNumber($orderNumber);
$remainingTotal = $this->remainingTotalProvider->getTotalLeftToRefund($unitId, $refundType);
if ($remainingTotal === 0) {
throw UnitAlreadyRefunded::withIdAndOrderNumber($unitId, $orderNumber);
}
$refund = $this->refundFactory->createWithData(
$order,
$unitId,
$amount,
$refundType
);
$this->refundManager->persist($refund);
$this->refundManager->flush();
}
@lukaszchrusciel
Communication outside of the local scope
Communication outside of the local scope
public function __invoke(string $orderNumber, int $unitId, int $amount, RefundTypeInterface
$refundType): void
{
$order = $this->orderRepository->findOneByNumber($orderNumber);
$remainingTotal = $this->remainingTotalProvider->getTotalLeftToRefund($unitId, $refundType);
if ($remainingTotal === 0) {
throw UnitAlreadyRefunded::withIdAndOrderNumber($unitId, $orderNumber);
}
$refund = $this->refundFactory->createWithData(
$order,
$unitId,
$amount,
$refundType
);
return $refund;
}
@lukaszchrusciel
@lukaszchrusciel
O
Open-Close
pen-Close
Principle
Principle
@lukaszchrusciel
private function getRefundUnitTotal(
int $id,
RefundTypeInterface $refundType
): int
@lukaszchrusciel
private function getRefundUnitTotal(int $id,
RefundTypeInterface $refundType): int
{
if ($refundType->getValue() ===
RefundTypeInterface::ORDER_ITEM_UNIT) {
// calculation
return $value;
}
// calculation
return $otherValue;
}
@lukaszchrusciel
private function getRefundUnitTotal(int
$id, RefundTypeInterface $refundType): int
{
$refundUnitTotalProvider = $this-
>totalProviderRegistry->get($refundType-
>getValue());
return $refundUnitTotalProvider-
>getRefundUnitTotal($id);
}
@lukaszchrusciel
protected function configureOptionsNode(ArrayNodeDefinition
$optionsNode): void
{
$optionsNode
->children()
->integerNode('amount')->isRequired()->min(0)->end()
->scalarNode('channel')->cannotBeEmpty()->end()
->scalarNode('customer')->cannotBeEmpty()->end()
->scalarNode('country')->cannotBeEmpty()->end()
->booleanNode('fulfilled')->defaultValue(false)-
>end()
->end()
;
}
@lukaszchrusciel
@lukaszchrusciel
@lukaszchrusciel
@lukaszchrusciel
protected function configureOptionsNode(ArrayNodeDefinition
$optionsNode): void
{
$optionsNode
->children()
->integerNode('amount')->isRequired()->min(0)->end()
->scalarNode('channel')->cannotBeEmpty()->end()
->scalarNode('customer')->cannotBeEmpty()->end()
->scalarNode('country')->cannotBeEmpty()->end()
->booleanNode('fulfilled')->defaultValue(false)-
>end()
->end()
;
}
@lukaszchrusciel
L
Liskov
iskov
Substitution
Substitution
Principle
Principle
@lukaszchrusciel
Behavioural
Behavioural
sub-typing
sub-typing
@lukaszchrusciel
Covariance
Covariance
abstract class Animal
{
}
class Cat extends Animal
{
}
interface AnimalShelter
{
public function adopt(): Animal;
}
class CatShelter implements AnimalShelter
{
public function adopt(): Cat // instead of returning class type Animal, it can return class type Cat
{
return new Cat();
}
}
@lukaszchrusciel
abstract class Animal
{
}
class Cat extends Animal
{
}
interface CatShelter
{
public function adopt(Cat $cat);
}
class AnimalShelter implements CatShelter
{
public function adopt(Animal $animal) // instead of accepting class type Cat, it can
accept any Animal
{
return new Cat();
}
}
@lukaszchrusciel
abstract class Animal
{
}
class Cat extends Animal
{
}
interface CatShelter
{
public function adopt(Animal $cat);
}
class AnimalShelter implements CatShelter
{
public function adopt(Cat $animal) // instead of accepting class type Cat, it can accept any Animal
{
return new Cat();
}
}
Fatal error: Declaration of AnimalShelter::adopt(Cat $animal) must be compatible with
CatShelter::adopt(Animal $cat) in /tmp/preview on line 19
@lukaszchrusciel
interface CalculatorInterface
{
public function
calculate(ShipmentInterface $subject,
array $configuration): int;
public function getType(): string;
}
@lukaszchrusciel
final class PerUnitRateCalculator implements CalculatorInterface
{
public function calculate(ShipmentInterface $subject, array
$configuration): int
{
return (int) ($configuration['amount'] * $subject-
>getShippingUnitCount());
}
public function getType(): string
{
return 'per_unit_rate';
}
}
@lukaszchrusciel
{
/**
* @param array{'amount': int}
$configuration
*/
public function calculate(ShipmentInterface
$subject, array $configuration): int;
public function getType(): string;
}
@lukaszchrusciel
interface CalculatorInterface
{
/**
* @throws
InvalidCalculatorConfigurationException
*/
public function calculate(ShipmentInterface
$subject, array $configuration): int;
public function getType(): string;
}
@lukaszchrusciel
public function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions($resolver);
// some logic
$resolver->setDefined([
'data',
]);
$resolver->setDefaults([
'data_class' => $dataClass,
'empty_data' => $emptyData,
'...' =>
]);
@lukaszchrusciel
interface CalculatorInterface
{
/**
* @throws
InvalidCalculatorConfigurationException
*/
public function calculate(Configuration
$configuration): int;
public function getType(): string;
}
@lukaszchrusciel
$resources = $this->resourcesResolver-
>getResources($requestConfiguration, $repository);
$paginationLimits = [];
if ($resources instanceof ResourceGridView) {
$paginator = $resources->getData();
$paginationLimits = $resources-
>getDefinition()->getLimits();
} else {
$paginator = $resources;
}
@lukaszchrusciel
I
Interface
nterface
Segregation
Segregation
Principle
Principle
@lukaszchrusciel
interface OrderRepositoryInterface extends BaseOrderRepositoryInterface
{
public function createListQueryBuilder(): QueryBuilder;
public function createSearchListQueryBuilder(): QueryBuilder;
public function createByCustomerIdQueryBuilder($customerId): QueryBuilder;
public function createByCustomerAndChannelIdQueryBuilder($customerId, $channelId): QueryBuilder;
public function countByCustomerAndCoupon(CustomerInterface $customer, PromotionCouponInterface $coupon): int;
public function countByCustomer(CustomerInterface $customer): int;
public function findOrderById($id): ?OrderInterface;
public function findByCustomer(CustomerInterface $customer): array;
public function findForCustomerStatistics(CustomerInterface $customer): array;
public function findOneForPayment($id): ?OrderInterface;
public function findOneByNumberAndCustomer(string $number, CustomerInterface $customer): ?OrderInterface;
public function findCartByChannel($id, ChannelInterface $channel): ?OrderInterface;
public function findLatestCartByChannelAndCustomer(ChannelInterface $channel, CustomerInterface $customer): ?OrderInterface;
public function findLatestNotEmptyCartByChannelAndCustomer(ChannelInterface $channel, CustomerInterface $customer): ?OrderInterface;
public function getTotalSalesForChannel(ChannelInterface $channel): int;
public function getTotalPaidSalesForChannel(ChannelInterface $channel): int;
public function getTotalPaidSalesForChannelInPeriod(ChannelInterface $channel, DateTimeInterface $startDate, DateTimeInterface $endDate): int;
public function countFulfilledByChannel(ChannelInterface $channel): int;
public function countPaidByChannel(ChannelInterface $channel): int;
public function countPaidForChannelInPeriod(ChannelInterface $channel, DateTimeInterface $startDate, DateTimeInterface $endDate): int;
public function findLatestInChannel(int $count, ChannelInterface $channel): array;
public function findOrdersUnpaidSince(DateTimeInterface $terminalDate, ?int $limit = null): array;
public function findCartForSummary($id): ?OrderInterface;
public function findCartForAddressing($id): ?OrderInterface;
public function findCartForSelectingShipping($id): ?OrderInterface;
public function findCartForSelectingPayment($id): ?OrderInterface;
public function findCartByTokenValue(string $tokenValue): ?BaseOrderInterface;
public function findCartByTokenValueAndChannel(string $tokenValue, ChannelInterface $channel): ?BaseOrderInterface;
}
@lukaszchrusciel
OrderRepositoryInterface extends
BaseOrderRepositoryInterface
@lukaszchrusciel
D
Dependency
ependency
Inversion
Inversion
Principle
Principle
@lukaszchrusciel
public function __invoke(VerifyCustomerAccount $command): JsonResponse
{
/** @var UserInterface|null $user */
$user = $this->shopUserRepository->findOneBy(['emailVerificationToken' =>
$command->token]);
if (null === $user) {
throw new InvalidArgumentException(
sprintf('There is no shop user with %s email verification token',
$command->token),
);
}
$user->setVerifiedAt(new DateTime());
$user->setEmailVerificationToken(null);
$user->enable();
return new JsonResponse([]);
}
@lukaszchrusciel
public function __construct(
private RepositoryInterface $shopUserRepository,
private DateTimeProviderInterface $calendar,
) {
}
public function __invoke(VerifyCustomerAccount $command): JsonResponse
{
/** @var UserInterface|null $user */
$user = $this->shopUserRepository->findOneBy(['emailVerificationToken' => $command->token]);
if (null === $user) {
throw new InvalidArgumentException(
sprintf('There is no shop user with %s email verification token', $command->token),
);
}
$user->setVerifiedAt($this->calendar->now());
$user->setEmailVerificationToken(null);
$user->enable();
return new JsonResponse([]);
}
@lukaszchrusciel
Sylius/Calendar
–
PSR-20 Clock interface +
Symfony/Clock
–
@lukaszchrusciel
@lukaszchrusciel
@lukaszchrusciel
@lukaszchrusciel
FINAL
FINAL
@lukaszchrusciel
What the horse is, everyone can see
1
ks. Benedykta Chmielowskiego
1.
@lukaszchrusciel
What the address is, everyone can
see 1
Łukasz Chruściel
1.
@lukaszchrusciel
Łukasz Chruściel
Wólczańska 125
90-521 Łódź
Poland
@lukaszchrusciel
Name Surename
Street StreetNumber (?Flat)
PostCode City
Country
@lukaszchrusciel
Antigua and Barbuda
–
Aruba
–
Ascension island
–
Bahamas
–
Belize
–
Benin
–
Botswana
–
Bolivia
–
Bonaire, Sint Eustatius and Saba
–
Burkina Faso
–
Burundi
–
Cameroon
–
Central African Republic
–
Comoros
–
Congo
–
Congo the Democratic Republic of the
–
Cook Islands
–
Cote d’Ivoire
–
Curaçao
–
Djibouti
–
Dominica
–
East Timor
–
Equatorial Guinea
–
Eritrea
–
Fiji
–
French Southern Territories
–
Gambia
–
Gamon
–
Ghana
–
Grenada
–
Guyana
–
Heard and McDonald Islands
–
Hong Kong
–
Kiribati
–
Libya
–
Macau
–
Malawi
–
Mali
–
Mauritania
–
Nauru
–
Netherlands Antilles
–
Niue
–
North Korea
–
Qatar
–
Rwanda
–
Saint Kitts and Nevis
–
Sao Tome and Principe
–
Seychelles
–
Sierra Leone
–
Solomon Islands
–
Suriname
–
Syria
–
Timor-Leste
–
Togo
–
Tokelau
–
Tonga
–
Tuvalu
–
Uganda
–
United Arab Emirates
–
Vanuatu
–
Yemen
–
Zimbabwe
–
@lukaszchrusciel
Antigua and Barbuda
–
Aruba
–
Ascension island
–
Bahamas
–
Belize
–
Benin
–
Botswana
–
Bolivia
–
Bonaire, Sint Eustatius and Saba
–
Burkina Faso
–
Burundi
–
Cameroon
–
Central African Republic
–
Comoros
–
Congo
–
Congo the Democratic Republic of the
–
Cook Islands
–
Cote d’Ivoire
–
Curaçao
–
Djibouti
–
Dominica
–
East Timor
–
Equatorial Guinea
–
Eritrea
–
Fiji
–
French Southern Territories
–
Gambia
–
Gamon
–
Ghana
–
Grenada
–
Guyana
–
Heard and McDonald Islands
–
Hong Kong
Hong Kong
–
Kiribati
–
Libya
–
Macau
Macau
–
Malawi
–
Mali
–
Mauritania
–
Nauru
–
Netherlands Antilles
–
Niue
–
North Korea
–
Qatar
Qatar
–
Rwanda
–
Saint Kitts and Nevis
–
Sao Tome and Principe
–
Seychelles
–
Sierra Leone
–
Solomon Islands
–
Suriname
–
Syria
–
Timor-Leste
–
Togo
–
Tokelau
–
Tonga
–
Tuvalu
–
Uganda
–
United Arab Emirates
United Arab Emirates
–
Vanuatu
–
Yemen
–
Zimbabwe
–
@lukaszchrusciel
Name Surename
Street StreetNumber (?Flat)
PostCode City
Country
@lukaszchrusciel
Outro
Outro
@lukaszchrusciel
SOLID works perfectly
SOLID works perfectly in
in
the context of reusable
the context of reusable
software
software
@lukaszchrusciel
SOLID gives useful
SOLID gives useful
directions how to design
directions how to design
any code
any code
@lukaszchrusciel
Benefits of these
Benefits of these
approaches
approaches
@lukaszchrusciel
Is there anything
Is there anything
more in
more in CUPID
CUPID?
?
@lukaszchrusciel
Resources
Resources
https://symfonycasts.com/screencast/solid/
https://symfonycasts.com/screencast/solid/
https://stackoverflow.blog/2021/11/01/why-solid-principles-are-still-the-foundation-for-modern-
software-architecture/
–
https://dannorth.net/2022/02/10/cupid-for-joyful-coding/
–
https://speakerdeck.com/tastapod/why-every-element-of-solid-is-wrong
–
https://www.reddit.com/r/programming/comments/5qto27/why_every_element_of_solid_is_wrong/
–
https://solid-is-not-solid.com/
–
Norbert Wójtowicz (@pithyless) - Functional Programming
–
https://www.youtube.com/watch?v=-Z-17h3jG0A
–
@lukaszchrusciel
Takeaways
Takeaways If you see clickbait title with
If you see clickbait title with
question in it
question in it
Then the answer is always no
no
Functional programming may
Functional programming may
help us
help us
Deliver better ObjectOriented code
SOLID is a solid fundament for
SOLID is a solid fundament for
packages that will be reused by
packages that will be reused by
other devs
other devs
But end applications may benefit from it as well
Doing eCommerce? Give a
Doing eCommerce? Give a
Sylius try ;)
Sylius try ;)
Don't be discouraged by this presentation
@lukaszchrusciel
@lukaszchrusciel
Thank you!
Thank you!

Mais conteúdo relacionado

Mais procurados

REST Versioning Architecture with ASP.NET MVC Web API v1.2
REST Versioning Architecture with ASP.NET MVC Web API v1.2REST Versioning Architecture with ASP.NET MVC Web API v1.2
REST Versioning Architecture with ASP.NET MVC Web API v1.2
Rodrigo Ezequiel Liberoff V
 

Mais procurados (20)

Query to get the geography information using bi report
Query to get the geography information using bi reportQuery to get the geography information using bi report
Query to get the geography information using bi report
 
Installation de Sylius 2.0 et découverte du nouveau backoffice en Bootstrap
Installation de Sylius 2.0 et découverte du nouveau backoffice en BootstrapInstallation de Sylius 2.0 et découverte du nouveau backoffice en Bootstrap
Installation de Sylius 2.0 et découverte du nouveau backoffice en Bootstrap
 
Calendar working days and holidays for Oracle EBS R12 Absence management
Calendar working days and holidays for Oracle EBS R12 Absence managementCalendar working days and holidays for Oracle EBS R12 Absence management
Calendar working days and holidays for Oracle EBS R12 Absence management
 
Django for Beginners
Django for BeginnersDjango for Beginners
Django for Beginners
 
Java Basics V3
Java Basics V3Java Basics V3
Java Basics V3
 
The Point of Vue - Intro to Vue.js
The Point of Vue - Intro to Vue.jsThe Point of Vue - Intro to Vue.js
The Point of Vue - Intro to Vue.js
 
Java 8 - CJ
Java 8 - CJJava 8 - CJ
Java 8 - CJ
 
OOP V3.1
OOP V3.1OOP V3.1
OOP V3.1
 
SQL Server Stored procedures
SQL Server Stored proceduresSQL Server Stored procedures
SQL Server Stored procedures
 
JDBC
JDBCJDBC
JDBC
 
Effective Java - Enum and Annotations
Effective Java - Enum and AnnotationsEffective Java - Enum and Annotations
Effective Java - Enum and Annotations
 
Functional Principles for OO Developers
Functional Principles for OO DevelopersFunctional Principles for OO Developers
Functional Principles for OO Developers
 
SQL : introduction
SQL : introductionSQL : introduction
SQL : introduction
 
Hibernate
Hibernate Hibernate
Hibernate
 
The Goal with performance details Oracle Fusion Cloud
The Goal with performance details Oracle Fusion CloudThe Goal with performance details Oracle Fusion Cloud
The Goal with performance details Oracle Fusion Cloud
 
REST Versioning Architecture with ASP.NET MVC Web API v1.2
REST Versioning Architecture with ASP.NET MVC Web API v1.2REST Versioning Architecture with ASP.NET MVC Web API v1.2
REST Versioning Architecture with ASP.NET MVC Web API v1.2
 
MVVM with SwiftUI and Combine
MVVM with SwiftUI and CombineMVVM with SwiftUI and Combine
MVVM with SwiftUI and Combine
 
Log4 J
Log4 JLog4 J
Log4 J
 
Legal Employer Details Query Oracle Fusion Cloud
Legal Employer Details Query Oracle Fusion CloudLegal Employer Details Query Oracle Fusion Cloud
Legal Employer Details Query Oracle Fusion Cloud
 
Object Oriented PHP - PART-1
Object Oriented PHP - PART-1Object Oriented PHP - PART-1
Object Oriented PHP - PART-1
 

Semelhante a SymfonyLive Online 2023 - Is SOLID dead? .pdf

Oneal perl-code-to-extract-from-voyager
Oneal perl-code-to-extract-from-voyagerOneal perl-code-to-extract-from-voyager
Oneal perl-code-to-extract-from-voyager
ENUG
 

Semelhante a SymfonyLive Online 2023 - Is SOLID dead? .pdf (20)

You code sucks, let's fix it
You code sucks, let's fix itYou code sucks, let's fix it
You code sucks, let's fix it
 
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
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design Patterns
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
 
Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome Town
 
The Art of Transduction
The Art of TransductionThe Art of Transduction
The Art of Transduction
 
Oneal perl-code-to-extract-from-voyager
Oneal perl-code-to-extract-from-voyagerOneal perl-code-to-extract-from-voyager
Oneal perl-code-to-extract-from-voyager
 
linieaire regressie
linieaire regressielinieaire regressie
linieaire regressie
 
Writing Sensible Code
Writing Sensible CodeWriting Sensible Code
Writing Sensible Code
 
Why async and functional programming in PHP7 suck and how to get overr it?
Why async and functional programming in PHP7 suck and how to get overr it?Why async and functional programming in PHP7 suck and how to get overr it?
Why async and functional programming in PHP7 suck and how to get overr it?
 
PHP for Python Developers
PHP for Python DevelopersPHP for Python Developers
PHP for Python Developers
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mocking
 
Introduction to DI(C)
Introduction to DI(C)Introduction to DI(C)
Introduction to DI(C)
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
 
Desymfony2013.gonzalo123
Desymfony2013.gonzalo123Desymfony2013.gonzalo123
Desymfony2013.gonzalo123
 
Command-Oriented Architecture
Command-Oriented ArchitectureCommand-Oriented Architecture
Command-Oriented Architecture
 
Symfony2 - extending the console component
Symfony2 - extending the console componentSymfony2 - extending the console component
Symfony2 - extending the console component
 
Functional php
Functional phpFunctional php
Functional php
 
Oops in php
Oops in phpOops in php
Oops in php
 
Your code sucks, let's fix it - PHP Master Series 2012
Your code sucks, let's fix it - PHP Master Series 2012Your code sucks, let's fix it - PHP Master Series 2012
Your code sucks, let's fix it - PHP Master Series 2012
 

Mais de Łukasz Chruściel

Mais de Łukasz Chruściel (20)

Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
ConFoo 2024 - Need for Speed: Removing speed bumps in API Projects
ConFoo 2024  - Need for Speed: Removing speed bumps in API ProjectsConFoo 2024  - Need for Speed: Removing speed bumps in API Projects
ConFoo 2024 - Need for Speed: Removing speed bumps in API Projects
 
ConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solution
ConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solutionConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solution
ConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solution
 
SyliusCon - Typical pitfalls of Sylius development.pdf
SyliusCon - Typical pitfalls of Sylius development.pdfSyliusCon - Typical pitfalls of Sylius development.pdf
SyliusCon - Typical pitfalls of Sylius development.pdf
 
Need for Speed: Removing speed bumps in API Projects
Need for Speed: Removing speed bumps in API ProjectsNeed for Speed: Removing speed bumps in API Projects
Need for Speed: Removing speed bumps in API Projects
 
Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...
Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...
Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...
 
4Developers - Rozterki i decyzje.pdf
4Developers - Rozterki i decyzje.pdf4Developers - Rozterki i decyzje.pdf
4Developers - Rozterki i decyzje.pdf
 
4Developers - Sylius CRUD generation revisited.pdf
4Developers - Sylius CRUD generation revisited.pdf4Developers - Sylius CRUD generation revisited.pdf
4Developers - Sylius CRUD generation revisited.pdf
 
BoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API Syliusa
BoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API SyliusaBoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API Syliusa
BoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API Syliusa
 
What we've learned designing new Sylius API
What we've learned designing new Sylius APIWhat we've learned designing new Sylius API
What we've learned designing new Sylius API
 
How to optimize background processes.pdf
How to optimize background processes.pdfHow to optimize background processes.pdf
How to optimize background processes.pdf
 
SymfonyCon - Dilemmas and decisions..pdf
SymfonyCon - Dilemmas and decisions..pdfSymfonyCon - Dilemmas and decisions..pdf
SymfonyCon - Dilemmas and decisions..pdf
 
Symfony World - Symfony components and design patterns
Symfony World - Symfony components and design patternsSymfony World - Symfony components and design patterns
Symfony World - Symfony components and design patterns
 
Sylius and Api Platform The story of integration
Sylius and Api Platform The story of integrationSylius and Api Platform The story of integration
Sylius and Api Platform The story of integration
 
Dutch php a short tale about state machine
Dutch php   a short tale about state machineDutch php   a short tale about state machine
Dutch php a short tale about state machine
 
A short tale about state machine
A short tale about state machineA short tale about state machine
A short tale about state machine
 
A short tale about state machine
A short tale about state machineA short tale about state machine
A short tale about state machine
 
BDD in practice based on an open source project
BDD in practice based on an open source projectBDD in practice based on an open source project
BDD in practice based on an open source project
 
Diversified application testing based on a Sylius project
Diversified application testing based on a Sylius projectDiversified application testing based on a Sylius project
Diversified application testing based on a Sylius project
 
Why do I love and hate php?
Why do I love and hate php?Why do I love and hate php?
Why do I love and hate php?
 

Último

AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
Alluxio, Inc.
 

Último (20)

Breaking the Code : A Guide to WhatsApp Business API.pdf
Breaking the Code : A Guide to WhatsApp Business API.pdfBreaking the Code : A Guide to WhatsApp Business API.pdf
Breaking the Code : A Guide to WhatsApp Business API.pdf
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
AI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAG
AI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAGAI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAG
AI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAG
 
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
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
 
Studiovity film pre-production and screenwriting software
Studiovity film pre-production and screenwriting softwareStudiovity film pre-production and screenwriting software
Studiovity film pre-production and screenwriting software
 
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
 
Workforce Efficiency with Employee Time Tracking Software.pdf
Workforce Efficiency with Employee Time Tracking Software.pdfWorkforce Efficiency with Employee Time Tracking Software.pdf
Workforce Efficiency with Employee Time Tracking Software.pdf
 
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
 
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
 
A Guideline to Gorgias to to Re:amaze Data Migration
A Guideline to Gorgias to to Re:amaze Data MigrationA Guideline to Gorgias to to Re:amaze Data Migration
A Guideline to Gorgias to to Re:amaze Data Migration
 
Top Mobile App Development Companies 2024
Top Mobile App Development Companies 2024Top Mobile App Development Companies 2024
Top Mobile App Development Companies 2024
 
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
 
AI/ML Infra Meetup | ML explainability in Michelangelo
AI/ML Infra Meetup | ML explainability in MichelangeloAI/ML Infra Meetup | ML explainability in Michelangelo
AI/ML Infra Meetup | ML explainability in Michelangelo
 
Agnieszka Andrzejewska - BIM School Course in Kraków
Agnieszka Andrzejewska - BIM School Course in KrakówAgnieszka Andrzejewska - BIM School Course in Kraków
Agnieszka Andrzejewska - BIM School Course in Kraków
 
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
 
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
 
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
 
5 Reasons Driving Warehouse Management Systems Demand
5 Reasons Driving Warehouse Management Systems Demand5 Reasons Driving Warehouse Management Systems Demand
5 Reasons Driving Warehouse Management Systems Demand
 
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...
 

SymfonyLive Online 2023 - Is SOLID dead? .pdf