SlideShare ist ein Scribd-Unternehmen logo
1 von 138
Downloaden Sie, um offline zu lesen
Architecture
in the Small
1 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Hi!
Vinai Kopp
Freelance Developer and Trainer
@VinaiKopp
2 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
My PHP Evolution:
1. Quick Hacks (1999)
2. Typo3 Plugin Developer (2003)
3. Magento Developer (2008)
4. Experienced Magento Developer (2012)
5. Discovering Code Beyond Magento (2014)
3 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
I hope some of the following
will be useful and interesting
to play with for you, too
4 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Some of the many People
who inspired and helped me
‱ Rich Hickey
‱ Robert C. Martin
‱ Martin Fowler
‱ Kent Beck
All brilliant people with a sense of humor!
5 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Disclaimer
The following thoughts are all mine, but influenced by
reading these great peoples work.
If I get something wrong, it is all my fault.
I might change my mind about something at any time.
6 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Topics
‱ Extraction & Encapsulation
‱ Managing State with Immutable Objects
‱ The Value of Validity
‱ Immutable Variables
‱ Reasoning about Code with Idempotence
7 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Extraction
&
Encapsulation
8 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Extraction?
WTF?
9 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
A subset of
Refactoring
10 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
„Refactoring is the process of changing a software
system in such a way that it does not alter the external
behavior of the code yet improves its internal
structure“
-- Martin Fowler, Refactoring (Addison-Wesley)
11 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
12 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
The usual purpose of refactoring:
Get rid of smelly code
13 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
But in case of extraction
It can be more
14 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Simplicity
vs.
Amount of code
15 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Simplicity
Can make things
visible
that where hidden in the code
16 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Extract Method Example - Before
// MagentoCatalogModelProduct
protected function convertToMediaGalleryInterface(array $mediaGallery)
{
$entries = [];
foreach ($mediaGallery as $image) {
$entry = $this
->mediaGalleryEntryConverterPool
->getConverterByMediaType($image['media_type'])
->convertTo($this, $image);
$entries[] = $entry;
}
return $entries;
}
17 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Extract Method Example - After (1/2)
// MagentoCatalogModelProduct
protected function convertToMediaGalleryInterface(array $mediaGallery)
{
$entries = [];
foreach ($mediaGallery as $image) {
$entries[] = $this->convertImageToMediaGalleryEntry($image);
}
return $entries;
}
private function convertImageToMediaGalleryEntry(array $image)
{
$converter = $this->mediaGalleryEntryConverterPool
->getConverterByMediaType($image['media_type']);
return $converter->convertTo($this, $image);
}
18 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Extract Method Example - After (2/2)
// MagentoCatalogModelProduct
protected function convertToMediaGalleryInterface(array $mediaGallery)
{
$entries = [];
foreach ($mediaGallery as $image) {
$entries[] = $this->mediaGalleryEntryConverterPool
->convertImageToMediaGalleryEntry($image, $this);
}
return $entries;
}
// MagentoCatalogModelProductAttributeBackendMediaEntryConverterPool
public function convertImageToMediaGalleryEntry(array $image, Product $product)
{
$converter = $this->getConverterByMediaType($image['media_type']);
return $converter->convertTo($product, $image);
}
19 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Encapsulation
„In general, encapsulation is the inclusion of one thing
within another thing so that the included thing is not
apparent.“
-- TechTarget SearchNetworking
20 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Encapsulation
„Other objects ... use the object without having to be
concerned with how the object accomplishes it.“
-- TechTarget SearchNetworking
21 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Tell, don't ask!
22 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Extraction enables us to properly encapsulate
functionality.
23 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Proposition:
It is good to write code that is simple to extract.
24 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Topics
‱ Extraction & Encapsulation
‱ Managing State with Immutable Objects
‱ The Value of Validity
‱ Immutable Variables
‱ Reasoning about Code with Idempotence
25 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Managing State
with Immutable
Objects
26 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Immutawhat?
27 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
„In object-oriented and functional programming, an
immutable object is an object whose state cannot be
modified after it is created.“
-- Wikipedia, Immutable object
28 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Yes, but... why?
29 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
I've read it helps avoid a whole class of bugs.
So, what are they?
30 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Reasonability
31 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Reading ➡ Understanding
32 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Understanding ➡ Knowing
‱ Is it correct
or
‱ Is it incorrect
33 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
When objects change in distant code, it becomes more
complex to track what changed where and why.
34 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Immutability helps to avoid
temporal coupling
35 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
For Example:
// MagentoBraintreeModelPaymentMethod::partialCapture()
$this->conïŹg->initEnvironment($payment->getOrder()->getStoreId());
36 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Temporal Coupling:
// MagentoBraintreeModelPaymentMethod::partialCapture()
$this->conïŹg->initEnvironment($payment->getOrder()->getStoreId());
What state does the config start out in before it is
initialized?
37 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Temporal Coupling:
// MagentoBraintreeModelPaymentMethod::partialCapture()
$this->conïŹg->initEnvironment($payment->getOrder()->getStoreId());
What happens if the config is initialized twice with
different store ids?
38 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Temporal Coupling:
// MagentoBraintreeModelPaymentMethod::partialCapture()
$this->conïŹg->initEnvironment($payment->getOrder()->getStoreId());
What happens if another method is called before this
one and the other one also relies on the config
environment being initialized?
39 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Temporal Coupling:
// MagentoBraintreeModelPaymentMethod::partialCapture()
$this->conïŹg->initEnvironment($payment->getOrder()->getStoreId());
What happens if the call to initEnvironment is missed?
40 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Temporal Coupling:
// MagentoBraintreeModelPaymentMethod::partialCapture()
$this->conïŹg->initEnvironment($payment->getOrder()->getStoreId());
Extracting methods is tricky because the extracted part
might rely on a different method being called first.
This might not be apparent.
41 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Temporal Coupling:
// MagentoBraintreeModelPaymentMethod::partialCapture()
$this->conïŹg->initEnvironment($payment->getOrder()->getStoreId());
What happens if another object has a reference to the
same config instance, but it doesn't know about or
expect the config change?
42 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Temporal Coupling:
// MagentoBraintreeModelPaymentMethod::partialCapture()
$this->conïŹg->initEnvironment($payment->getOrder()->getStoreId());
What happens if a response of the payment instance is
cached and then the config environment is changed?
43 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
External
Initialization methods
and
Setters
add complexity
44 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
External immutability
&
Internal immutability
45 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Internal mutability allows for memoization
46 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Memoization :
„An optimization technique to speed up expensive
method calls by storing the result after the first call and
returning the cached result if the same inputs occur
again.“
47 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Memoization Example
public function getAltitudeAvg(Location $loc, Date $date)
{
$coords = (string) $loc->getCoords();
$dateStr = (string) $date;
if (! @$this->memoizedResults[$coords][$dateStr]) {
$avgAltitude = $this->doExpensiveCalculation($loc, $date);
$this->memoizedResults[$coords][$dateStr] = $avgAltitude;
}
return $this->memoizedResults[$coords][$dateStr];
}
48 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Anyway...
Memoization is a lot simpler to do with
externally immutable objects
since nothing can invalidate the result.
49 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Testing code which uses
immutable objects is simpler
50 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Test Double: Mutable Object
$initWasCalled = false;
$mockConïŹg = $this->getMock(MagentoBraintreeModelConïŹg, [], [], '', false);
$mockConïŹg->method('initEnvironment')
->willReturnCallback(function () use (&$initWasCalled) {
$initWasCalled = true;
});
$mockConïŹg->method('canUseForCountry')
->willReturnCallback(function ($country) use (&$initWasCalled) {
return $initWasCalled ? false : true;
});
51 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Yuck!
52 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Incomplete Test Double:
Mutable Object
$initializedConïŹgMock = $this->getMock(MagentoBraintreeModelConïŹg, [], [], '', false);
$initializedConïŹgMock->method('canUseForCountry')->willReturn(true);
Easy to miss calling initEnvironment in the system
under test!
53 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Test Double: Immutable Object
$conïŹgMock = $this->getMock(MagentoBraintreeModelConïŹg, [], [], '', false);
$conïŹgMock->method('canUseForCountry')->willReturn(true);
54 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Simpler to cache
No need to worry that an object changes after it is
written to cache.
55 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Example:
Magento EE PageCache
<controller_front_send_response_before>
<observers>
<enterprise_pagecache>
<class>enterprise_pagecache/observer</class>
<method>cacheResponse</method>
</enterprise_pagecache>
</observers>
</controller_front_send_response_before>
56 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Example:
Magento EE PageCache
Events after cache write:
‱ controller_front_send_response_before
(in a later Observer)
‱ controller_front_send_response_after
‱ http_response_send_before
57 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Once valid
always valid
Can something be „half valid“?
58 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Example: invalidation of a mutable object
$product = $productCollection->getFirstItem();
$product->getPrice(); // 24.99
$product->getSpecialPrice(); // 19.99
$product->setPrice(11.95);
$product->setSpecialPrice(10.95);
$product->getFinalPrice() // 19.99
59 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
So how do the values get into an immutable object?
60 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Constructor Injection
61 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
__construct()
$request = new HttpRequest(
HttpRequest::METHOD_GET,
HttpUrl::fromString('http://example.com/lookie/here'),
HttpHeaders::fromArray($httpHeaders),
HttpRequestBody::fromString($httpRequestBodyString)
);
62 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Named constructor
$request = HttpRequest::fromGlobalState();
63 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Example 1: named constructor
public static function fromGlobalState($requestBody = '')
{
$method = $_SERVER['REQUEST_METHOD'];
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']) ?
'https' :
'http';
$path = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$url = $protocol . '://' . $path;
$headers = self::getGlobalRequestHeaders();
return static::fromScalars($method, $url, $headers, $requestBody);
}
64 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Example 2: named constructor
public static function fromScalars(
$methodString,
$urlString,
$headersArray,
$bodyString
) {
$url = HttpUrl::fromString($urlString);
$headers = HttpHeaders::fromArray($headersArray);
$body = HttpRequestBody::fromString($bodyString);
return new self($methodString, $url, $headers, $body);
}
65 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
But IRL
things change
66 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Modeling change with
immutable objects
Change is introduced by creating a new instance.
67 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Looks like mutation, but it ain't
$today = new DateTimeImmutable();
echo $today->format('Y-m-d H:i:s'); // 2015-10-29 21:32:06
$day = DateInterval::createFromDateString('24 hours');
$tomorrow = $today->add($day);
echo $today->format('Y-m-d H:i:s'); // 2015-10-29 21:32:06
echo $tomorrow->format('Y-m-d H:i:s');// 2015-10-30 21:32:06
68 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Contraindications
69 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Does immutability make code more
complex
or
simple?
70 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
A thing that changes over time.
$room = new ConferenceRoom(
$location,
$event,
$attendees
)
71 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Is it a new conference room just because the number of
people change?
72 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
A mutable conference room model:
$nPeople = $room->countPeople();
$room->addPerson($attendee);
$room->countPeople() === $nPeople + 1;
73 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
A immutable conference room model:
$nPeople = $room->countPeople();
$updatedRoom = $room->addPerson($attendee);
$room->countPeople() === $nPeople;
$updatedRoom->countPeople() === $nPeople + 1;
74 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Temporal modeling
An instance represents the object
at one moment in time.
75 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Temporal modeling
(Immutable object at a moment in time)
(Immutable object at a moment in time)
(Immutable object at a moment in time)
(Immutable object at a moment in time)
...
All the same Entity that changes over time.
76 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Temporal modeling
Keeps History !
Not a natural way to do OOP, adds complexity !
Unaccustomed way to think ! "
77 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Bottom Line
If you don't have to model changes over time, using
immutability will probably make your code simpler.
If you do have to worry about changes over time...
it depends.
78 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Topics
‱ Extraction & Encapsulation
‱ Managing State with Immutable Objects
‱ The Value of Validity
‱ Immutable Variables
‱ Reasoning about Code with Idempotence
79 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
The Value of
Validity
80 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Enforce object validity at instantiation.
81 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Validation at Instantiation
‱ __construct()
‱ Named constructor (aka Factory Method)
‱ Builder or Factory
82 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Constructor validation
The safest place to enforce validity
83 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Example Constructor Validation
public function __construct($amount)
{
if (!is_int($amount)) {
$type = gettype($amount);
$msg = sprintf('Can not create price from "%s"', $type);
throw new InvalidAmountTypeException($msg);
}
$this->amount = $amount;
}
84 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
When it gets more complex...
85 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Example Delegation of Validation
// ProductAttributeListBuilder
public static function fromArray(array $attributesArray)
{
$attributes = array_map(function (array $attributeArray) {
return ProductAttribute::fromArray($attributeArray);
}, $attributesArray);
return new self(...$attributes);
}
public function __construct(ProductAttribute ...$attributes)
{
$this->validateAllAttributesHaveCompatibleContextData(...$attributes);
$this->attributes = $attributes;
}
86 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Each thing is a class
Each object validates it's data
87 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Plug: Value Objects
Introduction slides on Value Objects
by Tim Bezhashvyly
http://vin.ai/tims_value_objects
88 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
The cost of validity
Classes require time to write, test and maintain.
‱ Each thing is a new class
‱ Lots of code
89 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
What about scalars?
‱ string
‱ int
‱ bool
‱ float
‱ null
‱ arrays of scalars
90 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Code Smell:
Primitives Obsession
„Primitives Obsession is using primitive data types to
represent domain ideas.“
91 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Primitives Obsession
No Type Safety
(until PHP 7)
Tests help
92 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Primitives Obsession
Easy to end up with Code Duplication
93 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Primitives Obsession
Magic values
„I knew at once what process(1.34, true) meant!“
-- Noone, ever
Class names have documentary value
94 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Primitives Obsession
No built-in validation
Tests help (again)
95 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Benefits of scalar types
96 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Benefits of scalar types
They are immutable
97 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Benefits of scalar types
They are easily created
98 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Benefits of scalar types
They are comparable
99 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Benefits of scalar types
Serializable
They work over the wire
100 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Benefits of scalar types
Completely upgrade safe
101 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Benefits of scalar types
They are fast
102 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Benefits of scalar types
They are language independent
103 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Scalars
vs.
Value Objects
104 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Scalars make great
boundary interfaces
105 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Scalar Boundary Interfaces
‱ Web API
‱ Components API
‱ Message Queue Payload
106 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Scalar Boundary Interfaces
‱ Less interface dependencies
‱ But implicit coupling to data format
107 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Topics
‱ Extraction & Encapsulation
‱ Managing State with Immutable Objects
‱ The Value of Validity
‱ Immutable Variables
‱ Reasoning about Code with Idempotence
108 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Immutable Variables
109 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
In PHP?
No
110 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
But we can treat variables as immutable.
111 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Example 1: reusing local variables
public function testTwoRequestsAddTwoMessages()
{
$request = $this->createProductUpdateRequest();
$app = new WebFront($request, $this->testFactory);
$app->runWithoutSendingResponse();
$request = $this->createStockUpdateRequest();
$app = new WebFront($request, $this->testFactory);
$app->runWithoutSendingResponse();
$queue = $this->testFactory->createQueue();
$this->assertCount(2, $queue);
}
// Multiple assignments to $request and $app
112 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
What is the problem?
‱ Messy to move or extract
‱ Complex to reason about
113 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Example 1: treating local variables as immutable
public function testTwoRequestsAddTwoMessages()
{
$productUpdateRequest = $this->createProductUpdateRequest();
$ïŹrstApp = new WebFront($productUpdateRequest, $this->testFactory);
$ïŹrstApp->runWithoutSendingResponse();
$stockUpdateRequest = $this->createStockUpdateRequest();
$secondApp = new WebFront($stockUpdateRequest, $this->testFactory);
$secondApp->runWithoutSendingResponse();
$queue = $this->testFactory->createQueue();
$this->assertCount(2, $queue);
}
114 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Example 2: local variable mutation in a loop
// MagentoCatalogModelProduct
protected function convertToMediaGalleryInterface(array $mediaGallery)
{
$entries = [];
foreach ($mediaGallery as $image) {
$entries[] = $this->mediaGalleryEntryConverterPool
->convertImageToMediaGalleryEntry($image, $this);
}
return $entries;
}
// Multiple assignments to $image, mutation of $entries
115 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Example 2: map/reduce helps avoiding local variable
mutation
// MagentoCatalogModelProduct
protected function convertToMediaGalleryInterface(array $mediaGallery)
{
return array_map(
function ($image) {
$this->mediaGalleryEntryConverterPool
->convertImageToMediaGalleryEntry($image, $this);
},
$mediaGallery
);
}
116 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Immutable Variables
++Reasonability
117 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Immutable Variables
Less bugs
118 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Immutable Variables
Simple to refactor
119 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Immutable Variables
My new friends:
‱ Closure
‱ array_map()
‱ array_reduce()
‱ array_merge()
‱ array_filter()
‱ recursion
‱ ...
120 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Topics
‱ Extraction & Encapsulation
‱ Managing State with Immutable Objects
‱ The Value of Validity
‱ Immutable Variables
‱ Reasoning about Code with Idempotence
121 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Reasoning about
Code with
Idempotence
122 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Another of those words...
123 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Idempotence
„In computer science, the term idempotent is used ... to
describe an operation that will produce the same
results if executed once or multiple times.“
-- Wikipedia, Idempotence, Computer Science
124 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
What it ain't
Example 1
class Logger
{
public function log($level, $message)
{
$f = fopen($this->ïŹle . '-' . $level, 'a');
ïŹ‚ock($f, LOCK_EX);
fwrite($f, message);
ïŹ‚ock($f, LOCK_UN);
fclose($f);
}
}
// repeated calls add additional records
125 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Idempotent logger
Example 1
class Logger
{
public function log($level, $message)
{
$f = fopen($this->ïŹle . '-' . $level, 'a');
ïŹ‚ock($f, LOCK_EX);
if ($this->getLastLineFromFile() !== $message) {
fwrite($f, message);
}
ïŹ‚ock($f, LOCK_UN);
fclose($f);
}
}
// repeated calls add NO additional records
126 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
What it ain't
Example 2
protected function validateIsFoo($object)
{
if (! $object instanceof Foo) {
echo "$object is not an instance of Foon";
return false;
}
return true;
}
// repeated calls may produce repeated output
127 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Idempotent validateIsFoo
Example 2
protected function validateIsFoo($object)
{
return $object instanceof Foo;
}
// no output
128 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Pure Functions
All pure functions are idempotent
129 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Pure Functions
No side effects
130 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Pure Functions
Rely only on input arguments
131 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Pure Functions
No dependency on global state such as
‱ $_SERVER, $_SESSION
‱ getcwd()
‱ file_exists()
‱ Mage::getIsDeveloperMode()
132 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Pure Functions
For the same input they always return the same output
133 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
And my point is?
134 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Idempotent Functions are
Simpler to reuse
Simpler to compose
Pure Functions are
Simpler to refactor
Simpler to change
Simpler to reason about
135 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
It pays to focus on the
dependencies of every
method
OOP is all about dependency management
136 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
I'm still learning
But so far results are very encouraging.
I'm happy for every tool that helps to reduce complexity
137 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
Thanks for your attention!
Please,
Ask questions, and
I'm eager to hear your thoughts and comments!
138 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015

Weitere Àhnliche Inhalte

Ähnlich wie Architecture in-the-small-slides

To Microservices and Beyond
To Microservices and BeyondTo Microservices and Beyond
To Microservices and BeyondMatt Stine
 
Vinai Kopp - How i develop M2 modules
Vinai Kopp - How i develop M2 modules Vinai Kopp - How i develop M2 modules
Vinai Kopp - How i develop M2 modules Meet Magento Italy
 
Arguments in favor of a progressive software rewrite
Arguments in favor of a progressive software rewrite  Arguments in favor of a progressive software rewrite
Arguments in favor of a progressive software rewrite Sylvain Leroy
 
Arguments in favor of a progressive software rewrite
Arguments in favor of a progressive software rewrite  Arguments in favor of a progressive software rewrite
Arguments in favor of a progressive software rewrite Sylvain Leroy
 
Pivotal microservices spring_pcf_skillsmatter.pptx
Pivotal microservices spring_pcf_skillsmatter.pptxPivotal microservices spring_pcf_skillsmatter.pptx
Pivotal microservices spring_pcf_skillsmatter.pptxSufyaan Kazi
 
Hyvä from a developer perspective
Hyvä from a developer perspectiveHyvä from a developer perspective
Hyvä from a developer perspectivevinaikopp
 
Writing Testable Code (for Magento 1 and 2)
Writing Testable Code (for Magento 1 and 2)Writing Testable Code (for Magento 1 and 2)
Writing Testable Code (for Magento 1 and 2)vinaikopp
 
Becoming Certified - MageTitansMCR 2018
Becoming Certified - MageTitansMCR 2018Becoming Certified - MageTitansMCR 2018
Becoming Certified - MageTitansMCR 2018vinaikopp
 
Building Distributed Systems with Netflix OSS and Spring Cloud
Building Distributed Systems with Netflix OSS and Spring CloudBuilding Distributed Systems with Netflix OSS and Spring Cloud
Building Distributed Systems with Netflix OSS and Spring CloudMatt Stine
 
How Facebook's Technologies can define the future of VistA and Health IT
How Facebook's Technologies can define the future of VistA and Health ITHow Facebook's Technologies can define the future of VistA and Health IT
How Facebook's Technologies can define the future of VistA and Health ITRob Tweed
 
Awesome Architectures in Magento 2.3
Awesome Architectures in Magento 2.3Awesome Architectures in Magento 2.3
Awesome Architectures in Magento 2.3Riccardo Tempesta
 
IT Financial Management at GameStop
IT Financial Management at GameStopIT Financial Management at GameStop
IT Financial Management at GameStopCA Technologies
 
The Cloud Native Journey with Simon Elisha
The Cloud Native Journey with Simon ElishaThe Cloud Native Journey with Simon Elisha
The Cloud Native Journey with Simon ElishaChloe Jackson
 
The Cloud Native Journey
The Cloud Native JourneyThe Cloud Native Journey
The Cloud Native JourneyVMware Tanzu
 
Vinai Kopp - FPC Hole punching in Magento 2
Vinai Kopp - FPC Hole punching in Magento 2Vinai Kopp - FPC Hole punching in Magento 2
Vinai Kopp - FPC Hole punching in Magento 2Meet Magento Italy
 
From LazyCoffee to Appstore - The Key stages of app development
From LazyCoffee to Appstore - The Key stages of app developmentFrom LazyCoffee to Appstore - The Key stages of app development
From LazyCoffee to Appstore - The Key stages of app developmentScott Roberts
 
Zero-Copy Compositing in WebKitGTK+ for GUADEC 2015 (GUADEC 2015)
Zero-Copy Compositing in WebKitGTK+ for GUADEC 2015 (GUADEC 2015)Zero-Copy Compositing in WebKitGTK+ for GUADEC 2015 (GUADEC 2015)
Zero-Copy Compositing in WebKitGTK+ for GUADEC 2015 (GUADEC 2015)Igalia
 
Deploying CA Applications in the Cloud: Automated Blueprints for your Agile I...
Deploying CA Applications in the Cloud: Automated Blueprints for your Agile I...Deploying CA Applications in the Cloud: Automated Blueprints for your Agile I...
Deploying CA Applications in the Cloud: Automated Blueprints for your Agile I...CA Technologies
 
James Zetlen - PWA Studio Integration
With You
James Zetlen - PWA Studio Integration
With YouJames Zetlen - PWA Studio Integration
With You
James Zetlen - PWA Studio Integration
With YouMeet Magento Italy
 

Ähnlich wie Architecture in-the-small-slides (20)

To Microservices and Beyond
To Microservices and BeyondTo Microservices and Beyond
To Microservices and Beyond
 
Vinai Kopp - How i develop M2 modules
Vinai Kopp - How i develop M2 modules Vinai Kopp - How i develop M2 modules
Vinai Kopp - How i develop M2 modules
 
Arguments in favor of a progressive software rewrite
Arguments in favor of a progressive software rewrite  Arguments in favor of a progressive software rewrite
Arguments in favor of a progressive software rewrite
 
Arguments in favor of a progressive software rewrite
Arguments in favor of a progressive software rewrite  Arguments in favor of a progressive software rewrite
Arguments in favor of a progressive software rewrite
 
Pivotal microservices spring_pcf_skillsmatter.pptx
Pivotal microservices spring_pcf_skillsmatter.pptxPivotal microservices spring_pcf_skillsmatter.pptx
Pivotal microservices spring_pcf_skillsmatter.pptx
 
Hyvä from a developer perspective
Hyvä from a developer perspectiveHyvä from a developer perspective
Hyvä from a developer perspective
 
Writing Testable Code (for Magento 1 and 2)
Writing Testable Code (for Magento 1 and 2)Writing Testable Code (for Magento 1 and 2)
Writing Testable Code (for Magento 1 and 2)
 
Becoming Certified - MageTitansMCR 2018
Becoming Certified - MageTitansMCR 2018Becoming Certified - MageTitansMCR 2018
Becoming Certified - MageTitansMCR 2018
 
Building Distributed Systems with Netflix OSS and Spring Cloud
Building Distributed Systems with Netflix OSS and Spring CloudBuilding Distributed Systems with Netflix OSS and Spring Cloud
Building Distributed Systems with Netflix OSS and Spring Cloud
 
How Facebook's Technologies can define the future of VistA and Health IT
How Facebook's Technologies can define the future of VistA and Health ITHow Facebook's Technologies can define the future of VistA and Health IT
How Facebook's Technologies can define the future of VistA and Health IT
 
Awesome Architectures in Magento 2.3
Awesome Architectures in Magento 2.3Awesome Architectures in Magento 2.3
Awesome Architectures in Magento 2.3
 
IT Financial Management at GameStop
IT Financial Management at GameStopIT Financial Management at GameStop
IT Financial Management at GameStop
 
The Cloud Native Journey with Simon Elisha
The Cloud Native Journey with Simon ElishaThe Cloud Native Journey with Simon Elisha
The Cloud Native Journey with Simon Elisha
 
The Cloud Native Journey
The Cloud Native JourneyThe Cloud Native Journey
The Cloud Native Journey
 
Vinai Kopp - FPC Hole punching in Magento 2
Vinai Kopp - FPC Hole punching in Magento 2Vinai Kopp - FPC Hole punching in Magento 2
Vinai Kopp - FPC Hole punching in Magento 2
 
From LazyCoffee to Appstore - The Key stages of app development
From LazyCoffee to Appstore - The Key stages of app developmentFrom LazyCoffee to Appstore - The Key stages of app development
From LazyCoffee to Appstore - The Key stages of app development
 
Zero-Copy Compositing in WebKitGTK+ for GUADEC 2015 (GUADEC 2015)
Zero-Copy Compositing in WebKitGTK+ for GUADEC 2015 (GUADEC 2015)Zero-Copy Compositing in WebKitGTK+ for GUADEC 2015 (GUADEC 2015)
Zero-Copy Compositing in WebKitGTK+ for GUADEC 2015 (GUADEC 2015)
 
What does it cost to develop an app
What does it cost to develop an app What does it cost to develop an app
What does it cost to develop an app
 
Deploying CA Applications in the Cloud: Automated Blueprints for your Agile I...
Deploying CA Applications in the Cloud: Automated Blueprints for your Agile I...Deploying CA Applications in the Cloud: Automated Blueprints for your Agile I...
Deploying CA Applications in the Cloud: Automated Blueprints for your Agile I...
 
James Zetlen - PWA Studio Integration
With You
James Zetlen - PWA Studio Integration
With YouJames Zetlen - PWA Studio Integration
With You
James Zetlen - PWA Studio Integration
With You
 

Mehr von vinaikopp

Building Mage-OS - MageTitans 2023
Building Mage-OS - MageTitans 2023Building Mage-OS - MageTitans 2023
Building Mage-OS - MageTitans 2023vinaikopp
 
HyvÀ: Compatibility Modules
HyvÀ: Compatibility ModulesHyvÀ: Compatibility Modules
HyvÀ: Compatibility Modulesvinaikopp
 
Property Based Testing in PHP
Property Based Testing in PHPProperty Based Testing in PHP
Property Based Testing in PHPvinaikopp
 
Property based testing - MageTestFest 2019
Property based testing - MageTestFest 2019Property based testing - MageTestFest 2019
Property based testing - MageTestFest 2019vinaikopp
 
SOS UiComponents
SOS UiComponentsSOS UiComponents
SOS UiComponentsvinaikopp
 
ClojureScript in Magento 2 - PHPUGMRN
ClojureScript in Magento 2 - PHPUGMRNClojureScript in Magento 2 - PHPUGMRN
ClojureScript in Magento 2 - PHPUGMRNvinaikopp
 
Magento 2 TDD Code Kata
Magento 2 TDD Code KataMagento 2 TDD Code Kata
Magento 2 TDD Code Katavinaikopp
 
Magento 2 TDD Code Kata Intro
Magento 2 TDD Code Kata IntroMagento 2 TDD Code Kata Intro
Magento 2 TDD Code Kata Introvinaikopp
 
Testing Magento 2
Testing Magento 2Testing Magento 2
Testing Magento 2vinaikopp
 
ClojureScript in Magento 2 - MageTitansMCR 2017
ClojureScript in Magento 2 - MageTitansMCR 2017ClojureScript in Magento 2 - MageTitansMCR 2017
ClojureScript in Magento 2 - MageTitansMCR 2017vinaikopp
 
Lizards & Pumpkins Catalog Replacement at mm17de
Lizards & Pumpkins Catalog Replacement at mm17deLizards & Pumpkins Catalog Replacement at mm17de
Lizards & Pumpkins Catalog Replacement at mm17devinaikopp
 
Stories from the other side
Stories from the other sideStories from the other side
Stories from the other sidevinaikopp
 
Writing Testable Code (for Magento 1 and 2) 2016 Romaina
Writing Testable Code (for Magento 1 and 2)  2016 RomainaWriting Testable Code (for Magento 1 and 2)  2016 Romaina
Writing Testable Code (for Magento 1 and 2) 2016 Romainavinaikopp
 
Writing testable Code (MageTitans Mini 2016)
Writing testable Code (MageTitans Mini 2016)Writing testable Code (MageTitans Mini 2016)
Writing testable Code (MageTitans Mini 2016)vinaikopp
 
Getting your Hands Dirty Testing Magento 2 (at London Meetup)
Getting your Hands Dirty Testing Magento 2 (at London Meetup)Getting your Hands Dirty Testing Magento 2 (at London Meetup)
Getting your Hands Dirty Testing Magento 2 (at London Meetup)vinaikopp
 
Getting your hands dirty testing Magento 2 (at MageTitansIT)
Getting your hands dirty testing Magento 2 (at MageTitansIT)Getting your hands dirty testing Magento 2 (at MageTitansIT)
Getting your hands dirty testing Magento 2 (at MageTitansIT)vinaikopp
 

Mehr von vinaikopp (16)

Building Mage-OS - MageTitans 2023
Building Mage-OS - MageTitans 2023Building Mage-OS - MageTitans 2023
Building Mage-OS - MageTitans 2023
 
HyvÀ: Compatibility Modules
HyvÀ: Compatibility ModulesHyvÀ: Compatibility Modules
HyvÀ: Compatibility Modules
 
Property Based Testing in PHP
Property Based Testing in PHPProperty Based Testing in PHP
Property Based Testing in PHP
 
Property based testing - MageTestFest 2019
Property based testing - MageTestFest 2019Property based testing - MageTestFest 2019
Property based testing - MageTestFest 2019
 
SOS UiComponents
SOS UiComponentsSOS UiComponents
SOS UiComponents
 
ClojureScript in Magento 2 - PHPUGMRN
ClojureScript in Magento 2 - PHPUGMRNClojureScript in Magento 2 - PHPUGMRN
ClojureScript in Magento 2 - PHPUGMRN
 
Magento 2 TDD Code Kata
Magento 2 TDD Code KataMagento 2 TDD Code Kata
Magento 2 TDD Code Kata
 
Magento 2 TDD Code Kata Intro
Magento 2 TDD Code Kata IntroMagento 2 TDD Code Kata Intro
Magento 2 TDD Code Kata Intro
 
Testing Magento 2
Testing Magento 2Testing Magento 2
Testing Magento 2
 
ClojureScript in Magento 2 - MageTitansMCR 2017
ClojureScript in Magento 2 - MageTitansMCR 2017ClojureScript in Magento 2 - MageTitansMCR 2017
ClojureScript in Magento 2 - MageTitansMCR 2017
 
Lizards & Pumpkins Catalog Replacement at mm17de
Lizards & Pumpkins Catalog Replacement at mm17deLizards & Pumpkins Catalog Replacement at mm17de
Lizards & Pumpkins Catalog Replacement at mm17de
 
Stories from the other side
Stories from the other sideStories from the other side
Stories from the other side
 
Writing Testable Code (for Magento 1 and 2) 2016 Romaina
Writing Testable Code (for Magento 1 and 2)  2016 RomainaWriting Testable Code (for Magento 1 and 2)  2016 Romaina
Writing Testable Code (for Magento 1 and 2) 2016 Romaina
 
Writing testable Code (MageTitans Mini 2016)
Writing testable Code (MageTitans Mini 2016)Writing testable Code (MageTitans Mini 2016)
Writing testable Code (MageTitans Mini 2016)
 
Getting your Hands Dirty Testing Magento 2 (at London Meetup)
Getting your Hands Dirty Testing Magento 2 (at London Meetup)Getting your Hands Dirty Testing Magento 2 (at London Meetup)
Getting your Hands Dirty Testing Magento 2 (at London Meetup)
 
Getting your hands dirty testing Magento 2 (at MageTitansIT)
Getting your hands dirty testing Magento 2 (at MageTitansIT)Getting your hands dirty testing Magento 2 (at MageTitansIT)
Getting your hands dirty testing Magento 2 (at MageTitansIT)
 

KĂŒrzlich hochgeladen

What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
Advantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessAdvantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessEnvertis Software Solutions
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfStefano Stabellini
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Hr365.us smith
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Mater
 
ćŠžç†ć­ŠäœèŻ(UQæ–‡ć‡­èŻäčŠ)æ˜†ćŁ«ć…°ć€§ć­ŠæŻ•äžšèŻæˆç»©ć•ćŽŸç‰ˆäž€æšĄäž€æ ·
ćŠžç†ć­ŠäœèŻ(UQæ–‡ć‡­èŻäčŠ)æ˜†ćŁ«ć…°ć€§ć­ŠæŻ•äžšèŻæˆç»©ć•ćŽŸç‰ˆäž€æšĄäž€æ ·ćŠžç†ć­ŠäœèŻ(UQæ–‡ć‡­èŻäčŠ)æ˜†ćŁ«ć…°ć€§ć­ŠæŻ•äžšèŻæˆç»©ć•ćŽŸç‰ˆäž€æšĄäž€æ ·
ćŠžç†ć­ŠäœèŻ(UQæ–‡ć‡­èŻäčŠ)æ˜†ćŁ«ć…°ć€§ć­ŠæŻ•äžšèŻæˆç»©ć•ćŽŸç‰ˆäž€æšĄäž€æ ·umasea
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commercemanigoyal112
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 

KĂŒrzlich hochgeladen (20)

What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
Advantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessAdvantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your Business
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdf
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)
 
ćŠžç†ć­ŠäœèŻ(UQæ–‡ć‡­èŻäčŠ)æ˜†ćŁ«ć…°ć€§ć­ŠæŻ•äžšèŻæˆç»©ć•ćŽŸç‰ˆäž€æšĄäž€æ ·
ćŠžç†ć­ŠäœèŻ(UQæ–‡ć‡­èŻäčŠ)æ˜†ćŁ«ć…°ć€§ć­ŠæŻ•äžšèŻæˆç»©ć•ćŽŸç‰ˆäž€æšĄäž€æ ·ćŠžç†ć­ŠäœèŻ(UQæ–‡ć‡­èŻäčŠ)æ˜†ćŁ«ć…°ć€§ć­ŠæŻ•äžšèŻæˆç»©ć•ćŽŸç‰ˆäž€æšĄäž€æ ·
ćŠžç†ć­ŠäœèŻ(UQæ–‡ć‡­èŻäčŠ)æ˜†ćŁ«ć…°ć€§ć­ŠæŻ•äžšèŻæˆç»©ć•ćŽŸç‰ˆäž€æšĄäž€æ ·
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commerce
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 

Architecture in-the-small-slides

  • 1. Architecture in the Small 1 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 2. Hi! Vinai Kopp Freelance Developer and Trainer @VinaiKopp 2 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 3. My PHP Evolution: 1. Quick Hacks (1999) 2. Typo3 Plugin Developer (2003) 3. Magento Developer (2008) 4. Experienced Magento Developer (2012) 5. Discovering Code Beyond Magento (2014) 3 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 4. I hope some of the following will be useful and interesting to play with for you, too 4 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 5. Some of the many People who inspired and helped me ‱ Rich Hickey ‱ Robert C. Martin ‱ Martin Fowler ‱ Kent Beck All brilliant people with a sense of humor! 5 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 6. Disclaimer The following thoughts are all mine, but influenced by reading these great peoples work. If I get something wrong, it is all my fault. I might change my mind about something at any time. 6 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 7. Topics ‱ Extraction & Encapsulation ‱ Managing State with Immutable Objects ‱ The Value of Validity ‱ Immutable Variables ‱ Reasoning about Code with Idempotence 7 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 8. Extraction & Encapsulation 8 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 9. Extraction? WTF? 9 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 10. A subset of Refactoring 10 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 11. „Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure“ -- Martin Fowler, Refactoring (Addison-Wesley) 11 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 12. 12 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 13. The usual purpose of refactoring: Get rid of smelly code 13 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 14. But in case of extraction It can be more 14 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 15. Simplicity vs. Amount of code 15 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 16. Simplicity Can make things visible that where hidden in the code 16 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 17. Extract Method Example - Before // MagentoCatalogModelProduct protected function convertToMediaGalleryInterface(array $mediaGallery) { $entries = []; foreach ($mediaGallery as $image) { $entry = $this ->mediaGalleryEntryConverterPool ->getConverterByMediaType($image['media_type']) ->convertTo($this, $image); $entries[] = $entry; } return $entries; } 17 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 18. Extract Method Example - After (1/2) // MagentoCatalogModelProduct protected function convertToMediaGalleryInterface(array $mediaGallery) { $entries = []; foreach ($mediaGallery as $image) { $entries[] = $this->convertImageToMediaGalleryEntry($image); } return $entries; } private function convertImageToMediaGalleryEntry(array $image) { $converter = $this->mediaGalleryEntryConverterPool ->getConverterByMediaType($image['media_type']); return $converter->convertTo($this, $image); } 18 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 19. Extract Method Example - After (2/2) // MagentoCatalogModelProduct protected function convertToMediaGalleryInterface(array $mediaGallery) { $entries = []; foreach ($mediaGallery as $image) { $entries[] = $this->mediaGalleryEntryConverterPool ->convertImageToMediaGalleryEntry($image, $this); } return $entries; } // MagentoCatalogModelProductAttributeBackendMediaEntryConverterPool public function convertImageToMediaGalleryEntry(array $image, Product $product) { $converter = $this->getConverterByMediaType($image['media_type']); return $converter->convertTo($product, $image); } 19 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 20. Encapsulation „In general, encapsulation is the inclusion of one thing within another thing so that the included thing is not apparent.“ -- TechTarget SearchNetworking 20 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 21. Encapsulation „Other objects ... use the object without having to be concerned with how the object accomplishes it.“ -- TechTarget SearchNetworking 21 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 22. Tell, don't ask! 22 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 23. Extraction enables us to properly encapsulate functionality. 23 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 24. Proposition: It is good to write code that is simple to extract. 24 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 25. Topics ‱ Extraction & Encapsulation ‱ Managing State with Immutable Objects ‱ The Value of Validity ‱ Immutable Variables ‱ Reasoning about Code with Idempotence 25 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 26. Managing State with Immutable Objects 26 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 27. Immutawhat? 27 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 28. „In object-oriented and functional programming, an immutable object is an object whose state cannot be modified after it is created.“ -- Wikipedia, Immutable object 28 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 29. Yes, but... why? 29 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 30. I've read it helps avoid a whole class of bugs. So, what are they? 30 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 31. Reasonability 31 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 32. Reading ➡ Understanding 32 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 33. Understanding ➡ Knowing ‱ Is it correct or ‱ Is it incorrect 33 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 34. When objects change in distant code, it becomes more complex to track what changed where and why. 34 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 35. Immutability helps to avoid temporal coupling 35 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 36. For Example: // MagentoBraintreeModelPaymentMethod::partialCapture() $this->conïŹg->initEnvironment($payment->getOrder()->getStoreId()); 36 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 37. Temporal Coupling: // MagentoBraintreeModelPaymentMethod::partialCapture() $this->conïŹg->initEnvironment($payment->getOrder()->getStoreId()); What state does the config start out in before it is initialized? 37 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 38. Temporal Coupling: // MagentoBraintreeModelPaymentMethod::partialCapture() $this->conïŹg->initEnvironment($payment->getOrder()->getStoreId()); What happens if the config is initialized twice with different store ids? 38 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 39. Temporal Coupling: // MagentoBraintreeModelPaymentMethod::partialCapture() $this->conïŹg->initEnvironment($payment->getOrder()->getStoreId()); What happens if another method is called before this one and the other one also relies on the config environment being initialized? 39 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 40. Temporal Coupling: // MagentoBraintreeModelPaymentMethod::partialCapture() $this->conïŹg->initEnvironment($payment->getOrder()->getStoreId()); What happens if the call to initEnvironment is missed? 40 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 41. Temporal Coupling: // MagentoBraintreeModelPaymentMethod::partialCapture() $this->conïŹg->initEnvironment($payment->getOrder()->getStoreId()); Extracting methods is tricky because the extracted part might rely on a different method being called first. This might not be apparent. 41 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 42. Temporal Coupling: // MagentoBraintreeModelPaymentMethod::partialCapture() $this->conïŹg->initEnvironment($payment->getOrder()->getStoreId()); What happens if another object has a reference to the same config instance, but it doesn't know about or expect the config change? 42 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 43. Temporal Coupling: // MagentoBraintreeModelPaymentMethod::partialCapture() $this->conïŹg->initEnvironment($payment->getOrder()->getStoreId()); What happens if a response of the payment instance is cached and then the config environment is changed? 43 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 44. External Initialization methods and Setters add complexity 44 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 45. External immutability & Internal immutability 45 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 46. Internal mutability allows for memoization 46 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 47. Memoization : „An optimization technique to speed up expensive method calls by storing the result after the first call and returning the cached result if the same inputs occur again.“ 47 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 48. Memoization Example public function getAltitudeAvg(Location $loc, Date $date) { $coords = (string) $loc->getCoords(); $dateStr = (string) $date; if (! @$this->memoizedResults[$coords][$dateStr]) { $avgAltitude = $this->doExpensiveCalculation($loc, $date); $this->memoizedResults[$coords][$dateStr] = $avgAltitude; } return $this->memoizedResults[$coords][$dateStr]; } 48 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 49. Anyway... Memoization is a lot simpler to do with externally immutable objects since nothing can invalidate the result. 49 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 50. Testing code which uses immutable objects is simpler 50 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 51. Test Double: Mutable Object $initWasCalled = false; $mockConïŹg = $this->getMock(MagentoBraintreeModelConïŹg, [], [], '', false); $mockConïŹg->method('initEnvironment') ->willReturnCallback(function () use (&$initWasCalled) { $initWasCalled = true; }); $mockConïŹg->method('canUseForCountry') ->willReturnCallback(function ($country) use (&$initWasCalled) { return $initWasCalled ? false : true; }); 51 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 52. Yuck! 52 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 53. Incomplete Test Double: Mutable Object $initializedConïŹgMock = $this->getMock(MagentoBraintreeModelConïŹg, [], [], '', false); $initializedConïŹgMock->method('canUseForCountry')->willReturn(true); Easy to miss calling initEnvironment in the system under test! 53 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 54. Test Double: Immutable Object $conïŹgMock = $this->getMock(MagentoBraintreeModelConïŹg, [], [], '', false); $conïŹgMock->method('canUseForCountry')->willReturn(true); 54 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 55. Simpler to cache No need to worry that an object changes after it is written to cache. 55 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 57. Example: Magento EE PageCache Events after cache write: ‱ controller_front_send_response_before (in a later Observer) ‱ controller_front_send_response_after ‱ http_response_send_before 57 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 58. Once valid always valid Can something be „half valid“? 58 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 59. Example: invalidation of a mutable object $product = $productCollection->getFirstItem(); $product->getPrice(); // 24.99 $product->getSpecialPrice(); // 19.99 $product->setPrice(11.95); $product->setSpecialPrice(10.95); $product->getFinalPrice() // 19.99 59 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 60. So how do the values get into an immutable object? 60 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 61. Constructor Injection 61 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 62. __construct() $request = new HttpRequest( HttpRequest::METHOD_GET, HttpUrl::fromString('http://example.com/lookie/here'), HttpHeaders::fromArray($httpHeaders), HttpRequestBody::fromString($httpRequestBodyString) ); 62 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 63. Named constructor $request = HttpRequest::fromGlobalState(); 63 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 64. Example 1: named constructor public static function fromGlobalState($requestBody = '') { $method = $_SERVER['REQUEST_METHOD']; $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']) ? 'https' : 'http'; $path = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; $url = $protocol . '://' . $path; $headers = self::getGlobalRequestHeaders(); return static::fromScalars($method, $url, $headers, $requestBody); } 64 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 65. Example 2: named constructor public static function fromScalars( $methodString, $urlString, $headersArray, $bodyString ) { $url = HttpUrl::fromString($urlString); $headers = HttpHeaders::fromArray($headersArray); $body = HttpRequestBody::fromString($bodyString); return new self($methodString, $url, $headers, $body); } 65 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 66. But IRL things change 66 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 67. Modeling change with immutable objects Change is introduced by creating a new instance. 67 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 68. Looks like mutation, but it ain't $today = new DateTimeImmutable(); echo $today->format('Y-m-d H:i:s'); // 2015-10-29 21:32:06 $day = DateInterval::createFromDateString('24 hours'); $tomorrow = $today->add($day); echo $today->format('Y-m-d H:i:s'); // 2015-10-29 21:32:06 echo $tomorrow->format('Y-m-d H:i:s');// 2015-10-30 21:32:06 68 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 69. Contraindications 69 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 70. Does immutability make code more complex or simple? 70 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 71. A thing that changes over time. $room = new ConferenceRoom( $location, $event, $attendees ) 71 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 72. Is it a new conference room just because the number of people change? 72 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 73. A mutable conference room model: $nPeople = $room->countPeople(); $room->addPerson($attendee); $room->countPeople() === $nPeople + 1; 73 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 74. A immutable conference room model: $nPeople = $room->countPeople(); $updatedRoom = $room->addPerson($attendee); $room->countPeople() === $nPeople; $updatedRoom->countPeople() === $nPeople + 1; 74 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 75. Temporal modeling An instance represents the object at one moment in time. 75 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 76. Temporal modeling (Immutable object at a moment in time) (Immutable object at a moment in time) (Immutable object at a moment in time) (Immutable object at a moment in time) ... All the same Entity that changes over time. 76 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 77. Temporal modeling Keeps History ! Not a natural way to do OOP, adds complexity ! Unaccustomed way to think ! " 77 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 78. Bottom Line If you don't have to model changes over time, using immutability will probably make your code simpler. If you do have to worry about changes over time... it depends. 78 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 79. Topics ‱ Extraction & Encapsulation ‱ Managing State with Immutable Objects ‱ The Value of Validity ‱ Immutable Variables ‱ Reasoning about Code with Idempotence 79 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 80. The Value of Validity 80 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 81. Enforce object validity at instantiation. 81 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 82. Validation at Instantiation ‱ __construct() ‱ Named constructor (aka Factory Method) ‱ Builder or Factory 82 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 83. Constructor validation The safest place to enforce validity 83 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 84. Example Constructor Validation public function __construct($amount) { if (!is_int($amount)) { $type = gettype($amount); $msg = sprintf('Can not create price from "%s"', $type); throw new InvalidAmountTypeException($msg); } $this->amount = $amount; } 84 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 85. When it gets more complex... 85 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 86. Example Delegation of Validation // ProductAttributeListBuilder public static function fromArray(array $attributesArray) { $attributes = array_map(function (array $attributeArray) { return ProductAttribute::fromArray($attributeArray); }, $attributesArray); return new self(...$attributes); } public function __construct(ProductAttribute ...$attributes) { $this->validateAllAttributesHaveCompatibleContextData(...$attributes); $this->attributes = $attributes; } 86 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 87. Each thing is a class Each object validates it's data 87 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 88. Plug: Value Objects Introduction slides on Value Objects by Tim Bezhashvyly http://vin.ai/tims_value_objects 88 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 89. The cost of validity Classes require time to write, test and maintain. ‱ Each thing is a new class ‱ Lots of code 89 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 90. What about scalars? ‱ string ‱ int ‱ bool ‱ float ‱ null ‱ arrays of scalars 90 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 91. Code Smell: Primitives Obsession „Primitives Obsession is using primitive data types to represent domain ideas.“ 91 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 92. Primitives Obsession No Type Safety (until PHP 7) Tests help 92 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 93. Primitives Obsession Easy to end up with Code Duplication 93 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 94. Primitives Obsession Magic values „I knew at once what process(1.34, true) meant!“ -- Noone, ever Class names have documentary value 94 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 95. Primitives Obsession No built-in validation Tests help (again) 95 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 96. Benefits of scalar types 96 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 97. Benefits of scalar types They are immutable 97 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 98. Benefits of scalar types They are easily created 98 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 99. Benefits of scalar types They are comparable 99 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 100. Benefits of scalar types Serializable They work over the wire 100 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 101. Benefits of scalar types Completely upgrade safe 101 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 102. Benefits of scalar types They are fast 102 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 103. Benefits of scalar types They are language independent 103 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 104. Scalars vs. Value Objects 104 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 105. Scalars make great boundary interfaces 105 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 106. Scalar Boundary Interfaces ‱ Web API ‱ Components API ‱ Message Queue Payload 106 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 107. Scalar Boundary Interfaces ‱ Less interface dependencies ‱ But implicit coupling to data format 107 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 108. Topics ‱ Extraction & Encapsulation ‱ Managing State with Immutable Objects ‱ The Value of Validity ‱ Immutable Variables ‱ Reasoning about Code with Idempotence 108 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 109. Immutable Variables 109 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 110. In PHP? No 110 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 111. But we can treat variables as immutable. 111 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 112. Example 1: reusing local variables public function testTwoRequestsAddTwoMessages() { $request = $this->createProductUpdateRequest(); $app = new WebFront($request, $this->testFactory); $app->runWithoutSendingResponse(); $request = $this->createStockUpdateRequest(); $app = new WebFront($request, $this->testFactory); $app->runWithoutSendingResponse(); $queue = $this->testFactory->createQueue(); $this->assertCount(2, $queue); } // Multiple assignments to $request and $app 112 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 113. What is the problem? ‱ Messy to move or extract ‱ Complex to reason about 113 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 114. Example 1: treating local variables as immutable public function testTwoRequestsAddTwoMessages() { $productUpdateRequest = $this->createProductUpdateRequest(); $ïŹrstApp = new WebFront($productUpdateRequest, $this->testFactory); $ïŹrstApp->runWithoutSendingResponse(); $stockUpdateRequest = $this->createStockUpdateRequest(); $secondApp = new WebFront($stockUpdateRequest, $this->testFactory); $secondApp->runWithoutSendingResponse(); $queue = $this->testFactory->createQueue(); $this->assertCount(2, $queue); } 114 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 115. Example 2: local variable mutation in a loop // MagentoCatalogModelProduct protected function convertToMediaGalleryInterface(array $mediaGallery) { $entries = []; foreach ($mediaGallery as $image) { $entries[] = $this->mediaGalleryEntryConverterPool ->convertImageToMediaGalleryEntry($image, $this); } return $entries; } // Multiple assignments to $image, mutation of $entries 115 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 116. Example 2: map/reduce helps avoiding local variable mutation // MagentoCatalogModelProduct protected function convertToMediaGalleryInterface(array $mediaGallery) { return array_map( function ($image) { $this->mediaGalleryEntryConverterPool ->convertImageToMediaGalleryEntry($image, $this); }, $mediaGallery ); } 116 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 117. Immutable Variables ++Reasonability 117 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 118. Immutable Variables Less bugs 118 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 119. Immutable Variables Simple to refactor 119 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 120. Immutable Variables My new friends: ‱ Closure ‱ array_map() ‱ array_reduce() ‱ array_merge() ‱ array_filter() ‱ recursion ‱ ... 120 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 121. Topics ‱ Extraction & Encapsulation ‱ Managing State with Immutable Objects ‱ The Value of Validity ‱ Immutable Variables ‱ Reasoning about Code with Idempotence 121 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 122. Reasoning about Code with Idempotence 122 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 123. Another of those words... 123 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 124. Idempotence „In computer science, the term idempotent is used ... to describe an operation that will produce the same results if executed once or multiple times.“ -- Wikipedia, Idempotence, Computer Science 124 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 125. What it ain't Example 1 class Logger { public function log($level, $message) { $f = fopen($this->ïŹle . '-' . $level, 'a'); ïŹ‚ock($f, LOCK_EX); fwrite($f, message); ïŹ‚ock($f, LOCK_UN); fclose($f); } } // repeated calls add additional records 125 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 126. Idempotent logger Example 1 class Logger { public function log($level, $message) { $f = fopen($this->ïŹle . '-' . $level, 'a'); ïŹ‚ock($f, LOCK_EX); if ($this->getLastLineFromFile() !== $message) { fwrite($f, message); } ïŹ‚ock($f, LOCK_UN); fclose($f); } } // repeated calls add NO additional records 126 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 127. What it ain't Example 2 protected function validateIsFoo($object) { if (! $object instanceof Foo) { echo "$object is not an instance of Foon"; return false; } return true; } // repeated calls may produce repeated output 127 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 128. Idempotent validateIsFoo Example 2 protected function validateIsFoo($object) { return $object instanceof Foo; } // no output 128 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 129. Pure Functions All pure functions are idempotent 129 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 130. Pure Functions No side effects 130 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 131. Pure Functions Rely only on input arguments 131 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 132. Pure Functions No dependency on global state such as ‱ $_SERVER, $_SESSION ‱ getcwd() ‱ file_exists() ‱ Mage::getIsDeveloperMode() 132 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 133. Pure Functions For the same input they always return the same output 133 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 134. And my point is? 134 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 135. Idempotent Functions are Simpler to reuse Simpler to compose Pure Functions are Simpler to refactor Simpler to change Simpler to reason about 135 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 136. It pays to focus on the dependencies of every method OOP is all about dependency management 136 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 137. I'm still learning But so far results are very encouraging. I'm happy for every tool that helps to reduce complexity 137 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015
  • 138. Thanks for your attention! Please, Ask questions, and I'm eager to hear your thoughts and comments! 138 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - contact@vinaikopp.com - © 2015