Architecture in-the-small-slides
Transcript of Architecture in-the-small-slides
![Page 1: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/1.jpg)
Architecturein the Small
1 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 2: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/2.jpg)
Hi!
Vinai KoppFreelance Developer and Trainer@VinaiKopp
2 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 3: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/3.jpg)
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 - [email protected] - © 2015
![Page 4: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/4.jpg)
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 - [email protected] - © 2015
![Page 5: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/5.jpg)
Some of the many Peoplewho 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 - [email protected] - © 2015
![Page 6: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/6.jpg)
DisclaimerThe 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 - [email protected] - © 2015
![Page 7: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/7.jpg)
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 - [email protected] - © 2015
![Page 8: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/8.jpg)
Extraction&Encapsulation
8 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 9: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/9.jpg)
Extraction?WTF?
9 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 10: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/10.jpg)
A subset of
Refactoring
10 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 11: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/11.jpg)
„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 - [email protected] - © 2015
![Page 12: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/12.jpg)
12 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 13: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/13.jpg)
The usual purpose of refactoring:
Get rid of smelly code
13 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 14: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/14.jpg)
But in case of extraction
It can be more
14 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 15: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/15.jpg)
Simplicityvs.
Amount of code
15 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 16: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/16.jpg)
SimplicityCan make things
visiblethat where hidden in the code
16 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 17: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/17.jpg)
Extract Method Example - Before// Magento\Catalog\Model\Product
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 - [email protected] - © 2015
![Page 18: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/18.jpg)
Extract Method Example - After (1/2)// Magento\Catalog\Model\Product
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 - [email protected] - © 2015
![Page 19: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/19.jpg)
Extract Method Example - After (2/2)// Magento\Catalog\Model\Product
protected function convertToMediaGalleryInterface(array $mediaGallery){ $entries = []; foreach ($mediaGallery as $image) { $entries[] = $this->mediaGalleryEntryConverterPool ->convertImageToMediaGalleryEntry($image, $this); } return $entries;}
// Magento\Catalog\Model\Product\Attribute\Backend\Media\EntryConverterPool
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 - [email protected] - © 2015
![Page 20: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/20.jpg)
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 - [email protected] - © 2015
![Page 21: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/21.jpg)
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 - [email protected] - © 2015
![Page 22: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/22.jpg)
Tell, don't ask!
22 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 23: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/23.jpg)
Extraction enables us to properly encapsulate functionality.
23 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 24: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/24.jpg)
Proposition:It is good to write code that is simple to extract.
24 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 25: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/25.jpg)
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 - [email protected] - © 2015
![Page 26: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/26.jpg)
Managing State with Immutable Objects
26 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 27: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/27.jpg)
Immutawhat?
27 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 28: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/28.jpg)
„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 - [email protected] - © 2015
![Page 29: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/29.jpg)
Yes, but... why?
29 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 30: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/30.jpg)
I've read it helps avoid a whole class of bugs.
So, what are they?
30 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 31: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/31.jpg)
Reasonability
31 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 32: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/32.jpg)
Reading ➡ Understanding
32 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 33: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/33.jpg)
Understanding ➡ Knowing• Is it correct
or
• Is it incorrect
33 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 34: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/34.jpg)
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 - [email protected] - © 2015
![Page 35: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/35.jpg)
Immutability helps to avoid temporal coupling
35 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 36: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/36.jpg)
For Example:// \Magento\Braintree\Model\PaymentMethod::partialCapture()$this->config->initEnvironment($payment->getOrder()->getStoreId());
36 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 37: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/37.jpg)
Temporal Coupling:// \Magento\Braintree\Model\PaymentMethod::partialCapture()$this->config->initEnvironment($payment->getOrder()->getStoreId());
What state does the config start out in before it is initialized?
37 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 38: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/38.jpg)
Temporal Coupling:// \Magento\Braintree\Model\PaymentMethod::partialCapture()$this->config->initEnvironment($payment->getOrder()->getStoreId());
What happens if the config is initialized twice with different store ids?
38 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 39: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/39.jpg)
Temporal Coupling:// \Magento\Braintree\Model\PaymentMethod::partialCapture()$this->config->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 - [email protected] - © 2015
![Page 40: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/40.jpg)
Temporal Coupling:// \Magento\Braintree\Model\PaymentMethod::partialCapture()$this->config->initEnvironment($payment->getOrder()->getStoreId());
What happens if the call to initEnvironment is missed?
40 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 41: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/41.jpg)
Temporal Coupling:// \Magento\Braintree\Model\PaymentMethod::partialCapture()$this->config->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 - [email protected] - © 2015
![Page 42: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/42.jpg)
Temporal Coupling:// \Magento\Braintree\Model\PaymentMethod::partialCapture()$this->config->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 - [email protected] - © 2015
![Page 43: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/43.jpg)
Temporal Coupling:// \Magento\Braintree\Model\PaymentMethod::partialCapture()$this->config->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 - [email protected] - © 2015
![Page 44: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/44.jpg)
ExternalInitialization methodsandSetters
add complexity
44 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 45: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/45.jpg)
External immutability&Internal immutability
45 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 46: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/46.jpg)
Internal mutability allows for memoization
46 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 47: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/47.jpg)
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 - [email protected] - © 2015
![Page 48: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/48.jpg)
Memoization Examplepublic 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 - [email protected] - © 2015
![Page 49: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/49.jpg)
Anyway...
Memoization is a lot simpler to do withexternally immutable objectssince nothing can invalidate the result.
49 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 50: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/50.jpg)
Testing code which uses immutable objects is simpler
50 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 51: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/51.jpg)
Test Double: Mutable Object$initWasCalled = false;$mockConfig = $this->getMock(\Magento\Braintree\Model\Config, [], [], '', false);
$mockConfig->method('initEnvironment') ->willReturnCallback(function () use (&$initWasCalled) { $initWasCalled = true; });
$mockConfig->method('canUseForCountry') ->willReturnCallback(function ($country) use (&$initWasCalled) { return $initWasCalled ? false : true; });
51 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 53: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/53.jpg)
Incomplete Test Double:Mutable Object$initializedConfigMock = $this->getMock(\Magento\Braintree\Model\Config, [], [], '', false);
$initializedConfigMock->method('canUseForCountry')->willReturn(true);
Easy to miss calling initEnvironment in the system under test!
53 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 54: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/54.jpg)
Test Double: Immutable Object$configMock = $this->getMock(\Magento\Braintree\Model\Config, [], [], '', false);$configMock->method('canUseForCountry')->willReturn(true);
54 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 55: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/55.jpg)
Simpler to cacheNo need to worry that an object changes after it is written to cache.
55 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 56: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/56.jpg)
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 - [email protected] - © 2015
![Page 57: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/57.jpg)
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 - [email protected] - © 2015
![Page 58: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/58.jpg)
Once validalways validCan something be „half valid“?
58 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 59: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/59.jpg)
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 - [email protected] - © 2015
![Page 60: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/60.jpg)
So how do the values get into an immutable object?
60 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 61: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/61.jpg)
Constructor Injection
61 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 62: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/62.jpg)
__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 - [email protected] - © 2015
![Page 63: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/63.jpg)
Named constructor$request = HttpRequest::fromGlobalState();
63 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 64: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/64.jpg)
Example 1: named constructorpublic 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 - [email protected] - © 2015
![Page 65: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/65.jpg)
Example 2: named constructorpublic 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 - [email protected] - © 2015
![Page 66: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/66.jpg)
But IRLthings change
66 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 67: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/67.jpg)
Modeling change with immutable objectsChange is introduced by creating a new instance.
67 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 68: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/68.jpg)
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:06echo $tomorrow->format('Y-m-d H:i:s');// 2015-10-30 21:32:06
68 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 69: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/69.jpg)
Contraindications
69 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 70: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/70.jpg)
Does immutability make code more
complexor
simple?
70 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 71: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/71.jpg)
A thing that changes over time.
$room = new ConferenceRoom( $location, $event, $attendees)
71 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 72: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/72.jpg)
Is it a new conference room just because the number of people change?
72 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 73: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/73.jpg)
A mutable conference room model:
$nPeople = $room->countPeople();$room->addPerson($attendee);
$room->countPeople() === $nPeople + 1;
73 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 74: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/74.jpg)
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 - [email protected] - © 2015
![Page 75: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/75.jpg)
Temporal modelingAn instance represents the objectat one moment in time.
75 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 76: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/76.jpg)
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 - [email protected] - © 2015
![Page 77: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/77.jpg)
Temporal modelingKeeps History !
Not a natural way to do OOP, adds complexity !
Unaccustomed way to think ! "
77 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 78: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/78.jpg)
Bottom LineIf 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 - [email protected] - © 2015
![Page 79: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/79.jpg)
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 - [email protected] - © 2015
![Page 80: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/80.jpg)
The Value of Validity
80 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 81: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/81.jpg)
Enforce object validity at instantiation.
81 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 82: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/82.jpg)
Validation at Instantiation• __construct()• Named constructor (aka Factory Method)• Builder or Factory
82 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 83: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/83.jpg)
Constructor validationThe safest place to enforce validity
83 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 84: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/84.jpg)
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 - [email protected] - © 2015
![Page 85: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/85.jpg)
When it gets more complex...
85 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 86: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/86.jpg)
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 - [email protected] - © 2015
![Page 87: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/87.jpg)
Each thing is a classEach object validates it's data
87 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 88: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/88.jpg)
Plug: Value ObjectsIntroduction slides on Value Objectsby Tim Bezhashvyly
http://vin.ai/tims_value_objects
88 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 89: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/89.jpg)
The cost of validityClasses require time to write, test and maintain.
• Each thing is a new class• Lots of code
89 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 90: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/90.jpg)
What about scalars?• string• int• bool• float• null• arrays of scalars
90 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 91: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/91.jpg)
Code Smell:Primitives Obsession„Primitives Obsession is using primitive data types to represent domain ideas.“
91 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 92: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/92.jpg)
Primitives ObsessionNo Type Safety
(until PHP 7)
Tests help
92 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 93: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/93.jpg)
Primitives ObsessionEasy to end up with Code Duplication
93 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 94: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/94.jpg)
Primitives ObsessionMagic 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 - [email protected] - © 2015
![Page 95: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/95.jpg)
Primitives ObsessionNo built-in validation
Tests help (again)
95 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 96: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/96.jpg)
Benefits of scalar types
96 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 97: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/97.jpg)
Benefits of scalar types
They are immutable
97 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 98: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/98.jpg)
Benefits of scalar types
They are easily created
98 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 99: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/99.jpg)
Benefits of scalar types
They are comparable
99 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 100: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/100.jpg)
Benefits of scalar types
Serializable
They work over the wire
100 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 101: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/101.jpg)
Benefits of scalar types
Completely upgrade safe
101 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 102: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/102.jpg)
Benefits of scalar types
They are fast
102 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 103: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/103.jpg)
Benefits of scalar types
They are language independent
103 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 104: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/104.jpg)
Scalarsvs.Value Objects
104 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 105: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/105.jpg)
Scalars make greatboundary interfaces
105 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 106: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/106.jpg)
Scalar Boundary Interfaces• Web API• Components API• Message Queue Payload
106 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 107: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/107.jpg)
Scalar Boundary Interfaces• Less interface dependencies• But implicit coupling to data format
107 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 108: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/108.jpg)
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 - [email protected] - © 2015
![Page 109: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/109.jpg)
Immutable Variables
109 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 110: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/110.jpg)
In PHP?No
110 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 111: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/111.jpg)
But we can treat variables as immutable.
111 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 112: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/112.jpg)
Example 1: reusing local variablespublic 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 - [email protected] - © 2015
![Page 113: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/113.jpg)
What is the problem?• Messy to move or extract• Complex to reason about
113 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 114: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/114.jpg)
Example 1: treating local variables as immutablepublic function testTwoRequestsAddTwoMessages(){ $productUpdateRequest = $this->createProductUpdateRequest(); $firstApp = new WebFront($productUpdateRequest, $this->testFactory); $firstApp->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 - [email protected] - © 2015
![Page 115: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/115.jpg)
Example 2: local variable mutation in a loop// Magento\Catalog\Model\Product
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 - [email protected] - © 2015
![Page 116: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/116.jpg)
Example 2: map/reduce helps avoiding local variable mutation// Magento\Catalog\Model\Product
protected function convertToMediaGalleryInterface(array $mediaGallery){ return array_map( function ($image) { $this->mediaGalleryEntryConverterPool ->convertImageToMediaGalleryEntry($image, $this); }, $mediaGallery );}
116 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 117: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/117.jpg)
Immutable Variables++Reasonability
117 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 118: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/118.jpg)
Immutable VariablesLess bugs
118 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 119: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/119.jpg)
Immutable VariablesSimple to refactor
119 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 120: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/120.jpg)
Immutable VariablesMy new friends:
• \Closure• array_map()• array_reduce()• array_merge()• array_filter()• recursion• ...120 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 121: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/121.jpg)
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 - [email protected] - © 2015
![Page 122: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/122.jpg)
Reasoning about Code with Idempotence
122 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 123: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/123.jpg)
Another of those words...
123 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 124: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/124.jpg)
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 - [email protected] - © 2015
![Page 125: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/125.jpg)
What it ain'tExample 1class Logger{ public function log($level, $message) { $f = fopen($this->file . '-' . $level, 'a'); flock($f, LOCK_EX); fwrite($f, message); flock($f, LOCK_UN); fclose($f); }}// repeated calls add additional records
125 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 126: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/126.jpg)
Idempotent loggerExample 1class Logger{ public function log($level, $message) { $f = fopen($this->file . '-' . $level, 'a'); flock($f, LOCK_EX); if ($this->getLastLineFromFile() !== $message) { fwrite($f, message); } flock($f, LOCK_UN); fclose($f); }}// repeated calls add NO additional records
126 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 127: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/127.jpg)
What it ain'tExample 2protected function validateIsFoo($object){ if (! $object instanceof Foo) { echo "\$object is not an instance of Foo\n"; return false; } return true;}// repeated calls may produce repeated output
127 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 128: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/128.jpg)
Idempotent validateIsFooExample 2
protected function validateIsFoo($object){ return $object instanceof Foo;}// no output
128 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 129: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/129.jpg)
Pure FunctionsAll pure functions are idempotent
129 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 130: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/130.jpg)
Pure FunctionsNo side effects
130 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 131: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/131.jpg)
Pure FunctionsRely only on input arguments
131 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 132: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/132.jpg)
Pure FunctionsNo dependency on global state such as
• $_SERVER, $_SESSION• getcwd()• file_exists()• Mage::getIsDeveloperMode()
132 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 133: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/133.jpg)
Pure FunctionsFor the same input they always return the same output
133 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 134: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/134.jpg)
And my point is?
134 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 135: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/135.jpg)
Idempotent Functions areSimpler to reuseSimpler to compose
Pure Functions areSimpler to refactorSimpler to changeSimpler to reason about
135 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 136: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/136.jpg)
It pays to focus on the dependencies of every methodOOP is all about dependency management
136 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015
![Page 137: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/137.jpg)
I'm still learningBut 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 - [email protected] - © 2015
![Page 138: Architecture in-the-small-slides](https://reader031.fdocuments.in/reader031/viewer/2022030305/5871aef91a28abda6a8b635b/html5/thumbnails/138.jpg)
Thanks for your attention!Please,Ask questions, andI'm eager to hear your thoughts and comments!
138 Architecture in the Small - MageTitans 2015 - ! - @VinaiKopp - [email protected] - © 2015