 Thank you very much for the nice introduction. And so, welcome to the talk on design with us. At front, I wanted to say that this is about software design. So if you're listening to me and think about graphic design or UX design or so, not everything might make sense, so be aware. I wanted to do a talk about design patents that contains more real-life examples. Most of the time when you read books and tutorials that talk about design patents, they will tell you how to build to the dock and how to build a car and how to inherit tires. And that all does not really make sense if you want to apply it directly to your home. I wanted to do a talk that contains real-world examples of what you can actually do with these design patents. So what are design patents? Design patents are a reusable solution to commonly recurring problems. This means that during the many decades that people have developed software, they noticed that you always have the same problems coming time and time again. And they worked on finding solutions that solve these problems in a meaningful way, which are considered as practices. And design patents are a way to formalize these solutions. They're not finished code snippets, so you cannot just copy and paste the design patent. And more like it can play where you have the steps to solve the problem, but this will lead to the actual code you solve. They started a concept in architecture that then were transformed into a software design concept. And the book that started it all in the software engineering world was published in 1994. It's called the GoF, short for Game of Four because it was written by four authors. It's called design patents elements of reusable object-oriented software. This is all stuff you can read on Wikipedia, so I'm still not really explaining what design patents are. It's just some historical trivia. Design patents are a structured approach to soft department. So you have on a spectrum of having very abstract approaches and very complete approaches, you would have something like a programming paradigm, which would, for example, be object-oriented programming or procedural programming or functional programming. That is very abstract. Then you have things like algorithms. If I want to solve this and that, I first do this, that, and this, that, and this, that. That's a very concrete structured approach. And design patents are in between. They don't produce a specific algorithm. They don't tell you exactly how you solve your specific problem, but they tell you how problems in certain categories are being solved by providing you with a boilerplate. They provide you with a shared vocabulary, which is very important as soon as it's all working in teams. So if you talk with some other developer and you're discussing possible approaches to solve a problem, they can often evolve into, yes, well, you know, the thing we did in the other code where we had this approach and that, and yeah, I want to use this, but do it more like that, et cetera, et cetera. The design pattern lets you talk with other developers in real confidence. You can say, okay, here, this problem, you can solve it with a factory. If that factory happens to instantiate proxies, then we don't have a performance problem. And all the team members need to know what that implementation actually would kind of look like. The design patterns also give you higher-level building blocks for your own thinking, for your own reasoning. When you become more accustomed to using design patterns, it's called thinking patterns, which makes your thinking much faster. So we don't think at the line level or at the object level anymore. You're thinking about concepts. And in your head, you can just assemble these concepts, rearrange them until you solve the problem. It makes you much more efficient to reason about the problems you're solving. I want to start now by giving you an overview of some of the design patterns, and we will start by... I have this one here, it disappeared. We'll come back to that later. It is, unfortunately, the only pattern that most people apply. And we'll see a bit later why it doesn't work. Let's start by the instantiation factors first. So, instantiation of objects is one of the main aspects of object-oriented programming. It's basically, if you don't have instantiation, you don't have object-oriented programming. You just have classes, which you don't do much. Instantiation is a key factor in building up your object-oriented code, and you should always think very hard about where you instantiate and how you instantiate. Instantiation controls copying. So if you have a place in your code where you write object equals new class, you immediately coupled this code to the actual implementation of the class you referred to. If you do any changes to class, if you just rename it, the other code that was using it will break. So that's the hard copying. And we want to avoid direct copying as much as possible. Instantiation also controls the life cycle of objects. So if you can, for example, avoid instantiating objects, you can be sure that it will not consume too many resources and slow down your program. So the entire life cycle of the application is basically a tree of life cycles of individual objects. And you should very explicitly control that tree and how the individual soft elements are being instantiated. The ways you have to instantiate something are very diverse. So I want to quickly go over some of the ways. So first of all, you have direct instantiation. This is, as I said, object equals new class. Direct instantiation always produces direct copying to the class you referred to because you cannot instantiate an interface or something abstract. You can only instantiate actual implementations. It also requires knowledge about constructor elements. So if your constructor requires an instance of your database, driver, and an instance of your logger and driver, then you need to have them available to even be able to instantiate. There are name constructors, which is one small level of extracting away from the new operator from direct instantiation. The name constructor does not really change matters. Basically, you replace the magic construct method by method you can name yourself. It does give a few advantages, though, because you can, for example, have multiple name constructors, which allows you to have multiple ways of instantiating one same class. This is very useful, for example, if you're working a lot with exceptions, where multiple errors can produce the same exception, and to clean up your code, you can produce a name constructor for each of these error cases. The problem, though, is that the name constructor basically then makes you care about the instantiation as well as what the class is actually meant to do. Then we have the first pattern that goes away from the extract from the instantiations that produce the recovery. This pattern is called the simple factory, and we'll see that there are other factories later on. Basically, the simple factory is an object whose responsibility is to create other objects. That sounds very insensible at first, so why not just direct instantiation? The simple factory will normally just replace the direct copy to the class instantiating with direct copy to the factory that will instantiate the class. However, as the simple factory is an object itself, it can be injected. So you can use it indirectly, which is the first example. Here's an example. We have code that... Imagine you want to provide a feed that generates... A widget that generates a feed or such a network, but you want to have an option where you can switch which network to use. You can use Twitter, Facebook, Instagram, as well. You could, of course, develop this in such a way that you have a big switch statement somewhere and in your actual logic, you're going through all possible mechanisms. Any time you want to add another network, you will just grow your code. So the simple factory is basically an object that takes away the instantiation, and you can then produce multiple implementations of the same interface, and the consuming code will just retrieve what the factory produced and use it. Because now that it will adhere to this interface, the render feed. So the social network is some social network that the factory returned. We don't know the exact object, and we just use it. If we now want to add another social network to the bunch, if we now want to add Instagram, for example, we can add a new implementation of the social network, we can add it to the factory, but the consuming code doesn't need to be changed. It can still instantiate whatever time you need and use it. So this piece of the code is built once, is tested once, and doesn't need to change from that point on. So we're adding extract factory. The extract factory is basically one of the abstractions that further, where instead of dealing with a specific factory that can return some implementations, you're actually dealing with an extract factory that can have multiple different implementations of factories which return and produce different objects. It's also very complicated now, and I didn't reduce code sample for this one because it's really more complex code and it doesn't fit slides very well, but I tried to express it in a diagram. So basically the extract factory, let's think about woodwork blocks in this case. Let's say our woodwork editor has some built-in blocks you can use, and the blocks are instantiated through factories. So if you say I now need a paragraph block, then the extract factory will know how to choose the factory to use and then use the right factory to instantiate the correct block. And whatever you get from the extract block factory will be some object in implementing the block interface. The big advantage of this is that our factory is not extensible. So in our plugin we can now produce a new implementation of the factory register that with the system and all of a sudden we have additional piles of blocks we can create while not changing anything else from the consuming code. It still just works. It's basically all the special logic is contained within the plugin. The actual woodwork editor does not need to be updated to make this work. As you can see with these factories, in general, making something more abstract makes it more flexible. You need to pay attention though because sometimes it's not always the best way to start with abstractions up front because abstractions, they add additional complexity, additional overhead and they are only useful therefore if you actually make the benefit of having the inspection if there's no benefit to be had then just having more complex code is actually a drawback. So all you have to get a feel for where are abstractions needed and where can you just, for example, use a simple factory to start out and then later on if I notice that we have something that limits our flexibility only then use the abstract factory instead. So don't always start with the abstract factory. So with these factories, the question is when should you even directly initiate? Just assume the basic premise of having more direct oriented code is that everything is properly decoupled so that if you do a change in one place you don't need to change in another place to avoid side effects. This is why the direct copy that produces should normally be avoided. You can use the new operator though if you are instantiating newable tasks which are usually value objects which are exceptions and all patterns like the simple factory for example can also be directly instantiated when they're instant. Also inside of the factory of course you can use direct instantiation that's the main reason why you have them. So the next pattern I want to talk about is the template method. The template method is basically like a recipe. You build an object and that object already has in its main method all the calls it needs to do and in which order it needs to do them. And the methods that it calls they are abstract or you can override them. So basically the main structure of how the code is being executed is predefined and you can replace the steps that you want to change. Here's an example of the template method. It looks a bit more messy. Basically what I built here is a payment gateway and for payment gateways usually the general procedure is always the same. You cannot start with charging a credit card if you don't have a payment gateway. So there's a certain set of restrictions in place and a certain set of order requirements that you have. That's why in the template method you can... I want to first show you what the procedural version would be. So the procedural version would basically be this. No, this is the way to put it. So the template method is the checkout here. The checkout contains specific steps of how to do the checkout through the payment gateway and these specific steps as you can see at the bottom they are abstract functions. And the specific payment gateway or the payment gateway for example can then extend the gateway and just provide those implementations it needs. And the basic process of running through the checkout will still be the same. So for example here we added basic logging to log each separate step and in our payment gateway this is just being reused because we didn't override the actual template method, the checkout method. This is still the same one from the base object. We only override the individual steps. The template method is usually not something you start with the front it's mostly you start with one or two implementations or even problem and then when you have these implementations you look at what the common requirements are and so we start the refactor and this will distill your complete method. It's also very important to think about how to name your methodings and what signature to use or type of relationship to use because that will basically be the documentation you give to someone who wants to extend that object. So if your naming is unclear they don't really know how to extend it and will probably produce wrong implementation of all the parts. So the clearer your naming is and the more strict your type declarations are the more robust the actual implementations will become. We should also consider using value objects which is a pattern we'll discuss later to further harden the signatures instead of using scalar values like an int or string. If you have a function argument with lots of values that are very ambiguous then it's very easy to get it wrong when extending to come. The decorator is another pattern I want to cover. It serves to add a specific role, a specific responsibility to existing objects. So first let's think about caching. Caching is what you would call a cross-cutting concern. Cross-cutting concern is something that you cannot easily put into one object in one place and just have it work there. It's usually something that will go throughout the entire codebase. Caching is one of the cross-cutting concerns. Logging is one of the cross-cutting concerns. You cannot have one object in one specific area that will do the logging and all the rest of the code never bother with it. It's more that in each piece of your code you have some logging information in them. That's what you call a cross-cutting concern. Cross-cutting concerns are very problematic to deal with in object-oriented code because they go against what you normally try to achieve by encapsulating your code and separating everything in clean objects. They basically run through an entire layer of objects at once. So where would you put the caching logic, for example, to cache a remote data request? You would normally want to have a solution where neither the code that does the request needs to care about caching nor the code that uses what was requested needs to care about the caching. That's where the decorator comes into play. So it wraps an object and can add responsibilities on top of it without the rest of the code needing to change. Think about an interface. Let's say we have an interface get data or something to fetch or remote data. Normally your code would have a consumer and a producer. The producer will implement the interface to produce whatever the interface guarantees and the consumer will fetch the result from the interface and just use it as is. The decorator works by first splitting this up and going in between these two objects and then implementing the interface itself. So basically the consumer and the producer, they both did not need to change. It's just your existing code. It might be an external library that you're not even allowed to change, that you don't even have access to the code. Not everything is open source. So the decorator works by still being able to modify the behavior of existing objects without actually changing their code. Here's an example of how that would work. So we have an interface data to get data. We have an implementation that does the remote request. We have a renderer that can fetch that data and render it. And here's how you set it up. So we instantiate the remote data fetcher. We instantiate the renderer which gets an instance of the data fetcher. Then the renderer can render. This will then first call this data get. So the remote request will be executed and then return some render result. To do caching, normally you would end up with code like this. So your caching is part of the remote data. So the actual logic, this one call is obfuscated by all the caching logic you wrap around it which makes your code very messy and very difficult to reason about. For the slides it's very small code. Imagine having bigger source files. If all of your methods end up dealing with caching logic like this you will have trouble actually finding out what the real logic of the object is. What does it try to solve except for caching. So to do this with a decorator you would create a new implementation of data that receives a data object and then wraps its logic around it. So we have clean logic again in our actual data class. We didn't change the renderer and to use it we basically create a data object. We create cache data by wrapping the cache data object around the data object and then we can still go on from there and just use the renderer and render it. So if you remember from the first slide from these examples neither the remote data code nor the renderer code has changed. We have all the caching logic in here in a separate object. This makes sense for working with cross cutting concerns as I said. It's sometimes also useful for different areas but cross cutting concerns are most obvious ones. And the decorator works best if you can couple it with a dependency injection container which means that you have one central place where you configure how your objects will be instantiated because then in that one central place you can just say okay whenever I need remote data I return cached remote data instead. And that's it, the rest of the code that I need to care whether caching is active or not. The template view. The template view is something that I wish WordPress would use more often. It's basically a pattern that lets you separate the concern of how to fetch data from the concern of how to present that data by basically producing a template with placeholders and then for any given set of data you replace these placeholders with the actual data. It sounds very simple, it's a very simple concept. Here you can see an example. We have a set of data in here so we want to render a movie entry. We have a template that tells us how a movie should be rendered and you can see that this template has placeholders in here for the title and subtitle description. And then we have a view class which is how the template view design pattern actually is implemented. So here's a very basic version that uses built-in PHP templating mechanisms to work. So basically our view class gets the name of a view to use to make sure that name is valid. Then when you want to render something it patches the context, the data you want to use for your placeholders. And then here we're using output offering to do the rendering. This could also be something like tweak or stash or any other rendering engine. That's whatever you prefer. So here we use a basic PHP to just include our template file and PHP itself will then replace the placeholders. And to use it, it's basically we instantiate a new view with the template we want to use and then we can render it with a given set of data. That's it, so data is separate from the template and it's very easy to adapt either one or the other separately. Some tips for using template view. I would recommend building view objects yourself because to make the best use of it there's lots of details that go into building it so that you can, for example, switch out the rendering engine, etc. So I would recommend using a pre-booked library for that. You should use relative paths that point to your template files or some sort of identifier as not-absolute paths because then you can build an override mechanism where for example you can build a plugin that has its default templates in a template folder inside of the plugin but when you provide them in your child theme it will use them instead and serve those in the plugin. If you always prefer to use relative paths for that then you can reroute the template's location to point to a different place. Also you should think about allowing for nested rendering of these views because instead of having an entire checkout page view you could have a checkout page view that has a chord area with a button view, etc. So you can replace individual sub-views if you want to override something instead of always needing to override the entire thing, the entire page. Then we get to the strategy pattern. So the strategy pattern is basically it allows you to extract away differences in a given set of logic that you just want your logic irregardless of which specific variation you want to use. You can always add different strategies later on and make it so that the code that actually runs your logic is not aware of what strategy is currently being used. Here's an example of the strategy pattern. First we have the normal code without using the pattern. In this example we have a user list and we want to be able to print that user list in multiple different ways of ordering it. For example you can have it ordered by name, you can have it ordered by email but you might also have an ordering for example where you group the telephone numbers by showing the local telephone numbers first and then the international numbers. So you might have more complex logic than only deciding what column to solve it. In this case the code produced has one sort function that is pretty big. It uses a switch statement to decide which algorithm to use and then shows all of the algorithms that are available and you can see when we use it for example we print the user list sorted by phone then it will go through this switch statement and look at how to solve it etc. So to use the strategy pattern we want to extract this bit, the switch statement and have this being separate objects instead. So here you see there's lots going on here that's just because I happen to use three different ways of sorting but the general code is not that complicated. We still have our user list and you can see that when we want to have it sorted we give it a criteria of how to sort. It's an object and it then just passes the users to this object's compare method. So this is basically we prepared an interface that has the logic in this case compare method and this interface we can then implement it. We have a sort by name implementation we have a sort by email implementation and we have a sort by phone implementation which is more complex one. And you can imagine all sorts of other ways of comparing these elements might have all sorts of more complex use cases still where it's just a matter of adding one more implementation of this interface and to use this interface it's basically just instead of giving the get sorted by method some sort of identifier we pass it the actual criteria to use. So we tell the user list to have it be sorted by the sort by phone logic. We have encapsulated our logic into an object and we can pass that object around we can extend that object, replace it, etc. Oftentimes the strategy pattern is an obvious fit if you have huge switch statements or entire chains of if-else statements most of the time you can use one of the many variations of the strategy pattern to clean up this code and have the logic be separated into multiple separate objects. And of course you can also combine this with other patterns so in this case for example we had the consuming code needed to be aware of the different criterias it had direct coupling to the sort by phone class for example but if you combine this now again with a factory you can get rid of that direct coupling and have the factory just know ok it's the phone field we want to sort by and the factory will return the sort by phone object with null object. So the null object sounds like a very useless object at first glance but it's actually one of the objects that can drastically change the way you code Think about error conditions in your code usually when you build something that can fail that can break you will end up having all sorts of if-else statements in your code so if the result is a WP error then do this if the result is false or null then do that which again causes your logic you might have two or three lines of logic and you end up with thirty lines of error on your code before you can even trigger that logic the null object is a way of getting around that problem by creating an object that's created in these error conditions to just have neutral behavior so neutral behavior depends on the context for example if you want to create a view to render something from a template but you happen to not find that template instead of producing errors you could return a null view that will just render nothing so your error conditions are gone you of course have to think about whether architecture made sense to render nothing or whether you would prefer to really draw an error but often times for code on the front end for example errors are just not good so you prefer to not break the null view could also return the error string to just show what happened without breaking here's an example of using the null object we have as I said now with a view normally when you instantiate your view if it is not valid you might think about returning false for example so if you return false you have a problem in the code that uses your view because if the code just blindly uses it here we will call the render method on false which immediately causes a PHP failure so usually you will end up with code like this so you will always have wrenching code that first checks whether your objects are valid and only uses them when they are valid the null object can avoid this by producing a neutral view and returning that neutral view instead of false when something is off when you hit an error condition and again we can now just blindly call the render method and there's no way it can break so the worst case scenario has turned from a PHP fatal error into an empty output which is always preferable except if you want to have the errors so on the front end code you would always be preferable some usage tips for the null object often times having switch statements when you have the default case it's not obvious what to put in there that's a good fit for example to think about a null object also for any objects where the entire code path is going to always run through so you don't want to throw exceptions or print error messages you want to have it be robust then you can use null objects and it's also a good case for just catching exceptions and then turning them into something that's still usable in terms of that it is an object that you can call methods on so it's a good candidate for filling up your catch clauses in your try catch clause now we get to the value object I already hinted at that specific design pattern the value object basically turns all your types that your domain object that your business domain can contain into actual objects with an email address and to just store it as a string and pass it around as a string you never have to guarantee that that is actually an email address that you get in the next piece of code so you have several methods where one passes a string to the other every method will probably need to check whether it actually is an email address otherwise whatever it might want to do the email address might randomly break if you want to extract the domain from an email address for example and you actually don't have an email address the extraction will break and not produce meaningful results you might end up with a null value and then use that null value to pass on to the next method having value objects lets you encapsulate the validation logic into an object that you can then transport around and you can use that object for your type decorations so whenever you then use that value object you have a guarantee that what you get is actually what you think you have so here's an example of a value object I picked up the email example so the value object basically turns a string into an object that contains validation logic which is still stored as a string so in terms of how the data is persisted it does not change much but we now have guaranteed validation you can only instantiate the value object if it is valid otherwise it will throw an exception immediately letting you know that there's something off here we were supposed to get an email address but what we got was not an email address the logic is wrong you need to check the logic again you can also add actual methods to this object of how to deal with that specific value object so instead of having the code to extract the domain part from an email instead of having that being the consuming logic you can put it into the value object and code it once and then just reuse it and here you can see an email sender object where you can add email addresses and it just stores them it does no validation whatsoever because if it uses a type declaration of email address there's no way it could get something else than a pre-validated email address so it makes your code very simple and you will get immediate errors when your data is not what you expected it to be and here you can see an example of how we're using this so instantiate our email sender here we're using Amazon for example send emails then we can add new emails and send them and the validation is properly encapsulated within the concept of the email address only the email address knows how to validate email addresses only the email address knows how to fetch the domain part of an email address and that's it, the rest of the code just uses it mutable value objects should be used with care though they can call something that's called agent box so we have an example here we have Doc Brown who's stuck in the past and we have Marty McFly who's 30 years ahead so to code this up we use a point in time we set that time for Doc Brown and we add 30 years to that time and set it for Marty McFly although now when we actually print our dates all of a sudden both are present in 1985 so what happened? well the actual thing is that we added 30 years to the point in time which was an object both Doc Brown and Marty used that same object reference for their point in time so actually if you change one the other changes as well because there is only one object here and when we add 30 years to it it's changed in both cases that's why you should always prefer mutable value objects instead mutability means that once an object has been instantiated you cannot change it anymore if you want to change it this will create a new instance of the object so here we are using datetime immutable instead of the normal datetime by the way both of these objects are part of normal PHP language and with the datetime immutable when we do our add operation here this add operation actually returns a new datetime object instead of returning a changed version of the previous one so we have two datetime objects that are now being used and we get the correct dates when we want to print them this is something that's very important this is why the mutability is such an important factor in doing software development because the more complex the system gets the more difficult it is to actually diagnose parts like this and it's very important to be aware that when you're dealing with objects they are not copied by value they are copied by reference so they are passed by reference by value so if you pass an object to some method it's passed by reference and they are not copied like every way so some tips for value objects use them with abundance use them for all of the type equations nowadays if you're using modern PHP code you can really work by almost exclusively using objects instead of any scalar values if you have an integer value somewhere why not think about what concept it represents and then create an object with that contains its own valuation if you have an array why not turn it into a collection of specific objects using objects in that way makes the code more robust and it also helps with static analysis so for example if you're using ID like PHP storm if you only use objects and very strict type declarations PHP storm itself the meaning that you know when you have a logic error in your code because it's obvious that there is a mismatch between what you expected to get and what you actually got you should, as I already said also prefer immutability and make sure that that you always wear that the value objects always share the same instance if you just move them around the next design pattern is the proxy the proxy pattern is an object that takes the place of another object and can forward calls from the proxy to the other object it is used for example to replace an object that's very expensive to instantiate by a very cheap small weight proxy and then only when the proxy is being hit by request you actually instantiate the expensive object so here's an example of the proxy we have a database implementation that as you can see does a very expensive initialization so if we just use this code as is you can see we instantiate our database we pass the database into the plugin and then add actions the actions might never be triggered so that code might never be needed but we nevertheless needed to instantiate our database to be able to pass it into the plugin because the plugin required the database to work to dependency so to avoid this very expensive initialization from and only do it when it's actually needed which might be very rarely the case we can use the proxy so the proxy basically implements the same interface and it can forward calls to the real object and in this case we store an instance of the database and only instantiate it when you have an actual query so here we then pass the database proxy to the plugin instead of the normal database we still do a normal an action called etc and what is not us is if we do a web request that runs through the entire code and then just triggers stuff to do which is this code path it will never initialize the database because it was not needed it was not hit by an actual query so it will never be initialized so the very expensive initialization was not actually done during the web request only when we do a web request that needs the database it will trigger the initialization yes another way of writing a proxy that is a more simple hack of PHP internals I go back to the previous one just to show what we want to avoid so here you can see that for each query we do we have a condition first that checks whether our database was initialized or not and if we happen to do 5 million queries in one request we will do 5 million 5 million to always check whether database was set or not so we can avoid this by doing a construct like this so our query will just use the database and forward to query but if we look closely we see that we don't have a property database in here so the property database does not actually exist but we have magic data that when a property is being requested it doesn't exist it checks whether it was actually the database and then add the property dynamically where the reference to the database so the next time the database property will exist and the magic method will not run so this way we have avoided having a conditional one with every query beware though that this is only needed if you actually have performance issues because of these conditionals because that's more in the territorial attacks than it is of theme code so these are tips first of all don't code proxy by hand if you can avoid it there's a really great library that's mature and tested and used everywhere in HP frameworks and libraries that's the proxy manager library which basically gives you also the different types of proxies readily built and tested and also all bytes already exist also you should not use proxies through an entire tree but rather replace the root of one sub tree by a proxy which will then trigger earlier on the entire rest of the tree so use it for everything the observer pattern I think this should be the last pattern we'll see now the observer pattern is basically a notification mechanism where the one who wants to have the notification and the one who sends the notification are the couples so you have the subject and your server the subject does something and your server wants to be notified when the subject does that thing this is similar to the concept of publishers and subscribers but not exactly the same thing in terms of the pattern the public subscribe pattern is actually a variation of this and the public subscribe pattern does not directly have the observer and the subject communicated in the observer pattern has some form of channel some form of grouping in between to have an indirect communication between these two so here's the differences between these two as you can see the observer pattern has a direct connection between these two or a direct relationship between these two let's say and the public subscribe goes through channels so the subscribers subscribe to a channel and the publisher will publish an event into one or more channels so when an event is being published into one or more channels one or more subscribers will be notified and if you actually know the procedural implementation of the public subscribe pattern namely the plan if you are working with this form which provides actions so you can think of actions as a channel and you have multiple subscribers that can add action to a specific action and then you have a publisher that does a new action to actually trigger the channel so the planning API with its actions is actually a procedural implementation of the public subscribe pattern yes, so here we are again with our favorite pattern Singleton here's what I want to say about Singleton because everyone seems to use it it breaks the single responsibility principle it breaks the open closed principle it breaks the list of situation principle it doesn't break the interface segregation principle does because it doesn't have an interface it didn't get the chance to break it and it breaks the dependency in version principle so 4 out of 5 of the solid principles which are basically what are the common stones of clean modular overp development so Singleton is really bad please don't use it you can pretty much always replace it with factories or other patterns we've seen here there's no that makes you need to use the Singleton it's just a pattern that happens to have been in the book I've described before from the game of war but everyone now considers it to be an anti-pattern not a real pattern so even both campaign arrows this seems to be one of them there's a link at the bottom of this slide which goes into more detail about the Singleton why it should be avoided and in multiple ways replacing it with something more useful the key data way from this talk design patterns are a concept and a tool they are not specific of code they are not something you can copy and paste with your code so if you go to the website that contains design pattern examples don't copy an example like the rubber duck in your code or the corp actually is something design patterns simplify communication it allows you to very efficiently communicate with the rest of the team you can talk to them by saying the factory that you produced should return value objects instead of something else we need a processing here to improve performance level etc etc so it's a very efficient form of discussing high level concepts and again with some time it will shape your thinking and you will actually think in this more efficient way using these design patterns if you want to start your design patterns I recommend looking into these first these are pretty simple to use in normal code actually using a factory will improve your code by copying everything this will make you more flexible to experiment with patterns so you can return one pattern see what it does and if it doesn't work return a different pattern the complete method makes everything more structured in terms of what other people need to deal with when you want to extend your code the decorate the last logic like caching and logging out of your proper business logic and to template you lets you decouple the rendering from the data preparation and lets you easily change the way your front end rendering is done later here are some references the first one is the work that is sorted at all the second one is the work that contains a little additional patterns that are mostly useful that are mostly explained in the context of enterprise application architecture but the patterns are always valid no matter where you use them and if you happen to use them in a mobile game then if they produce cleaner code then they are all there there is also a learning resource this is Github you can deposit with lots of useful KGP resources and they have a big section on design patterns thank you very much we all know the press part is not very rich in design patterns do you think it is possible at this point to implement some at least some of them and what do you think it will do in the future I am currently working on some attractiveness in WordPress core that mostly deal with performance issues for example for these performance issues often times the proxy pattern is very valuable to give you an example the translation system in WordPress basically makes it so that if you use underscore underscore it is a function called if you return the translated version of that screen the problem with that approach is that as soon as that code is hit the translation is being requested even if it might not be used and this causes performance issues like for example in the REST API when the item schema is built it contains lots of description fields with every description field and this causes weird effects like doing a REST request to fetch the post title of the first post on the site and this will trigger 3,000 translations behind the scenes that are never being used so for example in this context I have produced a string proxy and then at the implementation of the translated string proxy so the underscore underscore method actually returns an object that if you cast it to a string if you want to if you turn it into an actual statement or so it will actually then trigger the translation and return it but if you just set the object and pass it around and never render it somewhere the translation is never being triggered so that's one example of how you can use design patterns in the procedural WordPress or lexy code it's easy to change the code to apply inside it it's easy to change it it's not so easy to change if we are afraid so in this example I had to update some of the unit tests because the unit test did a direct check to see if it got a string because they were not interested in having a translation they were interested in having the string type so these tests had to be updated but there was also some weird use cases in the regional code where translations for the month names were done for example and then the translations were being used as indexes into a way to produce next set of translations and you cannot use such a spring as a proxy object as an index into an array for example so some things need to be updated hey so not directly related to design patterns I was wondering if you could comment a little bit on your thoughts for the future of WPCLi and your thoughts on WPCLi becoming a WordPress but more project that happened last year I think to hit me up after the talk I think that's completely out of scope now for discussion but just for you to hit me up later on we'll discuss this being a collaborative