 Hi, everyone. I think this was my cue. Welcome to a series of fortunate events. My name is Matias Novak, but you may pronounce it in any other way that vaguely resembles that. You may know me better as a Symphony II guy, but since Drupal is about to or has already embraced Symphony as part of its core, it makes sense for me to be here. And I'm talking about events. What are events, really? And this is something I've learned to ask ever since I studied philosophy, actually. You can sound like a very smart person if you ask things like, what are events, really? And then ask it again. No, but really, what are events? Yes, in the case of events, it's really very simple. Events are just things that happen. And what's very interesting about events in particular, especially during this talk, will be that they can trigger actions. Just now, a very practical example. You arrived. And then this finally triggered me to turn on my microphone, which was an event that triggered you to stop talking, actually. And then that particular event triggered me to start talking. So that is just a series of fortunate events leading to this particular fact of me being here talking to you. And when it comes to events in software, this is more or less the same. Events model what happened inside a system. And also, the actions that are triggered by particular events are what happens inside other parts of the same system, and sometimes even what happens in other systems. So within a system, you can respond to events happening somewhere. And you can do some things based on that particular event. Most programming out there looks something like this. You will have only a long list of commands, basically. There is the command do this, the command do that, update something, and then finally return something. You will see this again and again. And if we were to introduce the concept of an event in such code, it would only be very easy. We would only have to write some comments like this. Of course, there's no implementation to events at this time, but it's very easy to at least introduce a notion of events. So when the command do this has been executed, really what happened was that the event this was done took place. And the same thing for do that, this stands for the event that was done, and so on. So it can be very easy. This is more of an everyday code sample that you will find in any project, really. Most projects have some kind of a post or an article. And most articles in posts can also have comments. This is what code looks like that tries to add a comment to an existing post. You provide a post ID and a comment, which is just a string here. You fetch the post from some place, probably the database. You add the comment to the post, and you save the post again. And that will basically save the comment, too. And then after the comment was added, you want to run some code like this, the logger. You want to maybe add a line to the log file saying there was a new comment. And you want to send a mail to people who are interested about this fact. So you want to send a mail saying there was a new comment. Well, something I would have to mention here is that in order to send an email and to add a line to a log file, you would, of course, need a mailer and a logger, which you need to inject using constructor arguments. And then you would be able to do such a thing from inside the post service. Now, to introduce events in a bit more interesting way than just adding comments in place, it would just be as simple as creating a private method probably inside the same class, saying new comment added, and to put all the logic that happens after a comment was added right there inside that particular method. By the way, it looks really great to see my code so big on the screen. It's at home I usually write smaller codes, so that's just very nice. Well, just a note about the graph of dependencies here. The post service needs a logger and a mailer, and this is something we have to keep in mind. It's somehow strange, right? And this leads to some design issues. I really don't think that the post service should know all about the mailer and the logger. It usually doesn't have anything to do with that kind of tool. And if I would like to change the behavior that happens after a comment was added, I would have to modify the post service class itself, even though the post service is not worried at all about sending mails and writing lines to a log file. So this is something I would really like to change, I would like to be able to modify that behavior without touching the actual class. And, well, of course, this talk is about events, so we are going to fix those design issues by introducing events, but only gradually. I will show you several steps that lead eventually towards using events in your software, but there are several other steps that we have to take before that can actually happen. First, I would like to introduce something called the observer pattern, or at least an implementation of that pattern in my code. Observer looks something like this. Inside a subject, something happens, and several observers are interested in this particular event. So there's already a slight hint of using events. So an observer pattern or implementing it allows you to notify other parts of the application when something changes or something happens. That might be interesting to others. It looks very simple. You have a list of observers, and each observer you call its method notify, and then you let it go. The observer is allowed to handle its own logic. The observer contract is actually very simple. It only has this notify method, and it's all there is to it. Just let's take a look at some very concrete observers, like the logging observer in our case, and when notified of the fact that a comment was added, it is allowed to add a line to the log file using the logger, and as you can see, it only gets the logger injected as a constructor argument here, and then when notified, it will log a message saying there is a new comment. And another very concrete observer is the notification mail observer. It has only one task to send an email when a new comment was added, and of course it uses the mailer for that, which is injected as a constructor argument. Now, we have moved some logic from the post service to another class, two classes actually, and we have to make that logic available inside the post service, and we do that by constructor injection again. We provide just an array of those observer objects. We inject it into the post service, and then, well, this is called configuration since we are going to do this outside of the post service, and maybe we use some kind of a dependency injection tool like the symphony service container to actually take care of this for us. Now, before we had this very nice dependency graph, but not really very nice since we wanted to move those dependencies out, the post service depended immediately or directly on the logger and the mailer. And now afterwards, the post service depends on an unknown number of observers, which is a very abstract thing, and there are two concrete things, the logging observer and the notification mail observer, and each has very specific tasks and use different dependencies like the logger and the mailer. So there's no dependency on the logger and the mailer anymore from inside the post service, which is really great. So now it's time to have this little design principles party here since we have applied at least three of the solid design principles that you may have already heard of. I will explain them quickly to you. We have on the fly, so to say, applied the single responsibility principle here. The principle says that each class should have one small well-defined responsibility and nothing more. Basically, let's take a look at the different classes and what their responsibilities are currently. The post service, its only responsibility is to add comments to posts, which it does very well. The logging observer, its only responsibility is to write a line to the log file. And the same for the notification mail observer, it only has to send an email, which is a very small, well-defined responsibility. And the other side of this single responsibility principle is that whenever a change is necessary, it only has to happen in one place, or it only has to occur in one small part of the application. For instance, when someone walks in and says, well, we have to capitalize all the comments that have to be added to posts, we immediately open the post service class and modify some code there. And then if someone walks in and says, we are going to use a different logger, we are going to use monologue, for instance, or maybe even the PSR3 global logger interface. Now, then, of course, you have to modify code in the logger observer. You don't have to modify code in the post service for that, just the logger observer. And the same goes for the notification mail observer, since it knows all about sending emails and what is going to be inside the message. And so if someone asks you to add a timestamp to the mail, yes, you can easily do so. The second principle that we, well, knowingly or unknowingly applied here, is the dependency inversion principle. And it basically says that you have to depend on abstractions, not on concretions. And you already heard me use that word, abstract and concrete. What happened in the beginning, post service depended on something very concrete. It was a tool like a logger and a mailer with very concrete implementation details, just like we saw in the dependency graph. But now it depends actually on something very abstract, an observer, which really tells nothing about what's going on inside the code of the observer. So instead of depending on concrete things, we have been depending on abstract things. Like you see in this nice little diagram, there is nothing concrete about any of those observers. So the only things that are concrete, which are depended upon by other classes, are the mailer and the logger. And those are depended upon by very concrete classes themselves, like the logging observer and the mailing observer. As you can see in this part of the diagram. Well, the last of the principles that we applied here is the open-close principle, which is quite, I think, quite a famous principle. A class should be open for extension and closed for modification. We really applied this principle here since you don't need to modify a class anymore to change the behavior. So if we want to change the behavior that happens after a comment was added, we don't need to modify the post service class anymore. We can just switch out some observers, like in this diagram. You can switch the second observer and use another observer there. You can maybe even leave out the first observer or add another observer. And for all of these behavioral changes, you don't have to modify post service at all. That's really great. So we made the post service class close for modification. There's almost no need anymore to modify code inside that class. And we have made it open for extension. Well, this is a very famous event that happens in many houses all over the world. Mr. Body was murdered. Who recognizes this image, by the way? Yes, well, quite a few people. That's great. Well, this part is about event data. And, well, we don't have any data about an event currently. But we would, of course, like to know a little bit more about when and why a particular event occurred. So when you say, oh, Mr. Body was murdered, you would definitely like to know who did it, really. Well, Mrs. Peacock did. Which you all may remember. Where did it happen? Well, in the dining room, yes. And how did it happen, since we want the gory details, with a candlestick? Yes, and it must have not been a pleasant experience. But if we look at our own implementation of events currently, we don't have anything like that. We're not able to know anything about the event that happened inside one of the observers. So as you can see, when we are notified, we have no clue about the context in which the event occurred. So, yes, I would really like to be more specific about which comment was added, to which post it was added, when, really. So I need more information, and I want to log more details in this particular observer. So let's introduce an event object. It's very simple. We have a class, which is just some kind of a value holder. You may provide it using constructor arguments, in this case the post ID and the comment. But it may just as well be some public properties. It can be just very easy. As you can see, in this case, I wrapped those inside some public methods, comments and post ID, in order to be able to later retrieve the actual post added to and which comment really was added. What this does is it stores the context of an event that happened. So whenever an event occurs, we create such an object and we provide the information that was currently available at that time. And, well, since we want to pass that information to the observers, we have to change our interface here. So let's leave the observer part behind and implement command or event handlers. This is the interface. It looks like this. It has a handle method instead of a notify method, and it provides the event object as an argument. And now all of the event handlers may use the event object if they like. Or they can just be simple observers just doing something after they are notified of an event. This is a rework of our existing... Well, then it was called observer, but now it's called event handler. And basically it does almost the same, but now it has the right data about when the event happened and why in what context. The same goes for the notification mail observer or handler. It now implements the same interface, and it does more or less the same, but it uses data from the actual event object. Again, some configuration is needed to get this all working. Instead of providing an array of observers, we provide an array of event handlers that are more or less the same, but still there is some configuration going on outside of the post-service class. And just in the same way as we looped over observers, we are going to loop over event handlers, but right before we do so, we have to instantiate our event object, which is an instance of command edit event, and we just have to provide the right arguments to its constructor, and then it will already work. So this allows us to push some information to the actual handlers or observers as they were. Well, let's take this one step further. We introduce a mediator, which is another design pattern. I already mentioned observer is a pattern. These are some patterns from the design pattern book, Elements of Reusable Object Oriented Software. I have added a slide about this book at the end. I think it's really interesting to read the book and learn some of the very commonly used design patterns, since you will recognize them all over the place used in very famous projects. Well, we are going to introduce a mediator, which is really a simple design pattern, although mediators sometimes cost a lot of money. But we are going to leave the talking between the objects to a mediator. And, well, there are some famous mediators out there, the Doctrine Library and the Sand Framework both have an event manager, which is basically a mediator for events. Then there is another one, which I find quite nice. It's the event emitter created by the PHP League. And Symphony has its own event manager or event mediator. It's called the event dispatcher. And yes, since we have such a close relationship nowadays, well, I am going to talk here about the Symphony event dispatcher, of course. So before, this was the situation. The post service called each of the event handlers directly. So it called the logging event handler and it called the notification meal event handler. And now afterwards, we are going to leave the talking to the event dispatcher, which we put in between the post service and the handlers. And in code, this would look something like this. We inject an event dispatcher as a constructor argument. And then later, we create the same kind of objects that the command edit event, and we dispatch the event to it. We say, just handle this event. I don't care how you do it. Well, just figure it out. So we add a little string, which is the name of the event that occurred, and it will later allow the dispatcher to find which listeners or handlers it should notify. And then, of course, we also provide the event object to add little context to this particular event. If you're going to use the symphony event dispatcher for this, you have to extend the symphony event class, but that's not really a problem unless you really care about coupling like I do. But, well, okay, for this particular case, I let it here. Yeah, so this is just one thing you have to do. You have to use the event class and extend your event object from it, or event class from it. Then you need to have a little layer of configuration. So you instantiate the event dispatcher, which is just a very simple class. It doesn't need any constructor arguments. And then you instantiate all of your event handlers, which a symphony would call, or the symphony community would call event listeners, by the way. So on the dispatcher, you call the addListener method, and you add instances of the event handlers, or the event listeners. Again, you will see here the use of the string comment underscore edit, which is the name of the event, and the dispatcher will know how to find which event listeners to call. Then the second argument is an array of the object and the method that the dispatcher should call whenever the event occurs. So then you can instantiate the post service, and you will have a post service object with the dispatcher inside of it. Really nice. Yes, well, as I said, symphony2, Drupal 8, it's a good match. And when you want to use events in your application, it will be very easy, since the event underscore dispatcher service is already available, which is an instance of the event dispatcher. So you can use it right away and inject it inside your services. Then you can also register your event listeners very easily using service tags. And just a quick hands up, how many of you have used the symphony services YAML? Define some services for Drupal 8. Yes, well, quite some people. Yes. So this is a really great way to prepare your objects to be used. So you can just... Oh, I have some slides about it. This is the way service configuration looks like. You have a post service, which is defined by post underscore service. It's just the name of the service. You provide the full class name of it, and then you say it needs these arguments. And the arguments themselves can be anything, or not really anything, but many things. But in the first place, they can be other services, too. So you have this little ad, and then you write the name of another service that should be injected as a constructor argument. And that's very easy, since the event dispatcher is already defined as a service, you can use it in your own classes. Just great. If you have event listeners or event handlers, you can easily register them using a service tag, and this is what a service tag looks like. You create a service. It is called Logging Event Handler. You provide, again, a class, and some arguments. Also, a logger is already available in Symphony 2, so you can just use that one. And then the tag looks something like this. There is a name, and then there is an underscore listener. You provide the name of the event to which this listener is going to listen, and then you mention the name of the method that should be called on that object once the event occurs. So it's really very easy, and you can start using it immediately in your projects. And the interesting thing is that Symphony as well as Drupal have fully embraced the concept of events in their application. So when a request comes in in a Symphony 2 application and a response is about to be generated for it, this all happens using events and event listeners, partly by event listeners of the framework itself and partly by user-edit event listeners. I will just give you a quick overview of what Symphony does under the hood when it tries to create a response. And this is equally true for Drupal itself. And they have added some extra events to it, but it's really more or less the same. If you look in the index.php file for Drupal projects, or Drupal 8 projects, you will see something like this. Request is being generated from the super globals like underscore post, underscore get, underscore server, cookies, files, anything. And then this request object is provided as an argument to the handle method of the kernel. The kernel does really all the work, and on its way it dispatches lots of events, and the end result of all those events adds up to the actual response that should be returned to the client. And so the response object is the return value of the handle method, and the response can be sent to the client. So just a quick overview of those kernel events. The first one is kernel.request, and it allows event listeners to do some route matching, for instance. The URI will be looked at, and it will try to be matched with existing routes in the application. And then the resultant controller will be used in the step afterwards, after this one. Also kernel.request is an excellent time to do some authentication checks. For instance, this is also the way the symphony security component itself does it, but this allows any further execution of the usual flow. So you can break in and return a response right there, and you can say, in that response, you can say you are not allowed to be here, or something like that. Then the next interesting event would be kernel.controller. It allows you basically to replace any controller that was previously matched. So again, you can do something like preventing access to the current controller, but you can also do some other stuff that needs to be done before executing any controller, like maybe checking some access-related things. Then the controller should return an actual response object. At least that is a symphony philosophy. But in most situations, it doesn't. So for instance, in Drupal 8, you will always return an array, I think. Well, that array will, of course, be used to render a template. Yes, the kernel.view event allows event listeners to hook into this process and determine how to convert an actual return value of a controller to a true response object. So yes, in most cases, it's just render a template. But in other cases, it may also be convert the return value from the controller to maybe a JSON response for an API or something. The last event that I am going to... No, no, almost the last that I am going to explain here is the kernel.response event. And it can be used to modify the actual response object at the last moment that's possible. So right before sending the response back, you will, back to the client, or not even back to the client, but to the client, you are allowed to modify the content of the response, maybe add some headers to it. Symphony itself injects its toolbar, maybe you've seen it before, right at this time, whenever the response is an HTML response. So this is also used to add some cookies, maybe, or, well, remove some cookies if that is necessary. And then kernel.exception is used whenever any part of the application throws an exception. And it is used to ask one of the event listeners to generate a response for such an exceptional situation. So maybe you want to respond in a particular way to a user when a particular exception occurs. The most general way to handle an exception, of course, is to render a nice page with a friendly little fellow with three fingers, I guess, and the stack trace if you're in development mode. What's quite fascinating is that Symphony uses events not in a very traditional way, but in a, well, maybe a modern way. It allows event listeners to talk back to the one who has dispatched the events. So kernel events are not merely notifications. They are not meant for other parts of the application to be notified of something. They are meant for other parts of the application to be actively involved in some step of the process. They are allowed to modify, well, parts of the application or parts of the process by maybe returning a response early or modifying an existing response overriding a controller. And these are all very active things to do for event listeners. So in the previous parts of this talk, it was all about being notified, doing something when something else occurs, but now it's really like talking back to each other. And this very much reminds us of the chain of responsibility pattern, which is also from that famous Design Patterns book. It looks something like this. There is some sort of request, not even an HTTP request, but any kind of request. And there are several handlers like Handler 1, 2, 3. Each of them is asked to handle the request. But Handler 1, it doesn't know what to do with this particular request. So it lets Handler 2 do the work. Well, yes, Handler 2 knows something about this and it creates a response, which is actually used as the response for this particular request. Handler 3 will not be called in most situations. So that's that. When transposed to the symphony world, it would look something like this. You have event listeners 1, 2, 3. You have a particular event or request, like I've got an exception. So symphony, what should I tell the user? Now, Listener 1 tries to do something with it, but it doesn't know how to handle exceptions. So, well, yes, Listener 2. Well, Listener 2, in fact, knows how to handle this exception and it generates a response. And now Listener 3 will never be called. So you might wonder... Sorry. You might wonder how can I influence this process since if I am Listener 3, well, maybe someone else handles this request and I never get the chance to do so. The symphony event, especially, offers several ways to influence the chain of responsibility here. It also allows you to, well, prevent other listeners from picking up this request. One way to do it is, well, for instance, if I set the response on something, I can say stop propagation right there. And, well, this way, I particularly prevent other event listeners to handle this request. So that's great. Maybe this is the best response ever. Another way to influence the chain of responsibility is to use priorities. Whenever I add a Listener to the dispatcher manually and also with the service tags I mentioned before, you can also provide a priority, which is an integer. It can be a negative number by default at zero. But this way, you can modify the priority or the prior prioritization of all the listeners in the row. So when you use a priority of 1,000, maybe, I don't know, I think the limit will be PHP in max, or so. Then you will always be the first and you can stop any propagation of that particular event. So that's great. Now, well, you may have some concerns, or at least I do when I look at events at code that uses events. And in particular, if you're not used to using events in your code, introducing an event dispatcher may seem really strange. And there are several concerns that I like to address here, and I hope I can convince you to either step over it or, well, maybe do something about it. And the first concern is that events or the way events are handled can be very difficult to understand. So, well, I really think this is partly true since this type of understanding I call click through understanding. So if you are working in an editor which shows you some links to maybe methods and where are variables defined and in which file is this class defined, then, yes, it will be hard to understand event handling since whenever you encounter an event dispatcher in symphony code and you click on the dispatch method to see what's happening inside that method, you will see something like this, it just points to the interface. And there's no clue about a particular implementation of event listeners there or you may never know what happens behind the scenes. Well, this is a very easy solution. You just have to install XDbuck on your machine if you didn't already have that. Since that will basically allow you to step through the process when the application is running. So you don't need to click through anymore to where a method is defined or where you really expect the code to be. Anything can be different at runtime. So you have to have something like this, an interactive debugger where you can step through the code while it is being executed step by step. So then you will see what is the value of any current variable that is used and where did this current line or what is the stack trace? So you can see where you come from. Well, this may seem a bit... not really a solution, but it is. I think most of the modern code nowadays, like Symphony 2, is in my opinion quite modern code, works with interfaces a lot and then you are never able to click through to the actual implementation. This only works with concrete classes, right? So one, I think, bigger concern would be that you have some out-of-the-main concepts in your code. Like, if we looked at the original post service class, we saw things like a comment, which was a string, but, all right, a post ID, which is the identifier of a particular post. We saw a method add comment to post, and then all of a sudden we introduced this strange word, dispatcher, which has nothing to do in the domain of adding comments to posts. That really doesn't sound like something that you would usually use when you're adding comments to posts, but that's really strange. And while we did a good thing, actually, we fixed some very, very bad coupling issues since we used a mailer and a logger directly inside the post service. Yes, well, let me just tell you another part of the story. This is Konstantin Kudrashov. A great name, I think. I hope I pronounced it well. Also known as Everset. I went to a talk. He did a talk at Symphony Live last week. He had some great words to say about this. So let me just show you what he said. This guy, coupling, has a sister. So even though we are fixing coupling issues here, well, this sister, she's called Cohesion. And, well, she is important, too. And she also has her own ideas about what should happen to the code in your class. Cohesion really is about a sense of belonging together. So when you look at code, I think most of you have said one time or probably many times, hey, well, listen, this method doesn't belong inside this class. It just doesn't belong there. It's about a different concept or it doesn't feel right. Or maybe even what is this variable about? It doesn't make sense in this context. And this is what Cohesion is about. It is about belonging together. And the thing is, in most code or most domains, dispatcher, event listener, and even event, they shouldn't be there. They are just words that have nothing to do with the actual problem domain of adding comments to posts, in our case. So, yes, more difficult of a problem, but there are very easy solutions. The first thing you can do is have better naming in your code. So instead of writing things like notification meal event listener, such a class should be named send notification meal when comment added. And this already makes a lot more sense to anybody who would look at the code and try to understand what's happening, even if they wouldn't know about event listener. Then a comment added event, it doesn't really mean anything. You should write something like comment added, which already explains about itself that it is some kind of event. It just happened. And something like on comment added, which reminds us more of jQuery development, should definitely be something like when comment added. And this is something you can explain to anybody, just write the code out loud, and everybody will understand. If you use things like event listener, event, or on as a method name, that doesn't make sense to most people. Only if you know about event listener, of course. So basically this also hides implementation details. I think most people will not worry about whether you're using symphony event dispatcher or the doctrine event manager. You should just hide the fact that you do such a thing. It should be just plain by looking at the code what the code is doing. Another solution is to not use an event dispatcher. And I tend to not use it when... Or I tend to only use it when things are not naturally cohesive anyway. So for instance, the mailer and the logger in the post-service class, they showed no cohesion at first. So mailing and logging has nothing to do with adding comments to posts. So these things were naturally uncohesive and we could easily move them out to event listeners. There's no problem in that. But well, if there is natural cohesion, you'd better not introduce an event dispatcher, which would cause low cohesion. But you have to use something else. You may use observers there, or you may any other objects that just collaborates with the object you're currently talking about. For instance, when you look at the code, the symphony code for resolving the controller, you will see something like this. There is the event getResponse event, or something like that. You provide the request as a constructor argument. And then the dispatcher is used to dispatch the kernel.request event. And any listener is allowed to populate the request attribute underscore controller. Well, this is some magic going on. But it's really very... It has low cohesion, since many of the concepts used inside this piece of code don't clearly communicate what is actually going on. Maybe I would have expected something like this. So controller is controller-resolver-resolve. And of course, you may use the request, but in the end, I just want to get a controller from this. And I don't want to use a dispatcher. It's just totally unclear what happens in all the event listeners. So yes, well, there are several alternatives. You could just as well use observers like we did in the first few slides of this presentation. A third concern, which is also important and somewhat profound, is that you feel that you lose control in a way. Well, you know, you are relying on event listeners to do some very important work. It's not like you can just disable an event listener and your application will work, will still work as it did before. No, event listeners are very important. Yet how do you know if they are in place and well configured and that they do their job, that they are supposed to do? Yes, well, one thing, of course, you can, or you should have some kind of a test that shows that all those event listeners work, but if and still, this is not really a solution, or there isn't going to be a solution since let's label this as a won't fix. You have to really learn to live with this kind of loss of control. This happens all the time and it's good. Ah, yes, so I had one slide saying it's good, which is a good slide, by the way. Well, what this is called, this loss of control, is actually called inversion of control. So there's no real loss of control. It's just that this particular class, the post service in our case, doesn't have control about what happens after a comment was added. That's really good. It looks something like this. First, we have a thing that exercises control, yes, it exercises control over the other thing, and then we'll just give up control and there's no relationship even with that first thing and the second thing. You, of course, know all about inversion of control since, well, yes, a router determines the right controller for you. There's no way that from inside the controller you have to say, yes, yes, choose me or something. That doesn't happen. It all happens outside of the controller. Also, the service container, at least the symphony one, injects the right constructor arguments. That is also inversion of control. You leave that part of control that you would usually exercise yourself by instantiating any objects you need, right where you need them, to something outside of your class, like the service container. Well, just a little everyday example of inversion of control when you die. Someone will bury your body for you. It's not that you have to do something for that. You just leave it to others. So it's just all the same. But just like John Nash, or I don't know if the real person said this, but at least he does in the movie, I must admit that I'm also terrified, mortified, petrified, stupefied by inversion of control. It's really scary to give up so much control on all the things outside of your own classes. But it's really the best way of doing things. It will lead to better design, which is good anyway. It doesn't need any explanation. It will require less change since every little class has its own responsibility, like we saw before. And that will, in fact, make maintenance much easier. Just by looking at the names of the classes, everything will be clear, and any future maintainer, will be able to quickly find where he is supposed to modify some code. Yes, that is just good. At this moment, my presentation is somewhat finished. I always learn to ask questions when presentation finished, so I don't know if there is a microphone available to just have something. Yes? Oh, you can just move to the front and say anything you like to me. Anyone? I'm just going to count to 30 in my head until someone... That's really hard. All right. All right, thank you. Yeah, this was the other... Thank you for no more questions. Well, just some commercial messages towards the end of this talk. I wrote this book. It is very much about symphony, but it's very, very interesting to Drupal 8 developers. It contains lots of information about how you can create service definitions, all about those particular kernel events that lead eventually to the actual response. And because you're DrupalCon, I have created a special discount for this book. When you download the slides, just check out Twitter later. Or already, you can already download the slides on Twitter. Well, you can just click that link and you will get the discount. Also, if you're interested in package design, about which I'm writing a second book, well, just take a look at it. Maybe it interests you, and maybe it doesn't say anything to you. No problem at all. I just wanted to quickly mention this. Then there is this book Design Patterns, which I also mentioned sometime. I didn't write this book, of course. It is the famous Gang of Four, starting with Eric Gamma and all the other names I always forget. Lucky Eric Gamma, of course. It contains explanations of all the design patterns, like observer, mediator, chain of responsibility, and so many more. Then this book, Solid Principles, or it's not called Solid Principles, it's called HL Software Development. It's by another big name in the industry, Robert Martin. And he explained all about what he calls the Solid Principles. And these principles are very widely known and are very useful any day you're writing code. So just get it. Yes, some images I used. I especially liked the Capio. And, well, of course I'd like to know, what do you think? What did you think about this information I gave you? How did I do? Did I wait too long or too short to ask some questions? Never mind. Well, you can find me on Twitter, too. And, well, then this was really it. So thank you again.