 So, I will talk about design patterns, how you can implement those design patterns with real concrete code and with PHP. I guess most of you are Drupal developers, maybe some symphony developers as well. So this session will help you to know more about object-oriented design. And so you will also learn stuff that you can find in symphony as symphony uses design patterns a lot and I think Drupal does as well. I'm not a Drupal developer, I'm a symphony developer. My name is Hugo. I work for Essential Apps, the company that creates symphony and so I'm one of the major symphony contributors. You can find me on Twitter. My nickname is HMN with double H and this is my cat on the bottom left side of this slide. So this presentation is very code-oriented, as you will see. I will first take maybe 10 minutes to introduce design pattern in theory and then the remaining of the session will be about practicing design patterns. So I will show you four design patterns that I will present you with real world code. So introduction. So what are design patterns? So basically a design pattern is an abstract solution to a common redundant problems. So in software engineering, we always design softwares and when we design softwares, we do things that are recurring from a project to another. And so back in the 70s and 80s, some people decided to find or to invent some patterns on some abstract solutions to fix those problems. So the design patterns were formally, I would say, they were published as a book in the 90s. And as these are abstract solutions, you can implement them with any programming language as long as your programming language supports object-oriented design. So PHP, or Python, or Java, Rails, or Ruby, and whatever. So those patterns, they were mainly invented by four people that we called the Gang of Four. As I said, they created those patterns in the 70s. And there are 23 Gang of Four design patterns. You can find more architectural design patterns now, but those 23s are the default one. And so when they define those patterns, they organize them into three different families. The first family is the creational family patterns, which means all the design patterns that are meant to encapsulate how you create object and how you initialize objects. The second family is the family of structural design patterns. So it's basically the patterns that help you structure the code to make it more flexible and more extensible. And the final one, the behavior patterns family contains the patterns that help, or that define patterns that help your codes or your classes and objects communicate with each other in the way to decouple the objects from each other. So that's the three different families. And so I will show you patterns from the three different families. One creational, two structural, and one behavioral design pattern. So when you use design patterns, you will also leverage some benefits of using them. The first one is communication because every pattern has a name, has a unique name, and every pattern solves a unique problem. So when you know how to implement a pattern and if you know how to recognize them in a code base, then you know basically which problem it solves. And so this helps the communication between software engineers. If every engineer in the team know the patterns, then they will better communicate with the code base. The design patterns also force you to write your code in a way that you make it unit testable. So if you have unit testing tools like PHP unit, if you follow the patterns, your code should be unit testable. The patterns, as I said, they also help to decouple things. You want to have less coupling between your objects. And so this will also ease your maintenance. Because if you want to remove a piece and change it with another piece of code, this should be done without breaking too much things in your code base. And so as I said, the patterns will help you to make your code more extensible and loosely coupled. So these are the main benefits. However, we also have downsides of using design patterns. One of the main downsides is that it's very hard to teach them and also hard to learn design patterns. In my experience, when I started to learn them, I needed several years to master most of them. And I still don't master every 23 design patterns because I don't use all of them in my daily job. But knowing most of them is important. And also, when you want to use a pattern, sometimes it's not very interesting to use them. Sometimes you want to use a pattern because it really solves a problem in your code base and it provides value to your code base. But sometimes it's better to make a quick and dirty patch for your code. So you have to know whether it's valuable for your code base to use a pattern or not. The design pattern also uses object-oriented design. So you need strong knowledge of object-oriented programming. So you need to know about abstraction, encapsulations, interfaces, compositions, and everything. So that's another way of friction to learn design patterns. Anyway, so just before I show you some design pattern codes, I will just focus on this principle. Do you know the solid principle? Some people in the audience, yeah, some? So solid principle is a set of five principles to follow to make your code more unit-testable, more flexible, and better design. The first principle is called single-responsibility principle. This is basically a principle that states that your objects or your classes must be focused on one single responsibility. So one class or one object does one thing and it does it well. This is for preventing your classes to have thousands of lines of codes. If you have a class that has thousands of lines of codes, that means your class does too much things. The second principle is called OCP or open-close principle, which means your code must be open to extension but close to modifications, which basically means you must be able to extend your objects or extend your classes without modifying them, without touching them. So you will see in the design pattern that I will show you that those patterns encourage those practices. The second or the third principle is called LSP or list code substitution principle. It's basically a principle that states that you should be able to remove or to change a dependency of an object with another dependency which has the same contract. So if you have an object A and in the construct method, let's say, of your object A, you can have a dependency of type B. You should be able to swap this dependency B with another dependency of type B prime. And if those two classes respect the same contract, the same interface, then code A should be able to run the same way with either B or B prime dependency. ISP stands for interface segregation principle. It's basically the single responsibility principle but applied to interfaces. So you should make your interfaces short and only focus on what they do. We have an example in symphony, for instance, in the security system where we have an interface called user interface, which describes what a user, an authenticated user is. So you can just implement user interface. But if you want to have a more advanced user interface, which has other actions, then you can also implement advanced user interface. So to avoid having a big user interface in symphony, we just split it in two different interfaces. And the last one is called dependency inversion principle. It's dependency inversion, not dependency injection. I guess that you probably learned a lot of dependency injection during the conference. I think my colleague Nicholas need to talk about that. But dependency inversion means that you should depend on abstraction instead of implementation. So basically when you type into dependency as an argument of a method, for instance, you should use abstract types like abstract classes or interfaces to reduce coupling. So if you do dependency inversion, if you respect this principle, as a consequence, you are also doing dependency injection. So I encourage you to read some more stuff about solid principle because it's very interesting to dig into these coding craftsmanship. So let's start with concrete design patterns and stuff. So I will show you one first design pattern, which is a creational design pattern. As I said, this family of patterns, creational, allows you to encapsulate or to centralize the way you create your objects. So basically instead of using the new keywords to instantiate objects, you will do it in just one place. And then the code that needs to use objects, they will just call some factory objects to get these created objects. So we have different patterns for creating objects. They have different intents and they solve different problems. And the most famous one is probably the singleton, as you probably may know, which is now considered as an anti-pattern because it has lots of downsides, so this is why it strikes on my slide deck. So the one I want to show you is the factory method design pattern because this pattern is probably one of the one that is not the best well-implemented by developers, or it's the one that is the most misunderstood design pattern in this creational list. So basically, the Gengorfer says that the factory method design patterns defines an interface, so an interface can be an interface or an abstract class, for instance, or an abstract type, for creating an object. But it lets subclasses decide which object class to instantiate. So to sum up, that means when you have a factory abstract type, that you have to concretize with a concrete class. The concrete class will be responsible for instantiating one particular type of object, but only one. And this is this factory method design pattern. I will first show you the two approaches that are not the factory, the real factory method design pattern, but they look like this pattern. And then I will show you the real one. So why do you need a factory? The need for a factory comes when you need to encapsulate the complex steps to create an object. One famous example, let's say, in Symphony or in Drupal is the service container, the dependency injection container. The dependency injection container in Drupal is just a big factory for creating objects. But it doesn't follow this design pattern because the container can create different type of objects or services. When you follow this real pattern, that means you have one factory that creates one type of object and only one. And so the fact that you centralize this process or this algorithm in one single place, then it allows you to change it later on if you need to do some changes to your code. So you have to touch one single class instead of the multiple locations in your code where you are manually instantiating your objects. So this is not the real pattern, but this is a first approach, which is called the static method approach. As you can see this class, MediaFactory has a static method to create a media based on the extension of the file. So if it's a PDF extension, then we create a PDF file object. If it's a text extension, then we create a text file instance. At least that's not too bad to do that because at least you have centralized, sorry, you have centralized the creation of your objects in one location. So if you want to change something, you just change it here. And in your code everywhere you use this class or this static method, then you will reuse this code. But this implementation has many, many lacks. As you can see, I want to use this MediaFactory class and this static method in another object, which is called document repository. And the problem here is that I'm using the class here, MediaFactory, I'm strongly typing MediaFactory, which leads to a tight coupling between this object and this object. Remember, the solid principle, you should not depend on concrete classes. And this is a concrete class. Also, this code is not following the OCP principle, the open-close principle. If I want to swap this factory with another one, I will have to change the document repository class. So my code in this case is open to modification instead of being close to modification. So this is why the static factory approach has lots of lacks. A better way to do this is to remove the static keyword. So as I said, we have advantages of this approach. It's simple, it's pragmatic, but it introduces tight coupling between objects. So if you really want to make this better, you just remove the static keyword and you make it a real factory instance object. As you can see, my class also implements an interface. So this way, I will be able to type in in my document repository class. I will type in with this interface. And so this way, I will be able to change this factory with another one, which implements the same interface. So my document repository class now looks like this. As you can see, we have a dependency with media factor interface. So here I'm using dependency inversion principle and I'm also doing dependency injection because I'm injecting the dependency. This way, my document repository object just know about an abstract type, just know about the interface. And the interface says that we have this createMedia method, which takes a path and returns some objects. But the problem is, this method can return different type of objects. Image file, PDF file, text file, and so on. So I don't exactly know what is the real type of this file object. That's better. So if you at least want to make simple factories, you should do that in your own code. Okay, so it's simple, it's a very pragmatic approach. We have a loose coupling between document repository and the factory. We are leveraging the dependency inversion principle. We can easily switch the dependency with another one. So this code is following the solid principles. But it's still not a real factory method design pattern implementation because this object, this factory, returns different types of objects. So this is the real one, this is the real design pattern, which is called factory method. You have an abstract type, creator, which is the interface of the abstract class. And this method, operation, the public method, is usually pre-implemented in this abstract creator class. But this method, at some point, delegates to this protected factory method. This is the real factory method. This is the method that will instantiate the real object, the real class. But this method here is protected and abstract, and it must return some object that inherits the base abstract product type. And so remember that the pattern, the factory method design pattern, states that you have an interface and for defining the interface. But the responsibility of creating objects must be delegated to the concrete implementations. So the protected abstract method must be implemented by the concrete factory class, the concrete creator, which produces a concrete product, which extends the base product class. So the example I chose, you will see, is a media management system. I would like to be able to analyze media files like pictures, movie clips, and let's say sounds. And I want to be able to extract the metadata of those files, let's say, to import them somewhere in the database for storage, for instance. And I want to make it in a way that my system is flexible if I want, at some point, to analyze PDF files or Word files or whatever kind of files, without making too much changes in my code. So I can use this pattern to do that. This is how it looks like in the end. So this is the UML diagram. We have the abstraction, the abstract media metadata factory, which produces metadata objects. And so every file on your file systems share common stuff, like a name, a path, a size, a creation date. But depending on the file type or the file type you will analyze, you will want to get more specific metadata. For instance, for a picture, you want to retrieve the size of the picture, the width and the height. For a movie, you want to get the duration. You want to get the number of frames in the movie. For the sound, you want to get the bit rates and the duration as well. So this is why those classes will also allow you to know the extra specific attributes of the files. And so as you can see, my image metadata factory object, this factory will only produce this type of object. And this one will produce this one and this one will produce this one. So one factory creates one type of objects every time. If tomorrow I want to analyze PDF files, I will create a new class, a new factory class, and a new PDF metadata object. So two classes to create. But I will not touch the existing classes to not break the code. So this is what I want to achieve. I want to have an image metadata factory object which delegates to some analyzer object to analyze a picture. And when I load the metadata for a file, it returns an image metadata object which extends metadata. So these methods are the one taken from the base class, the base product class, because they are shared for every file. And those methods are specific to the image metadata class. And that's the same if I want to analyze movie clips. I have a movie metadata factory which has a video analyzer object and which produces a movie metadata object. And from this object, I can get the duration, the resolution, the frame rate, and so on. So this is basically how to achieve it. You have these base product class. This is the base metadata class, which defines all the shared attributes for every file. Then we have the abstract factory class, which defines the methods, which is this one, load metadata. This is the public method. And as you can see, at some point, we call this protected abstract method, which is implemented by every factory implementations. And this creates metadata method here is abstract. And it's delegated to every implementations. So my image metadata factory class will simply implement this method. So this is the class that defines what's an image. So an image extends the media metadata class. And I also want to store the width and the height for an image plus the getter method to read those information. And so this is basically the factory class. This one, image metadata factory. I implement create metadata. I will analyze the file with my injected analyzer. And I will simply instantiate image metadata. So the initialization of this object is centralized in the factory. And everywhere I need to analyze images, I will inject the factory to ask the factory to load the metadata for an image. So this way, I can easily change the algorithm to produce an image metadata object at some point. This is the analyzer class, which just uses the get image size function of PHP to read the data. And in return, they simply PHP array. And then I'm using it to read the width and the height. And so then you can repeat this for every other factory, for the movie factory, for the sound factory, for the PDF factory, and so on. So as you can see, with this powerful system, I can make my system much more flexible. If tomorrow I need to support PDF files, I will just have to create two or three classes. The PDF factory, the PDF metadata, and the PDF analyzer object. But I will not change the existing classes in my system. As a downside, you create many classes. So you make your code a bit more complex. So this design balance fits very well for complex applications or for frameworks for instance, because frameworks need to be very flexible. And this is why in Symphony we also use this design pattern to make the framework flexible. All right, makes sense? Good. So now the structural patterns, I will show you these. Two patterns, the composite and the decorator. The family of structural patterns allows you to make your code flexible in a way that implementations will be separated from their interfaces. This way you can easily replace an object by another one, for instance. Or you can easily extend an object without changing the code. So the first one is called composite. This one is very simple to implement. A composite object allows you to treat single objects or collections with the same unified API. So it's very useful whenever you have recursive representations or nested representations like file system, file explorer, where you have directories and files and the directory can also contain subdirectories and subdirectories and so on. If you have to parse an XML file, for instance, because an XML file has nodes, which contains nodes, which contains nodes and so on. In Symphony we use this pattern a lot in the form system because the form class can have nested forms, you can create complex forms. And so when you submit a form, then the main rule form will call the submit method on every of its children. And each child will also call the submit method on its nearest children. So the operation is recursively applied to the whole form tree. So this is what it looks like. You have an abstract type called component. It can be just an interface or an abstract class. You have a concrete object, a leaf, and you can create a composite and the composite can contain any component, so any leaf or any other composite. So you can have this, for instance, I want to use my concrete object and perform this operation on my concrete object. I can create a composite, which combines two leaves objects. And so the operation method will iterate over the leaves and call the operation method on each leaves. They can also inject the simple composite into my super composite because I can have composites of composites. So this is how this pattern works. So it works well for collections. And so in my system, in my example, I would like to make an e-commerce website where I want to be able to sell products, physical products, digital products, or combos. So I want to be able to sell a combo of products for a cheaper price, for instance. So this is how it looks like. You have the base product class. Each product has a price and it has a mass. As you can see, the mass and the price are represented as objects because it's easier to manipulate objects than manipulating scalar values or floating point numbers, especially for prices. And so each other class extends this one and you can see the combo is, it combines, it encapsulates any numbers of products, which can be our product, physical products, or other combos. So this is the base product class, which receives a money object to define the unit price and a mass object to define the mass in grams because I want to be able to know what's the total mass of a combo, for instance. This is my digital product class. A digital product, this is not something that you want to chip. So it doesn't have a mass, just something that you can download on your machine. So the mass is zero gram. So I can create my art product, which has a price of 49 euros and 960 grams, for instance, for the paper book. I'm using object here because this way I can easily, let's say, use or define the masses has grams or kilograms or whatever and the object will normalize everything to grams so that it would be easier to add masses together. And so a digital book doesn't have any mass, it just has a unit price. This is the combo class, this is the composite. Combo is the composite object. So it receives an array of product, this is the product that we want to put in the combo and I can choose whether or not to pass a unit price. If I pass the unit price, that means this will be the price for the combo, whatever the prices are for the inner products. If I don't pass any price, then by default I will calculate the total price of every product in this combo. All right, so this is what this method does, get total price. Same for the mass, I want to know what's the total mass of the combo. If I want to buy, let's say, a TV set and a PlayStation then I want to know what's the mass of this combo if I want to make it cheap to the customer and how it will cost for the web shop to pay for shipping it. So as you can see, my total price method here calculates the prices and as the price is an object, it's a money object, we have an add method. So I can add money objects together, I can add money A with money B which returns money C, which is the sum of money A and money B. And I can repeat the same for the mass. I can add a mass with another mass to get a third mass, which is the sum of two masses. So I don't really use scalar values, scalar types in my system, I always use object even for very simple concepts like monies and masses. So for instance, I want to create a simple combo here. This combo allows you to get a digital camera with the bag and the SD card for this price, so 803.39 euros, so the price is in cents because it's easier to deal with cents instead of euros, especially if you want to, let's say, let the customer pay three times without any interest, for instance, and you don't want to use any sense, you don't want to lose any sense in the payment. So this is why in the money design pattern, we always express the amount of money in cents. So that means this combo is sold at this price, so we don't care about the sum of every single unit pricing. But if I don't pass any price, then the total price will be the sum of every prices in the combo. And I can also make super combos, so combos of combos as it's a composite. So as you can see, we have the first combo, which is this one, and I also want to add an extra product to make another super combo on top of it, which I will sell with this price, or with a custom price. So as you can see, this design pattern allows to make your code very flexible when you need to make the same operation recursively on an object and it's children, right? Make sense? Now, the next one is probably one of my favorite design pattern, the decorator design pattern. As you will see, the decorator design pattern is very similar to composite. It looks like composite because it uses composition of objects, but it solves a very different intent or a different problem. The decorator design pattern allows you to extend an object capabilities without changing its class. So you don't want to change the class of the object that you want to extend, but you want to create new classes to envelope or to wrap the object that you want to extend. This way you can make any complex combination of decoration. And so remember when we talked about solid design pattern, the solid principle, we should not have classes with thousands line of codes, so this is why I don't want to, this is why I will use decorator design pattern because this pattern will force me to create new classes for every new responsibility that I want to attach to an object. And it also allows you to follow the open-close principle. Again, you don't want to touch the existing class if you want to extend the class. You want to create new classes and envelope the object to dynamically add new capabilities or new responsibilities. So you can hear about decorator, that's the original name. Sometimes you can also read wrapper as the other name for this design pattern. So this is how it looks like. As you can see, it's pretty similar than composite. The thing is we have this abstract decorator class which wraps a decorated component. And the decorated component can be a concrete component or it can be a decorator because we will type in with the base abstract type, which can be an interface or an abstract class, for instance. And then the operation method from the base interface will then do some stuff and then delegate to the operation method of the decorated components or the wrapped components. So this is how it looks like as a usage. You have your real components and you want to extend it. You want to add new dynamic responsibilities to this object. So instead of modifying this class, you will basically create a new class that will decorate this object and that will reimplement the operation methods. You mainly encounter this design pattern for logging, for instance. You have an object and you want, let's say you have a database object which performs database SQL queries and you want to be able to log the SQL queries made to your database. But you only want to log when you are in development environment. You don't want to log when you are in production environment. So instead of injecting a logger object in your database object, you will create a profiled database class which is a decorator for the original database class. So this way you have your database service for production environment and you have a profiled database service for your dev environment which wraps the original database object and which also receives the logger object to log any SQL queries. The example I chose is this one. Again, in my e-commerce system, I want to be able to let people use coupon codes to discount their orders. And so we have two type of coupons. We have rate coupons, so I want to get 15% off on my order. I want to have a value coupon, so minus 50 euros on my order. But to make those coupons eligible, we have to respect some conditions. For instance, the coupon is only valid for a period of time or the coupon is only valid for some very specific set of users or the coupon is valid on some very specific products in my shopping cart, not every product, right? So you can imagine all the ideas of restrictions that you can apply to a coupon. But the difficulty is that I want to make them cumulative. I want to create a coupon that I will give away to the people and I want this coupon to be valid for a specific period of time, but also we need to have a minimum amount of purchase amount in the shopping cart. And I want to give this coupon only to my premium customers, right? So how can I achieve these complex combinations of coupon restrictions? Then I can use the decorator design pattern in this case. As you can see, we have the base coupon, the coupon interface or the coupon abstract class. Each coupon has a unique code and we have a method to discount an order object. And so if I'm acting on a value coupon or on a rate coupon, those two classes will simply apply the discount on the order object. But if I want to add restrictions, then restrictions will be handled as decorators. So this is why we have a coupon decorator which is a restriction decorator. And this abstract class wraps a coupon object and it overwrites or re-implements the get code method. So the get code method simply delegates to the wrapped object. But the apply discount method has to be re-implemented by every single restriction class. And so what we will do is that if the condition, if the restriction is not valid, then the apply discount method will simply throw an exception or it will simply just do nothing on the order object. Otherwise, if the restriction is valid, then we will ask the next decorator to be applied which can be the value coupon, the rate coupon or another decorator. So we'll simply forward the method code to the next object, right? So for every restriction, you need a new class. Again, you will not change the order class, we will not change the coupon class. You just want to create a new class whenever you need to implement a new restriction for your coupons. So this is the value coupon. As you can see, the value amount for the discount is a money object. Again, I'm using money object because it's easier to subtract this amount of money on another amount of money. And so when I apply the discount, I will simply tell the order object to discount is it's total amount for this discount value. The rate coupon does mostly the same thing except that we have to calculate what's the amount to debit based on the rate that we have initialized in the construct method. And now we have the decorator, the decorator object, which is an abstract class. As you can see, the decorator wraps a coupon interface so it can be a rate coupon, a value coupon or any decorator object. The gate code method simply forwards the method code to the inner objects. And then I will have to implement the apply discount method in every concrete classes. So this is the first example, the limited lifetime coupon class. So this class in the construct method must wrap a coupon. It must wrap a coupon. And we also tell what's the begin date and the ending date for the validity period of this coupon. So I'm just checking that the validity period is fine. And then my apply discount method will check that the current date is between the validity period. If the coupon is expired or if the coupon is not yet usable, then I will throw exceptions or I can simply just do nothing on the order object. Otherwise, my job is done. So I will simply move or I will simply forward the method code to the inner coupon object. And this one would be able to apply the discount if it's a rate coupon or a value coupon. If it's another decorator, then the decorator will check for the restriction and then move forward to the inner objects. Okay, so I have my limited lifetime coupon which decorates a value coupon. And so I want to discount 20 euros on another object. And this one will discount 25% on the order object if we are using the coupon on this lifetime period. Okay, this is another one. The minimum purchase amount coupon decorator. So you need to have a minimum amount of ordered objects in your shopping cart to make this coupon eligible for discount. So again, I'm wrapping a coupon object and I'm telling what's the minimum amount of money we need in the shopping cart to make this coupon eligible. And as money is an object, my money class has a less than method so that I can compare two money objects together. So I will check that the amount is greater or lower than this minimum amount. But I will also check the currencies because if I have USDs compared to euros, that's a clash. So we'll have some currency mismatch exception at some point, all right. Otherwise, if we have enough amount of money, then we can forward the method call to the inner objects. Okay, so again, this is how you can use this. You can use this class minimum purchase amount coupon which wraps a value coupon or a rate coupon. But now with the decorator, with this system, I can also make things much more complex. I can have a value coupon which is decorated by a limited lifetime coupon which is decorated by minimum purchase amount coupon which is decorated by customer first order coupon. So you can imagine any complex combination of restrictions for your coupons. And then if you want to go further, this is the way you can use it. But if you have, let's say, an admin system to let the administrators create coupons with restrictions, then you can store this metadata in some storage engine like a database. And then with a coupon factory patterns, you could then reassemble the whole coupon restriction sets within a factory. Okay, so you can combine decorator with factories to make super great design pattern implementations. All right, so the decorators, as you can see, it allows us to leverage the single responsibility principle because we have small classes which are focused only on what they have to do. We don't change the existing objects. So we follow the OCP principle, open-close principle. We can make any complex combination of restriction sets. We can also decide in which order we want to apply the restrictions, okay? Sometimes it doesn't make sense for our use cases. We can, for instance, switch the order. Doesn't really make sense. Sometimes it may be important to have one decorator to be executed before another one, especially when you do caching, for instance. We can use the decorator design pattern for caching. You have a REST API object, and you want to cache the result of a REST API. So you have a cache, cached REST API decorator. And on top of this cache REST API, you want to have some authorization layer so you can have an authorized REST API. And so by decorating the layers, you will be able to make your REST API more flexible. Some downsides with this pattern is that as you start decorating, the variable you will use, so in this case, the coupon variable is now a customer first order coupon. So it's not a rate coupon, no a value coupon. So I don't know the real decorated object anymore. So I can't use instance of keywords in my code to check if it's an instance of rate coupon or value coupon because it's decorated. So that can be a limitation for your code. Also, if you have classes with lots of public methods, and if you want to decorate this object, then you have to, for every class, for every decorator class, you will have to reimplement all this method and make the forwards method calls. So you may end up with some code duplication at some point. Also, the decorator design pattern doesn't work if your object returns itself. So if you return this in a method, then you break, you will break the fluent interface that you designed by default. Yeah, so that's the main limitations of this design pattern. All right, 15 minutes left. Make sense? Good. All right, so the last one, last design pattern, which is a behavioral design pattern. So as I said, the behavioral patterns family is a set of design pattern which help objects communicate with each other, and they will also leverage decoupling. So the goal is to achieve decoupling between your objects. So you have all these patterns below. For instance, the strategy design pattern is very famous. You probably already know about it, or you probably use it already without knowing. Remember, in my first slides about the factory design pattern, when I've injected the media factory interface in my document repository, that's basically a strategy. So I also used a strategy design pattern. If you use Symphony or Drupal, maybe in Drupal 8, you probably use the event dispatcher component to dispatch events or to connect listeners to events. The Symphony event dispatcher is an implementation of this mediato design pattern. This is a mediator. The pattern I will show you is the visitor design pattern. So the last one, it's one of the, the one that is the least known pattern, but it's very easy to use, as you will see. So basically the visitor design pattern allows you to decompose an object which has data and operation. So basically you will move all the operations into separate classes, and you will just keep the data in the class. So this way we have the data objects and operations has other objects. So this is what it looks like. You have the objects that you want to visit. So this is the visitable objects which can accept a visitor as an argument. And the visitor concrete object will visit the element. So basically when the element, when you call the accept method on the element you want to visit, then this method will simply just make one single statement which is calling the visit method on the visitor and inject itself into the visitor. Okay, so as you can see the accept method takes a visitor. It simply calls the visit method of the visitor and injects itself so that the visitor knows about the visited objects. Well, this is what it looks like. You have your object, your concrete element, and you want to perform operations on this object. So you can then accept any visitor implementation in your visit method, visitor A, visitor B, visitor C, and each visitor does things with your visited objects. So this is my last example. Consider a shopping cart in your e-commerce system. And so in your shopping cart you can push products. So for each product you have some names, some quantity, some unit price. And so in this shopping cart object, so this is how I want to use my shopping cart. So I want to add products. So I want to order three bottles of shampoo. I want to order one kilogram, 38 of salmon, and this is the unit price per kilogram for the salmon, for instance. So this is my shopping cart. And when I check out my shopping cart, I would like to know the total price of the shopping cart or I would like to print a receipt or I want to generate a receipt as a PDF, for instance, or I want to reorder the list per category, or as you can see we have the categories for each product. So in the receipt I want to have all the product ordered by categories. So naively I could do those operations in the shopping cart class. I could have a method to get the total price. I can have a method to resort to the shopping cart by categories, or I can get a method to issue the receipt. But as you can see, this method, for instance, issue receipts doesn't really belong to the shopping cart. Basically, you don't want to have a strong coupling between a shopping cart data object and some PDF generator objects. This is a side operation that you don't want to directly do in your shopping cart. And if at some point you want to add new operations, let's say you want to discount the shopping cart because we have a loyal customer, then that means you have to add a new method to this class. Remember the open-close principle, you should not change the class if you want to extend it. So this tells me that I should move these operations somewhere else in my system. And the visitor design pattern can help us to achieve this. So basically my shopping cart object will simply store the list of ordered products that basically what we have, and some public get a method to read these list of items. And I will implement my accept method, which can accept any shopping cart visitor object. And so the visitor will visit the shopping cart, so shopping cart inject itself into the visitor. And so for each operation will be a single visitor class. So for instance, we have the total price cart visitor, which is the total price calculator. So when we visit a shopping cart, then we iterate over the items of the shopping cart and for each item we calculate the total, subtotal price. So the quantity times the unit price. And then we add it to the main total, okay? And so the main total has been updated. So we have a new money object. So I erase the previous one and update the new one. And we have then a get total price method that returns the computed total price. As you can see my visit method returns void. There is no return value because as we can have different types of visitors, we can't define in the interface what could be the return value of the visit methods. So this is why your visitor must store the computed values, has properties and then offer get a method to read those values. So the visit method just does things but it doesn't return anything, all right? So I have my shopping cart, which is populated with items. And then I want to get the total price of my shopping cart when I check out this shopping cart. So I will accept a visitor. The visitor will calculate the total price and then I can ask the visitor, what's the total price of this shopping cart? And that's done. If I want to test this class, it's super, super easy because we just have 25, 30 lines of code in this calculator visitor. Same if you want to reorder the list of items per category to display them on the receipt, for instance. Then again, I will create another visitor which will do this operation and it will update this attribute and I will have a get a method to read these attributes. And again, I can accept this visitor which does what it has to do and then I can get my list of ordered items per category, done. I can unitize this class separately without changing or without touching the other classes. So as a conclusion for this visitor and for the end of the conference. So the visitor design, as you can see, it's very simple. You just have two interfaces, the visitor and the visited object. So it allows you to separate the data, the data objects for the shopping cart, for instance, which contains data and the list of operations you can apply on these data objects. Operations are implemented as visitors. It encourage you to follow the single responsibility principle because you create new classes for every new single responsibility or any new tasks. Again, we don't change the existing shopping cart class. So we follow the OCP principle. We just create new classes for extending the shopping cart, for dynamically extending the shopping cart. So we now have loose carpling because my shopping cart doesn't know anything about the PDF generator. If I want to generate a receipt as a PDF, I just create a new visitor but only the visitor knows about the PDF generator, not the shopping cart object. So we have loosely capital code which means less HKCs or less problems when you make a change in your code base, less frictions. Some downsides of the visitor design pattern is that your visitor object must be mutable which means they can only be used once per visited object. So you can't reuse a visitor after it has been used by a visited object. Also you should not mutate the visited object inside a visitor because if you have another visitor running after the first one then it may have a state that is not coherent for the algorithm. So the visitor should only read the state of your visited object but not mutated. Which also means that your visited object must expose its public state, its public API. So you must expose with getter methods. And finally, we can't use what we call double dispatch if you read articles about this visitor design pattern. You will learn about double dispatch. Double dispatch is not supported in PHP because we would need to have polymorphism. Polymorphism is when you can define the same methods multiple times with the same name in the same class but with different arguments. So in this case we can only have one visit method but not multiple ones. So we can't use double dispatch in PHP. I think I'm done. So thank you for your attentions. I hope you enjoyed the conference. The slide date is already online on my speakerdeck.com slash H-H-A-M-O-N. You will also get the slide date from Drupal website. We have three minutes for questions. So yeah, there is a microphone. Yeah, hi, thanks. It's a great talk. So the decorator pattern, I noticed you're throwing exceptions. Uh-huh. I thought that was throwing exceptions but actually writing behavior against it. So I thought like you're not gonna do that. Is that kind of inherent part of decorator that you have to throw the exception and then... It's up to you if you want to throw an exception and then catch it to do something or if you just do nothing, you just forward the method code. If there's nothing, there's nothing to do. It's up to you. Okay, so it's acceptable too. Yeah, cool. Thanks.