SlideShare a Scribd company logo
Why should we use SIMPLE FACTORY pattern
even when we have one class only?
Based on DateTime (PHP) and PHPUnit
by Rafal Ksiazek, IT Leader
https://github.com/harpcio
Real example (or maybe not):
Application for an airline company
based in Europe
Requirements:
…
User should be able to create a flight route
...
Without SF With SF
public function createFlightRoute(User $user, $startTime, ...)
{
$route = new FlightRoute();
$route->setCreateTime(new DateTime());
$route->setStartTime(new DateTime($startTime));
$route->setEndTime(new DateTime($endTime));
$route->setStartPlace($startPlace);
$route->setEndPlace($endPlace);
$route->setCargo($cargo);
$route->setCreatedBy($user);
...
return $route;
}
class DateTimeFactory implements DateTimeFactoryInterface
{
public function create(
$time = 'now', DateTimeZone $timeZone = null
) {
return new DateTime($time, $timeZone);
}
}
…
public function __construct(..., DateTimeFactoryInterface $dateTimeFactory)
{
….
$this->dateTimeFactory = $dateTimeFactory;
}
public function createFlightRoute(User $user, $startTime, ...)
{
$route = new FlightRoute();
$route->setCreateTime($this->dateTimeFactory->create());
$route->setStartTime($this->dateTimeFactory->create($startTime));
$route->setEndTime($this->dateTimeFactory->create($endTime));
$route->setStartPlace($startPlace);
$route->setEndPlace($endPlace);
$route->setCargo($cargo);
$route->setCreatedBy($user);
...
return $route;
}
There is one thing we can be sure of:
CHANGE
So be prepared!
New client requirement!
Move our application to the new
powerful dedicated server
in US (Detroit)
The programmer copies the code and databases,
checks that everything works (twice!)
… but he forgets about timezones
A few hours later, first unhappy customers began to call the company
The blocker task!
The programmer changes the timezone on Detroit's server to European
timezone in one minute!
But we got
new client requirement!
For security, application should be independent of
the server's timezone
Without SF With SF
… somewhere in configuration
define('APP_TIME_ZONE', 'Europe/NoExistingCity')
… in „n” classes:
public function createFlightRoute(User $user, $startTime, ...)
{
$route = new FlightRoute();
$route->setCreateTime(
new DateTime('now', new DateTimeZone(APP_TIME_ZONE))
);
$route->setStartTime(
new DateTime($startTime, DateTimeZone(APP_TIME_ZONE))
);
$route->setEndTime(
new DateTime($endTime, DateTimeZone(APP_TIME_ZONE))
);
$route->setStartPlace($startPlace);
$route->setEndPlace($endPlace);
$route->setCargo($cargo);
$route->setCreatedBy($user);
...
return $route;
}
… somewhere in configuration
define('APP_TIME_ZONE', 'Europe/NoExistingCity')
… in only ONE class:
class DateTimeFactory implements DateTimeFactoryInterface
{
public function create($time = 'now', DateTimeZone $timeZone = null) {
if (null === $timeZone) {
$timeZone = new DateTimeZone(APP_TIME_ZONE);
}
return new DateTime($time, $timeZone);
}
}
… after hours of discussion and calculation of the cost of the failure, we got:
New client requirement!
All functionalities based on dates
should be fully tested
Without SF With SF
… in the test class:
public function setUp() {
$this->testedObject = ...
}
public function testCreateFlightRoute() {
$createTime = new DateTime('now', DateTimeZone(APP_TIME_ZONE));
$result = $this->testedObject->createFlightRoute($user, $startTime, ...);
$this->assertSame(
$result->getCreateTime()->format('Y-m-d H:i:s'),
$createTime->format('Y-m-d H:i:s')
);
}
But sometimes our tests are FAILED!
Someone know why?
… in the test class:
public function setUp() {
$this->testedObject = ...
}
public function testCreateFlightRoute() {
$this->dateTimeFactoryMock = $this->getMock(...)
$createTime = new DateTime('now', APP_TIME_ZONE);
$this->dateTimeFactoryMock->expects($this->at(0))
->method('create')
->willReturn($createTime);
$result = $this->testedObject->createFlightRoute($user, $startTime, ...);
$this->assertSame($result->getCreateTime(), $createTime);
}
Always PASSED!
Without SF With SF
Pros:
● We'll build our application „faster”*
(initially, anyway)
* yes, couple of minutes less per class is really an irrefutable fact
Cons:
● Each change will cost us a lot:
– time for implementation & bugs fixing
– customer confidence
– money
● When we'll start writing tests - we'll have to use
simple factory
– otherwise we will have broken builds from time to
time
Pros:
● We're saving (days|hours|minutes) of our time,
but also our client’s time (bugs)
– Do you remember the "n" classes we had to
change?
– In how many places can we potentially make
mistakes that way? How much time will we spend on
manual testing of all classes that we've changed?
● We can write tests for our classes in a proper
way - we will not have any failed builds ever
Cons:
● We need 1-3 minutes to create simply factory
class and inject it into our class
But what about creating not breakable tests?
class DateTimeFactoryMock() implements DataTimeFactoryInterface
{
public function __construct(array $nowTimes)
{
$this->nowTimes = $nowTimes;
}
public function create($time = 'now', DateTimeZone $timeZone = null)
{
if (null === $timeZone) {
$timeZone = new DateTimeZone(APP_TIME_ZONE);
}
if ('now' === $time) {
$time = array_shift($this->nowTimes);
}
return new DateTime($time, $timeZone);
}
}
... in test class
public function setUp()
{
$this->nowTime1 = '2012-01-01 12:00:00';
$dateTimeFactory = new DateTimeFactoryMock([$this->nowTime1]);
$this->testedObject = new AirRouteManager($dateTimeFactory);
}
public function testCreateFlightRoute()
{
$result = $this->testedObject->createFlightRoute($user, $startTime, ...);
...
$this->assertSame($result->getCreateTime()->format('Y-m-d H:i:s'), $this->nowTime1);
}
What about KISS
Simple Factory classes are very simple and stupid,
but I can obviously come up with an even simpler
and stupider class..
class A() {
public function doNothing() {
// yeah, this method really does nothing!
}
}
...but I'm afraid, that this class won't do us much good
What about YAGNI
Yes, YAGNI is about functionalities.. and we'll use
this functionality everywhere!
Yes! Everywhere, where we want the new
instances..
Thank you very much
for waching!

More Related Content

PDF
Design patterns in javascript
DOCX
Pratik Bakane C++
PDF
[Quase] Tudo que você precisa saber sobre tarefas assíncronas
PDF
Tasks: you gotta know how to run them
DOCX
Pratik Bakane C++
PDF
Functions
DOCX
Pratik Bakane C++
DOCX
Pratik Bakane C++
Design patterns in javascript
Pratik Bakane C++
[Quase] Tudo que você precisa saber sobre tarefas assíncronas
Tasks: you gotta know how to run them
Pratik Bakane C++
Functions
Pratik Bakane C++
Pratik Bakane C++

What's hot (20)

PPT
Cpp tutorial
PDF
Ps installedsoftware
PPT
Cappuccino @ JSConf 2009
PDF
What's new in iOS9
PDF
Oop in java script
PDF
Functional Programming in PHP
PDF
Real world scala
PPT
Wakanday JS201 Best Practices
PDF
Debugging JavaScript with Chrome
PDF
GCD in Action
PDF
PDF
Distributed work with Gearman
PDF
Monads in javascript
ZIP
Why MacRuby Matters
PDF
Emerging Languages: A Tour of the Horizon
PPT
Lecture05
PPTX
4Developers 2015: Clean JavaScript code - only dream or reality - Sebastian Ł...
Cpp tutorial
Ps installedsoftware
Cappuccino @ JSConf 2009
What's new in iOS9
Oop in java script
Functional Programming in PHP
Real world scala
Wakanday JS201 Best Practices
Debugging JavaScript with Chrome
GCD in Action
Distributed work with Gearman
Monads in javascript
Why MacRuby Matters
Emerging Languages: A Tour of the Horizon
Lecture05
4Developers 2015: Clean JavaScript code - only dream or reality - Sebastian Ł...
Ad

Similar to Why should we use SIMPLE FACTORY pattern even when we have one class only? (20)

ODP
PHP Barcelona 2010 - Architecture and testability
PDF
Best practices for crafting high quality PHP apps - PHP UK 2019
PDF
Getting started with TDD - Confoo 2014
PDF
Save time by applying clean code principles
ODP
From typing the test to testing the type
PDF
Building a Pyramid: Symfony Testing Strategies
PDF
Best practices for crafting high quality PHP apps (Bulgaria 2019)
PDF
Lithium: The Framework for People Who Hate Frameworks
PDF
Best practices for crafting high quality PHP apps (ScotlandPHP 2018)
PDF
Best practices for crafting high quality PHP apps (PHP South Africa 2018)
PDF
Alexander Makarov "Let’s talk about code"
PDF
Beyond Design Principles and Patterns
PDF
Best practices for crafting high quality PHP apps (PHP Yorkshire 2018)
PDF
Effective PHP. Part 1
PPT
Things to consider for testable Code
PDF
Unit and integration Testing
PPT
Design Patterns
PDF
PHP: 4 Design Patterns to Make Better Code
PDF
Finding the Right Testing Tool for the Job
PPT
Getting Started with Test-Driven Development at Midwest PHP 2021
PHP Barcelona 2010 - Architecture and testability
Best practices for crafting high quality PHP apps - PHP UK 2019
Getting started with TDD - Confoo 2014
Save time by applying clean code principles
From typing the test to testing the type
Building a Pyramid: Symfony Testing Strategies
Best practices for crafting high quality PHP apps (Bulgaria 2019)
Lithium: The Framework for People Who Hate Frameworks
Best practices for crafting high quality PHP apps (ScotlandPHP 2018)
Best practices for crafting high quality PHP apps (PHP South Africa 2018)
Alexander Makarov "Let’s talk about code"
Beyond Design Principles and Patterns
Best practices for crafting high quality PHP apps (PHP Yorkshire 2018)
Effective PHP. Part 1
Things to consider for testable Code
Unit and integration Testing
Design Patterns
PHP: 4 Design Patterns to Make Better Code
Finding the Right Testing Tool for the Job
Getting Started with Test-Driven Development at Midwest PHP 2021
Ad

Recently uploaded (20)

PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPTX
history of c programming in notes for students .pptx
PDF
Tally Prime Crack Download New Version 5.1 [2025] (License Key Free
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PPTX
Oracle Fusion HCM Cloud Demo for Beginners
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PPTX
Reimagine Home Health with the Power of Agentic AI​
PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PPTX
AMADEUS TRAVEL AGENT SOFTWARE | AMADEUS TICKETING SYSTEM
PPTX
assetexplorer- product-overview - presentation
PDF
Autodesk AutoCAD Crack Free Download 2025
PDF
Website Design Services for Small Businesses.pdf
PDF
Download FL Studio Crack Latest version 2025 ?
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
iTop VPN 6.5.0 Crack + License Key 2025 (Premium Version)
PDF
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
Complete Guide to Website Development in Malaysia for SMEs
Navsoft: AI-Powered Business Solutions & Custom Software Development
history of c programming in notes for students .pptx
Tally Prime Crack Download New Version 5.1 [2025] (License Key Free
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
Oracle Fusion HCM Cloud Demo for Beginners
Design an Analysis of Algorithms I-SECS-1021-03
Reimagine Home Health with the Power of Agentic AI​
wealthsignaloriginal-com-DS-text-... (1).pdf
AMADEUS TRAVEL AGENT SOFTWARE | AMADEUS TICKETING SYSTEM
assetexplorer- product-overview - presentation
Autodesk AutoCAD Crack Free Download 2025
Website Design Services for Small Businesses.pdf
Download FL Studio Crack Latest version 2025 ?
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Operating system designcfffgfgggggggvggggggggg
iTop VPN 6.5.0 Crack + License Key 2025 (Premium Version)
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
Wondershare Filmora 15 Crack With Activation Key [2025
Complete Guide to Website Development in Malaysia for SMEs

Why should we use SIMPLE FACTORY pattern even when we have one class only?

  • 1. Why should we use SIMPLE FACTORY pattern even when we have one class only? Based on DateTime (PHP) and PHPUnit by Rafal Ksiazek, IT Leader https://github.com/harpcio
  • 2. Real example (or maybe not): Application for an airline company based in Europe Requirements: … User should be able to create a flight route ...
  • 3. Without SF With SF public function createFlightRoute(User $user, $startTime, ...) { $route = new FlightRoute(); $route->setCreateTime(new DateTime()); $route->setStartTime(new DateTime($startTime)); $route->setEndTime(new DateTime($endTime)); $route->setStartPlace($startPlace); $route->setEndPlace($endPlace); $route->setCargo($cargo); $route->setCreatedBy($user); ... return $route; } class DateTimeFactory implements DateTimeFactoryInterface { public function create( $time = 'now', DateTimeZone $timeZone = null ) { return new DateTime($time, $timeZone); } } … public function __construct(..., DateTimeFactoryInterface $dateTimeFactory) { …. $this->dateTimeFactory = $dateTimeFactory; } public function createFlightRoute(User $user, $startTime, ...) { $route = new FlightRoute(); $route->setCreateTime($this->dateTimeFactory->create()); $route->setStartTime($this->dateTimeFactory->create($startTime)); $route->setEndTime($this->dateTimeFactory->create($endTime)); $route->setStartPlace($startPlace); $route->setEndPlace($endPlace); $route->setCargo($cargo); $route->setCreatedBy($user); ... return $route; }
  • 4. There is one thing we can be sure of: CHANGE So be prepared!
  • 5. New client requirement! Move our application to the new powerful dedicated server in US (Detroit) The programmer copies the code and databases, checks that everything works (twice!) … but he forgets about timezones A few hours later, first unhappy customers began to call the company
  • 6. The blocker task! The programmer changes the timezone on Detroit's server to European timezone in one minute! But we got new client requirement! For security, application should be independent of the server's timezone
  • 7. Without SF With SF … somewhere in configuration define('APP_TIME_ZONE', 'Europe/NoExistingCity') … in „n” classes: public function createFlightRoute(User $user, $startTime, ...) { $route = new FlightRoute(); $route->setCreateTime( new DateTime('now', new DateTimeZone(APP_TIME_ZONE)) ); $route->setStartTime( new DateTime($startTime, DateTimeZone(APP_TIME_ZONE)) ); $route->setEndTime( new DateTime($endTime, DateTimeZone(APP_TIME_ZONE)) ); $route->setStartPlace($startPlace); $route->setEndPlace($endPlace); $route->setCargo($cargo); $route->setCreatedBy($user); ... return $route; } … somewhere in configuration define('APP_TIME_ZONE', 'Europe/NoExistingCity') … in only ONE class: class DateTimeFactory implements DateTimeFactoryInterface { public function create($time = 'now', DateTimeZone $timeZone = null) { if (null === $timeZone) { $timeZone = new DateTimeZone(APP_TIME_ZONE); } return new DateTime($time, $timeZone); } }
  • 8. … after hours of discussion and calculation of the cost of the failure, we got: New client requirement! All functionalities based on dates should be fully tested
  • 9. Without SF With SF … in the test class: public function setUp() { $this->testedObject = ... } public function testCreateFlightRoute() { $createTime = new DateTime('now', DateTimeZone(APP_TIME_ZONE)); $result = $this->testedObject->createFlightRoute($user, $startTime, ...); $this->assertSame( $result->getCreateTime()->format('Y-m-d H:i:s'), $createTime->format('Y-m-d H:i:s') ); } But sometimes our tests are FAILED! Someone know why? … in the test class: public function setUp() { $this->testedObject = ... } public function testCreateFlightRoute() { $this->dateTimeFactoryMock = $this->getMock(...) $createTime = new DateTime('now', APP_TIME_ZONE); $this->dateTimeFactoryMock->expects($this->at(0)) ->method('create') ->willReturn($createTime); $result = $this->testedObject->createFlightRoute($user, $startTime, ...); $this->assertSame($result->getCreateTime(), $createTime); } Always PASSED!
  • 10. Without SF With SF Pros: ● We'll build our application „faster”* (initially, anyway) * yes, couple of minutes less per class is really an irrefutable fact Cons: ● Each change will cost us a lot: – time for implementation & bugs fixing – customer confidence – money ● When we'll start writing tests - we'll have to use simple factory – otherwise we will have broken builds from time to time Pros: ● We're saving (days|hours|minutes) of our time, but also our client’s time (bugs) – Do you remember the "n" classes we had to change? – In how many places can we potentially make mistakes that way? How much time will we spend on manual testing of all classes that we've changed? ● We can write tests for our classes in a proper way - we will not have any failed builds ever Cons: ● We need 1-3 minutes to create simply factory class and inject it into our class
  • 11. But what about creating not breakable tests? class DateTimeFactoryMock() implements DataTimeFactoryInterface { public function __construct(array $nowTimes) { $this->nowTimes = $nowTimes; } public function create($time = 'now', DateTimeZone $timeZone = null) { if (null === $timeZone) { $timeZone = new DateTimeZone(APP_TIME_ZONE); } if ('now' === $time) { $time = array_shift($this->nowTimes); } return new DateTime($time, $timeZone); } } ... in test class public function setUp() { $this->nowTime1 = '2012-01-01 12:00:00'; $dateTimeFactory = new DateTimeFactoryMock([$this->nowTime1]); $this->testedObject = new AirRouteManager($dateTimeFactory); } public function testCreateFlightRoute() { $result = $this->testedObject->createFlightRoute($user, $startTime, ...); ... $this->assertSame($result->getCreateTime()->format('Y-m-d H:i:s'), $this->nowTime1); }
  • 12. What about KISS Simple Factory classes are very simple and stupid, but I can obviously come up with an even simpler and stupider class.. class A() { public function doNothing() { // yeah, this method really does nothing! } } ...but I'm afraid, that this class won't do us much good
  • 13. What about YAGNI Yes, YAGNI is about functionalities.. and we'll use this functionality everywhere! Yes! Everywhere, where we want the new instances..
  • 14. Thank you very much for waching!