 Is it working? Hello. So hi everyone. Is everyone ready to start? Okay, so Welcome to this workshop about dependency injections and design patterns Great to see so many of you here. The room is cool. This is for us. It's great to see this workshop today is We started to to introduce or maybe craft a bit better to Let you introduce you design patterns a better programming for me personal. I'm a developer And I've been working with WordPress for a very long time But I sometimes miss the things I see in other frameworks like Laravel or symphony But simply because I work with WordPress so much I don't get a chance to really exploit the cool stuff that happens there So this is why me and Elaine I've started this workshop Some some minor things we are short on power supply so we might Have to ask in the in the break if we need to reschedule some people if you're out of power So if you are near a socket Try to work on the socket now so that the rest of the workshop you can do on your battery Sorry for that So about this workshop What we wanted to do is is do something that might be useful in real life. So we're not gonna do Ducks or or cars or something like that. We're gonna work on something. That's actually useful The workshop is Is done in pair programming. So the person you're sitting next to is gonna be the person you'll be working with during this workshop What we're gonna do is we're gonna fake a project and we're gonna introduce business requirements and What we're gonna do is we're gonna discuss this requirement And we're gonna explain what the requirement is and what kind of design pattern or php standard thing could help with this And then we're gonna actually work on it for a while See what kind of solutions you come up with discuss with your partner and once you Once the time is up. We're just gonna present like this is how we did it and we'll discuss Why we did it and how we did it so that way you're not just gonna see Design patterns on the screen. You're actually gonna work with it and then see and working example of it So What are we gonna work on today? We're gonna build a Gutenberg block from And it's gonna show you social mentions So we're gonna build for example a Twitter block and it will are based on if you type in WC IU is gonna Show you all the tweets that are happening about the WCU We we're gonna do just a server-side rendering. So it's be it's gonna be php only we have Abstract everything a way that has to do with Gutenberg. It's in the code so you can see how we've done it, but You'll be just focusing on the actual code implementation the pure logic that's required to solve the business requirements So we're gonna start with the first business requirement We're gonna we have a client fictional and he wants a Gutenberg block that just that shows Twitter mentions So You can read what it's what it's about to do what we're gonna build so I'll give you a few seconds you To read it. I was it So and then we're gonna do the exercise the first exercise is really a thought exercise because we're gonna also use this time to set you up The requirements for this workshop are a working laptop. We're gonna do We're gonna do we need a fresh WordPress installs. You need some sort of local host working and then we're gonna help you through the authentication With the WordPress and a Twitter Gutenberg APIs. It's it's all being automated. So it should be like really 10 minutes We have some TAs over there that will help you Okay, that's some TAs hidden there as well they will help you set up with this Do we have you okay Okay, okay, can you go to the github page of Ellen you will put it in So does everyone have a local host running with a WordPress install if it's a fresh install is the best Because we're gonna add some pages and stuff and it's gonna help if Yeah, so This one has read me this I Take go to the to the repo and Process the read me it says there are what the steps are which what which are required It will we're just gonna use five to ten minutes to set everyone up now and then we can actually Start sorry, it's the wrong one So if you have any questions on setting up WordPress or repo or anything just raise your hand and We'll we'll try to sort it out for you. I'm just gonna take like a five to ten minutes for everyone to set up So just to state the end result should be that you have Installed two plugins that you got from github as Explained in the github repository and activated both of them So for those who are ready you need a wordpress.com account and you need a Twitter account for this workshop Once you have installed those plugins or when you activated all three of them and you go to pages You'll see a few pages that should be generated In in WordPress The pages themselves don't contain any content But if you view them on the front end you'll see you'll see actually some rendering done What what everyone should do is is create a Twitter app and create a wordpress.com app Then once you've done that you can use the page that helps you Generate an open-out token for WordPress comm and once you've done that you can go to the github branches page And then everyone is set up and good to go If you have any questions or trouble just just raise your hand will one of the TAs or myself or Ellen will help out So So these are the pages that you should see and just by viewing them you'll have a brief tutorial on On what to do the nth.php file you can find it in the WCUO 2018 resources plug-in You have a file nth.php there and that's where you'll have to place those tokens So in the meantime for those who who don't use Composer all the time The reason that we're using it here is that we set up auto loading Using Composer so even though for example the resources plug-in it doesn't load in any external dependencies We still use it so we don't we don't require our php classes by hand We just instance new class and Composer takes care of the loading of it So just a quick note Because it might be something that other people are struggling with If your domain that you're using on local machine happens to contain the word wordpress Then this will not work work to create wordpress.com API app because they think you're infringing on their trademarks This will not work. You need to use a domain that does not contain the word wordpress the wordpress.com API Authentication is also Optional so if you really have trouble getting it to work We can still continue with the workshop you will get pretty weird results if you're not Authenticated because it just uses whatever local cookie it finds for your user and gives you random results based on that But the workshop itself will still be able to to to work forward so We need to move on you can continue working on this While while you're trying to get everything set up We need to slowly move on because we want to cover a lot so The git branch that you see printed here. That's the first step in the code that will Provide you with the clean Gutenberg block where you can start implementing your Twitter client But we will not have the time to actually work on that first implementation So we will move on from there But this is actually the code that would provide a clean Clean canvas from which to start the actual server side implementation so We we just assume now that everyone has this Gutenberg block Running with the first requirement all fulfilled with a Twitter API request that fills it with with the mentions on Twitter And now our client all of a sudden gives us a new business requirement. We need to add a second feed So we only planned in the beginning to just implement a basic Twitter API Access so We might even have hard-coded all of the Twitter logic into our code into our block Now the client needs to and needs us to add a second feed to this So this is why we Already requested two different APIs for you to authenticate with the client now requests us to use WordPress.com as well Side-by-side with Twitter so the Gutenberg block is meant to let you choose which network to show The mentions in and then you can dynamically switch between these two the second feed should pull this data from WordPress.com and we want to have the Conditional code be kept to a minimum So we don't want to have a big if else clause where where we basically duplicate the entire code path For doing the remote request and do it once for Twitter and once for WordPress.com. We want to be smart about this That's where Some of the first patterns come into play first I want to talk a bit about instantiation So instantiation is one of the most fundamental aspects of object-oriented programming you create classes and then you can instantiate these classes to have objects and The way you instantiate something controls the coupling between your objects and controls the life cycle of these objects, so Instantiation is is something that should That should get a lot of thought and effort from you to really use it in the best possible way There's a few ways you can instantiate something the most direct one is to use the new keyword in PHP So you just do new and a class name and you get an instance of an object in return And the this This causes immediate coupling to the class that you instantiate it So if you do a new My shiny class then your code is immediately tightly coupled to my shiny class and Cannot easily use any other implementation without first changing that code You also need to know what the constructor arguments are which Oftentimes is pretty simple, but sometimes the constructor arguments might be very complex They might be a lot of work to actually prepare them Step forward from using the new keyword is using named constructors So instead of having the new keyword and one default constructor you can have multiple constructors that create Maybe multiple variations of an object or maybe you have different arguments to create that object so that that allows you To have more control over how something is an instantiate and maybe automate some steps or do some validation etc and Then a step further away from this we get our first pattern, which is the simple factory The simple factory is a pattern that lets you get the instantiation of something of some object Away and put it into a different object so that that object has as its sole responsibility To instantiate another object That might sound a bit Useless at first. So why would I need two objects to instantiate one object? The point about this is that this simple factory can be passed around The simple factory is an object in its own right. So can have its own logic You can you also have this logic encapsulated so you can change the way something is instantiated after the fact after it was Used in some other place of the code and that other place does not need to be adapted So you've put away the exact way of instantiating something so that you have one central place of Changing it in case you need it Here's an example of how such a simple factory could work This is not necessarily the exact code that We would use in a good work block. It happens to be similar here as an example We have social network interface and multiple implementations of this interface and instead of Immediately instantiating a specific implementation We create a factory. This is the simple factory pattern. We create a factory that lets us abstract away the decision process of deciding which implementation to instantiate And here at the bottom you can see how this is used Let's say we have a function that that we pass some string to to denote which Network we need this string might for example be an option in the database or The value of an input field and then we get just past this to our network Factory and the factory then returns Some implementation. We don't need to know which implementation that was returned That is not needed at this point and whatever implementation we get we just use its rendering method so Given that you have multiple ways of instantiating something When should you use the new keyboard? keyboard keyword Because most of the time People just default to the new keyword and use it for all the instantiations that they need The new keyword should only be used for newable types, which is types that That are meant to be instantiated on the spot immediately Exceptions would be an example of this Value objects would be an example that for example the daytime Object you will not create a factory to create implementations of daytime. You will just use it as is And inside of any type of factory, of course you can use the new keyword and ideally the entire rest of your code would not have the new keyword anywhere and as an effect not have any tight coupling to the decisions that are Need that need to be made of which which implementation to use for which interface what comes along with Working with these objects is dependency injection We will have several different examples throughout this workshop of how dependency injection is used I want to start with a quick explanation of it So dependency injection is basically instead of Requesting a given Implementation from within a code. You just have it be passed into the code from the outside from the surrounding code The this Sounds very straightforward, and it basically means in most of the cases that your object has its dependencies Injected through constructor arguments, so when when you instantiate an object, and it needs dependencies Then you instantiate it by immediately passing it the dependencies it needs so that the object does not need to ask for these dependencies itself Here you can see a code example First we have The way of how not to do it We have the mysql database object, and we have some service that immediately instantiates directly instantiates this database and then uses it This is now a very simplistic example, but imagine that you have hundreds of these services which come with direct implementation Access to this one mysql database and now all of a sudden your boss wants you to change to oracle And you have your entire code base riddled with direct references to this mysql database So that's why we want to inject the database instead Here's a simplistic example of this. So we just Sorry, we just have the mysql database as a constructor argument and whatever we get We just store it and make use of that stored version This looks like it's still the same the same code as before, but there's an important distinction if we now extend this mysql database we can just Inject the extended version without this code needing to change because it doesn't include any direct reference to it and As you might even Imagine right now if you use an interface here instead of An actual class then you're even more flexible. You can just have any implementation of that interface being injected So what that causes in the end is the code you're writing it It is very cowardly in that it just defers technical decisions instead of Immediately needing to decide okay, which database implementation do I need we can just say okay This code will work with some database and we don't care which one it is yet We just care about which which data we retrieve So the decision on which implementation to use is deferred to a later moment So we don't need to deal with this decision immediately This also means that the code that we've just built does not depend on this decision and if this decision is ever changed in the future, we don't need to adapt our code because It didn't rely on that decision from the first place and if we now Think through of what that means for our entire application You can say that dependency injection always moves the instantiation of dependencies one level up But it can do this recursively Across the entire object tree or object graph So normally your application is a very complex tree of objects that are interrelated and Dependency injection can move all of the instantiation. So all of the technical Implementation detail decisions Out of the leaves of this tree and up to the root and this is called the composition route So basically what we have is We want the new keywords to all be regrouped in one central location So all the rest of the code if we need to make a change in any of these technical decisions All the rest of the code does not need to be adapted We just make a change in the composition route and that's it. We're good to go Provided that we build the code correctly, of course So There's the next exercise and now it's getting a bit realer So the branch you want to work on is to feed me we want to add the second feed to the code and We want to do this using a simple factory implementation of the same go simple factory pattern and This means that We create a feed factory Which when given given a specific string like Twitter or WordPress Will return an instance of the application of the implementation to use so Do a checkout of the branch to feed me look into the code It already contains an implementation of the Twitter feed and You can think about what you need to change now to add the WordPress.com feed When someone pointed out that it's actually important that you actually use the git repo and not download the zip Because you won't be able to to switch branches If you You can find that one of the pages I created Where they were created they contain all the branches for today, and they also have a tutorial on how to To swap between them also my bad the WordPress out of occasion was a buck so I I typed something wrong, which This why you couldn't authenticate. So if you For though it's optional. I'm saying now you if you pull in the resources the latest version You should be able to authenticate with WordPress again. It's not required, but it does give you proper results Also some some small hints. There's a there's a class called plug-in in the code It it it explains what we're doing here So if you go to the plug-in class, you will see what we're doing and that's this is a good point to start working Just just with your co-worker Start working on it If you have questions, it doesn't matter our hesitations. Just raise your hand. We're here to do something interactive We're gonna work on this for like 15 to 20 minutes Okay, so I see you all busy. I hope it's busy with discussing the solution not the authentication still We'll move on just again the authentication is That the worst case is that if you have no Twitter Authentication You will get no results from Twitter and if you have no WordPress.com Authentication you will get random results from WordPress.com but still get results So you can still use the block for the for the further work. So that's why we added that API as well So we're moving on now to the To the next step. So in comes our client and It has a great idea It's very expensive to run all the updates of this server-side Render block all the time. So the client wants us to add caching to remove some of the bandwidth That is being used by all the time updating Now This is where The design patterns and the object oriented approach and depends injection start to become very Interesting. So first of all here's the business with crimes. We have we want to do some short Short-term caching five minutes just to avoid doing a lot of remote requests at the same time But five minutes is so short that it still seems to be updated in real time We want to implement this caching Without changing the feed implementation So we don't want to go into the Twitter feed and add caching and then go into the WordPress.com feed and add caching That's not how we want to work So we want to just leave the feed implementations as they are without any single line of code changed We also want to implement this caching Without changing the code that consumes the feed data because we might not even be aware where this code is used In the code base. So there might be several different places in the code where the feed is being used for rendering or whatever We we're not sure so we prefer to build something that does not require any changes This is where the decorator comes in the decorator is another pattern In this instance, we're using it for caching So a quick mention about what caching Represents in terms of a software engineering concept caching is something that we call a cross-cutting concern a Cross-cutting concern is something that is very difficult To put into one single place in your code base and just say okay. This is the corner where the caching is It is a cross-cutting concern because it it cuts through all the concerns of your code and is Oftentimes something that needs to be done to all sorts of places of your code That's what makes it so difficult To do it properly another type of Cross-cutting concern would be logging for example You don't look in one corner of your code when you add logging it's to lock the rest of the code to know What's going on in there? so these are cross-cutting concerns and When we want to add cross-cutting concerns in such a way that we are still Adhering to all the principles we want to adhere like the single responsibility principle or we want to keep all the concerns separated Then this is where the decorator comes in the decorator adds a New responsibility to an existing object without changing that of the object and it does this By wrapping the existing object and attaching its own code in the same way so it interjects between the producer of something and the consumer of that same thing and To show you how this would be displayed visually Let's imagine that this crook line, whatever it is Let's imagine that this is an interface. So the interface has a Specific shape and whatever we build to implement this interface. It needs to match this shape So when you have an interface normally tells you okay, you need this and this method And so any implementation also needs to implement this and this method Here's our interface. We have producing code. That means code That actually implements the interface and produces what the interface is meant to return And we have consuming code that uses whatever Implementation you've provided to to implement this interface and now when we're talking about a decorator It means that we split this up without changing them. We just split them up We put a decorator in place which Accepts an interface of the thing we want to decorate and the decorator implements the same interface as well So it acts as a as a middleman and neither the producer nor the consumer Have to change. They just never noticed that something else happened and Here's an example now of how this would look in code So we have a data interface And we have a renderer that accepts an implementation of this data phase a data interface and Fatches the data and returns it very simple code We have one implementation a remote data implementation of this data interface That does remote request when you when you call it's a get method And here you can see how the code is being used. We instantiate remote data We inject the remote data into the renderer and when we call the renderers when the method It will do this remote request So now imagine we want to add caching in there The straightforward forward approach would be to add the caching in here The problem now is though we needed to change our implementation Maybe that implementation was not even part of our code. Maybe we just pulled this in as the third-party dependency through composer Also now this remote data it does two things it does remote request and it caches the remote request so Out goes the single single responsibility principle So the way we want to do this is actually a different one We create a create a new object That only deals with the caching and that object is a decorator So that means the object accepts an implementation of our interface and It implements the interface as well We can see here that our remote data is clean again. It doesn't need to change just to add caching And here you can see how we use it We have our remote data implementation and we pass it into the cache data So we wrap the remote data with a cache data and the renderer can then still Accept this because it does not notice the difference between Direct remote data or cash direct cash remote data So if you call renderer render it still does the same thing and it never notices that we've introduced A middleman that added the caching This has a few Benefits one is that you can apply this to code that is not your own third-party code you pull in as dependencies which means that you can Consider a lot of the code that you create that is reusable as just Third-party code that is not meant to be changed which means it makes maintenance easier. It also means that When we add testing to our code Basically as long as we don't make changes to tested code We can always just assume it works and no don't need to bother with it. Don't need to Spend any thought on on it And the decorator Let's us add new functionality without Changing the code that was already tested that was known to work because as soon as we make a change There's no guarantee that that change doesn't break the existing code Here's a few tips of how and when to use the decorator As I said, it's especially useful for adding cross-cutting concerns, but that's not the only the only purpose But it's just it's a typical usage of it and The decorator also works very well when you have a central place where you decide What gets instantiated and how it gets injected into other objects? Because then you have one central place where you can inject this middleman and all the rest of your code will never notice the difference Here's next exercise So we want to add a caching layer Through a decorator this thoughts in the branch three cash is king So the feet object should be wrapped into a caching decorator so that we end up with a caching feet and We want to use short exploration transient caching for this So just use the WordPress get transient and set transit methods To to do the actual caching in this instance What time is available for this exercise? We have 20 minutes So again, it's mostly about discussing this and starting to figure out how to build these objects It's not It's no problem. If you don't manage to finish it The important part is the discussion and the thought process of how to go about this If you have written some code in the in the previous branch You can just switch to swap to this branch So you have to stash your results if you have the latest version of the resource repository It will show you one of the pages how to stash and then switch your branch Also in the last exercise we ask you to create a factory if you go to plug in Dutch php And to feed factory dot com dot com that php You will see the implementation that we wrote to do this So before you start with this exercise check check this branch out and once you've done it check out plug in Dutch php And feed factory so you can see what how we implemented the theory We discussed in the in the previous problem and then start on this one Just just a quick note again In case you need to break As our time is very short All always when we do exercises if you need to get a quick break if you need to go to the restroom So feel free to do it during the exercises and know that the completed code will still be there for you when you return So we don't have a specific time period reserved for break Okay We'll move on to the next step, but first of all I wanted to quickly show you What the caching feed should look like? so a Lot of you have already understood how the decorator works and could quickly build a first implementation of it So the important pieces of the team of the decorator is it implements the interface we want to wrap and it also accepts the actual Current implementation we want to wrap we want to add another behavior to and If we now scroll down We can see that Basically the interface is this get entries method and we still have this get get entries again get entries method, sorry about that and We add caching to it and if the cache misses We forward again entries call to the actual wrapped object instead that's the main main functioning principle of the decorator so Now If you want to see the solution in your own code, you can check out the branch three cache is king final But we will now move on We will now move on to our next business requirement So the client comes again comes in again and has a new idea On the production server We want to use object caching not trends in caching because the client now noticed that while trends in caching is not As good as it is hyped. So on the production server. We have something like red is Available some persistent object cache. So we want to use object caching instead Some requirements for for this new change The caching just should support different caching engines so Basically, we already noticed now that having one implementation is not enough We need to make the code more flexible and if you're already doing it then it's a good opportunity to abstract away Detail implementation of whatever caching engine we're using so we remain remain flexible in the future We also want to keep the duplicate logic to a minimum again and The consuming code should still remain completely unaware of what we did to change the caching So the exercise now is To keep the caching feed that you've built now you will probably have all version now if you check out the new branch Use this caching feed and inject a caching engine into the feed So this will show us that not only can we inject code and we can Use decorators, but we can also inject into decorators basically design patterns are meant to mix and match as needed you can Stack them you can wrap them in in each other you can use them in whatever creative ways you can think of So here we're using dependency injection to make our decorator more flexible The we should have an abstract caching engine We want to have multiple implementations and Then inject it into the caching feed decorator. You can check out the git branch for test me if you can Yet the name is a bit misleading because that was a different exercise at one point yeah, just use a branch for test me if you can and Try to create an abstract caching engine that you can inject Into the caching feed decorator 20 minutes for this and again if someone needs to use the restrooms or so does a good time to do so so we are continuing with the exercises a Quick note about the code we've built now if you check out the branch For test me if you can final you can see the implementation that we've built that was the end goal as we had As we had suggested it and Basically, we have created an abstract class caching engine which includes three methods a remember method a read method and write method With did it we we did it this way because an abstract class Can still be considered an interface? It's not an implementation because you cannot instantiate it But it already can come with default behavior that that you cannot That you cannot just skip and in this case the default behavior. We wanted to add is or Remember algorithm so instead of having just a read and write method and always needing to go through the entire steps of okay, let's do read if the read was If the read failed then we know the cache did it was a miss then we need to generate then we do a right etc So this entire algorithm if we only have read and write method in our caching engine We would need to do this algorithm in every single place where we use our caching and we wanted to avoid that That's why we have a remember method to abstract away this algorithm So we have it in one place And if we went need to we'd need if we need to do a change with that algorithm We can do that change in the one place and all the other places where we're using the caching We'll just use the new behavior and be good without any necessary changes Okay, I think we go to the slides yeah So the caching engine is then injected into our decorator Which means we can do this in one single location namely in the feed factory So the feed factory which already wraps or feed in a cashed feed can just provide the caching engine to the to the feed to the cashed feed decorator and This is this is all instantiated at the composition route and pass down the tree through dependency injection so the caching the caching engine if you go to the composition route We plug in so the caching engine is instantiated in one place and We inject it into the feed factory and the feed factory will inject it into our caching feed decorator So even if we might end up with a thousand places in our code that use caching We have one single location where we can decide which engine to use if we need to use another one It's one single change Okay, we can head back to the slides now So the last pattern we want to cover and we need to go a bit quicker now Because time is slowly running out Last pattern we want to cover is a strategy pattern so the strategy pattern allows you To abstract away an entire family of algorithms So you can easily switch them at runtime in whatever way you want without The rest of the code being aware of it This makes algorithms reusable and It also means that you can easily add new algorithms without any extensive changes in the rest of your code So here's an example of the strategy pattern. This looks a bit complicated now Basically, we have a user list that we want to sort based on several criteria We can sort them by phone by email and by name and as you can see depending on which criteria We want to use the algorithms are quite different between these and here's just a consuming code We load a CSV file. We add the users and then we can grab them by a sorted criteria Now to use the strategy pattern, we can basically do We can put the actual implementation of the algorithms into separate classes So here on the right side, you see the sort by name sort by email and sort by phone That all contain a compare method This is because we created an interface sort order that has a compare method to compare two users with each other and Now when we look at our user list and the function gets sorted by it's drastically simpler It's just a use sort. So that's a PHP Function to sort based on a custom callback that you pass to the function so we sort the user's array and we use our compare method as the callback and we even Injected Well, no, we didn't inject here, but we could inject so the criteria here is the one we get by the good sorted by Methods argument and we don't even know which one it is. We just know that it will be some algorithm to compare users and we just use it and When you look at the consuming code here You probably can't remember all of it, but I can attest that it's mostly unchanged The only thing that changed is that here our criteria is not some random string But it's an instance of the actual sorting criteria we want to use So that's the strategy pattern Which is also a very powerful pattern As you can see the code that does the actual sorting is very simple now and If you need to add a fourth or fifth Sorting criteria now. It's just a matter of Creating a new implementation of the sort order interface a few tips If you want to look at how to use the strategy pattern It's often if you see big switch statements or long if else chains that's often a good indicator that you can use a strategy pattern and You can also combine the strategy pattern with a Factory so that you don't oh, sorry so that you don't need to know the actual Class to use but can just defer this to a factory to instantiate it so we can have a random argument and instantiate the actual implementation through factory So the exercise then it's in branch five sorted out Introduce an ordered feed decorator Which should sort the entries based on abstract logic object So you can probably already guess that this is meant to apply the strategy pattern and Provide multiple sorting algorithms We in all case we used by publication date by author name and by content length to have a bit of a Variation in the algorithms, but feel free to be creative and use something else a Quick note the ordered feed decorator Does not mean that it replaces the cashed feed decorator Decorators are stackable you can just decorate a decorator which decorates another decorator and go on and on You just need to pay attention to the order in which you stack them. So here as we're dealing with caching You need to think about whether the caching order the or the ordering should come first and how to stack them in which order So we'll continue on to wrap up slowly First of all the branch to see the final code is six. That's all folks So you can check out that branch to see what we finally come and came up with to build this good work log He has no review of the his view of the ordered feed the decorator that now includes or our strategy pattern so in the constructor in the constructor you can see that we are injecting a sorting strategy implementation and If you we look at the get entries implementation further down So we're still retrieved to get entries from the feed that we're wrapping But then we order its entries and return the ordered entries and in this order entries method We can see that we're using use sort to use whatever strategy That was injected and call this strategies compare pattern is to call back for sorting So this does sort Our entries but that's completely in your how they are being sorted. That's a different object a different responsibility Just as a quick example Hit up the by author name or something some strategy Yeah, just hit enter. Okay. No, that was not it. But yeah, that's also a very nice Yes No, it's not sort by it's it starts by by author name by Because yeah, there's this one. Yeah Okay, so here's one example Basically We do an implementation of the interface of the sorting strategy interface and this interface Just says that we need to have a compare method that compares to feed entries and returns an in value The usual way sorting algorithms and PHP are being used is that they return less than equal or greater than zero based on whether the first and entry is is Smaller equal or greater than the second one respectively In this case to implement this we use the get author name from both feed entries To make sure that we have a fair fight. We only use lowercase letters for both of them and We use the spaceship operator here That basically returns this integer value that we need and this is just one simple Implementation of a strategy and we can have whatever creative ways we need to sort them Okay, let's get back to the slides so Let's move on from here. I Before we close off. I wanted to quickly Show you an optional homework exercise you can do Another pattern that we that we haven't discussed yet, which is also very interesting and also nicely fits into the plug-in here But we won't show you the finished implementation. This is something you should figure out on yourself at home So the abstract factory is basically still a step beyond the abstraction level that a simple factory provides the abstract factory abstracts away factories so Which sounds like quite a mouthful, but what that what that means is that? You have an object that can create instantiate other objects and It doesn't even Depend itself on any specific way of instantiating these objects. This can be extended Even by third-party code So to better show you what this means Let's assume Gutenberg was built in a clean PHP and would contain an abstract block factory that has separate factories for each family of blocks So we have simple factories here and the abstract factory abstracts away the fact that they are multiple ones and When Gutenberg requests a block it will just request it from the abstract block factory and whoever is responsible will retrieve the correct in implementation and The big advantage of this is that We can create a plug-in that hooks into the abstract block factory and registers an additional factory Which can instantiate new blocks that were not part of the core Gutenberg experience and all of this works Without changing a single line of code in the Gutenberg plug-in so this makes it immediately extensible and third-party code can easily add factories to add instantiations of implementations So as a home exercise, please think about how you could extend the code so that another plug-in could add could add a third feed Implementation to this social mentions block Yeah, okay, that's the slide Yeah, you need to think about Providing some form of registration mechanism that the external plug-in can hook into it to get access to this abstract factory that's the difficult part about this and Yeah, you can Google about how the abstract factory is built But I think that by now what you've seen will probably make it very straightforward of what? The actual implementation of an abstract factory will look like the key takeaways of this session, hopefully is that Design patterns are not copy-paste snippets design patterns are ways of Thinking about a solution that has shown to be Preferable in long-term and applying this and applying it in different contexts These design patterns can take All sorts of different shapes and forms if you use them in in real life They not always are exactly like the example code you see in the academic books, but that doesn't mean That they are not these patterns. It's just about a Conceptual way of solving a specific problem When you will go through the code that we've provided to you There's other parts of the code that abstract away all the the Gutenberg block stuff There's you already started with quite a lot of code And if you go through this in detail, you will see that there's all sorts of other Instanciations of these patterns you will find additional factories you will find additional decorators And I think that I managed to always denote in the file header dog blocks of each class When they represent a given design pattern, so so you will find more examples of them inside of the example code Another key takeaway should be that dependency injection lets you defer decisions So whenever you can defer the decision You can be much lazier and not Care with all the technical details that would normally need to be solved and just Use a concept Don't use a given implementation. Just use a concept and trust that At one point we will solve the issue of knowing which implementation to use But we always want to defer this decision The third decisions mean that when the decision changes our code doesn't need to change because it isn't didn't rely on that decision in the first place And there's a third take away When when you apply these design patterns and when you apply Dependency injection these are all building blocks and you can combine them you can mix and match them You can combine a decorator with a factory and inject and Wrap and whatever and there's no limit to what you can build with these basic building blocks finally if this has Proven to be interesting to you if this has shown you that design patterns can be a useful tool for you Then know that there are probably at least 80 more of them to discover This was only a small Subset of the available patterns that are documented today We all fortunately needed to limit to the scope of this workshop, but if you Google about design patterns if you Look into books about design patterns you will find a lot of other patterns like this and Maybe now that you've seen how to apply them in real life This will help you get through the academic Mumbo jumbo that comes with the design pattern explanations and you can more easily See how you can use them for your problems and how how you can apply them in your actual Daily life and make it easier Yeah, David is there anything else you want to add So, thank you all for participating in the workshop feel free to also ask questions If you have them you can contact both of us on Twitter We're also available on slack We're always happy to help we we really care about Helping make the general code better because we also need to deal with it every day please help us all together make our own environment better and Also a big. Thank you to the TAs. We did a fantastic job of Helping everyone get up to speed and get moving Thank you