 Welcome to dependency injection in Drupal 8. My name is Kat Bailey. I've been working with Drupal since 2007 and I got involved in core development a little over a year ago and since then have been helping out a little with the Whiskey initiative the the web services and context core initiative That's the initiative that's been mostly responsible for getting a lot of the symphony components into Drupal core Okay So just a couple of things before I get started I will be assuming a rudimentary understanding of object-oriented programming as in I'll assume You know what I'm talking about when I when I'm talking about things like classes and interfaces and constructors But you know if the only experience you've had with object-oriented programming It's maybe writing custom views handlers or something like that. That's totally fine. The examples will be very simplistic The other thing I wanted to say is you've probably been hearing about the huge changes in Drupal 8 that are like just so Fundamental and just bigger in nature than the kinds of changes. You'll have seen between other versions of Drupal but what I would say is that one one of the major drives with the kinds of changes we've been making is towards more standard ways of doing things and Getting away from Drupal isms Uncertainly with dependency injection Learn, you know, you'll have to learn it for Drupal 8, but that's going to stand to you No matter, you know, wherever you your programming career takes you beyond Drupal 8 So what I'm going to cover I'm going to start by looking at dependency injection as a design pattern as a way of structuring classes Then move on to looking at how frameworks support dependency injection Before getting more specific and looking at a symphony style dependency injection and then looking at what we're actually doing in Drupal So the first Item there dependency injection as a design pattern That's all about why you know as in why should you care about dependency injection and what problems does it solve for us? And the rest of it then is all about how like how how do frameworks support this? So why dependency injection? Well, normally when the topic of dependency injection is introduced You'd start off with an example of some object oriented code Where which isn't doing dependency injection and look at the kinds of problems that can arise But I thought it made more sense to take a bit of a step back seeing as we're not all object-oriented programmers here And just think about what sort of what sorts of common goals we might have when we're writing code So I think we can probably all agree that when we write code We want it to be clutter-free Reusable and testable now what I mean by clutter-free is just you know when you're writing a function You want it to be to the point and not going off on tangents You don't want to have lines of code that aren't central to what that function is all about And we'll see some examples of this in a moment Reusable obviously, you know when you go to the trouble of writing a function to do something awesome you want to be able to use it over and over again in different contexts and Very closely tied to that probably the first context you want to use it in is within the context of a test We want to be able to test up the code we write So we'll start by looking at an example of some procedural code that kind of does it wrong This is a totally contrived example It's very silly function that doesn't do anything interesting, but if you see the first line of the function body there Loads an include file from a module because it knows that it's gonna have to that's where the function is that it calls on the next line That module load includes that's an example of clutter like it happens to be necessary clutter But this function isn't in the business of loading files So that's clutter As for reusability Obviously this can't be reused outside of the context of a bootstrapped Drupal And it's very closely tied to whatever this other module does for it So it's not great. It's not clutter free. It's not not easily reusable and it's not easily testable Like if you wanted to test this function, you'd either have to have a bootstrapped Drupal or at least load the file Where module load include is defined So let's now look at the sort of classic example of doing it wrong an object-oriented code Again a fairly contrived example This is a notifier class that we have and its main sort of thing that it does is the notify method Which During the course of whatever it does it uses it sends an email and It uses an email or object to send that email and how it gets that you see in its constructor It instantiates one for itself At first glance it doesn't look like there's an awful lot of clutter going on here But that line where it's instantiating a mailer object that new mailer We could see that as clutter because you know This class should not be in the business of loading and knowing how to instantiate a mailer object Because you know what if it's not that simple maybe the mailer actually takes various parameters And if those parameters change like if anything about the mailer class changes well then this class is going to have to Change accordingly so we say that it's tightly coupled to the mailer class And that's bad In terms of reusability then You know what if you wanted you didn't want to use the mailer class as the class that sends the email You wanted to use something else And then obviously testability right you prefer to use a mock mailer something that's not actually going to send an email But here we don't have a choice We're being forced it's it's going to instantiate a mailer object whether we like it or not So what can we do about it? The only difference here you'll see rather than instantiating a mailer in its constructor. It takes one as its constructor parameter and So now it doesn't need to know how to instantiate the mailer now it's worth just transitioning back and Seeing the difference between that instantiating the thing in its constructor and that receiving it as a constructor parameter That's dependency injection. All right. That's all it is So like as one guy put it in a blog post. I read recently dependency injection is a $25 term for a 5 cent concept Like you're just passing the object its instance variables as constructor parameters Or if you want to be really fancy about it, you're injecting it with its dependencies So Here I've just put the calling code at the bottom So the thing that's going to instantiate the notifier first It's going to instantiate a mailer object and then it passed that into the constructor So if you've reframed this in terms of the goals that we had about writing code That's clutter-free reusable and testable another way of thinking about that Is we want to write code that's ignorant? Why ignorant? So the less your code knows the more reusable it is and if you think about it The more your code knows like the more it knows about other classes and how to instantiate those classes The more dependent it is that that knowledge that it has stays the same And that's that tight coupling that we want to get away from So let's look at this again and think well What does the notifier class really need to know about the thing that it's going to use to send the email? Does it even know need to know what the concrete class is that gets injected into it? It doesn't all it needs to know is that it gets going to get a thing on Which it can call the send method and pass these parameters and so the way we express that is It'll accept anything that implements the mailer interface So now at the bottom you can see instead of instantiating a mailer object We we use a special mailer and pass that in instead So that is constructor injection one form of dependency injection so the calling code at the bottom is injecting the mailer into the notifier and You can see the constructor at the top is expressing its dependency on anything that implements the mailer interface So dependency injection is about declaratively expressing dependencies in the class definition rather than instantiating them in the class itself So it's about having classes that are just kind of saying like I need These things to do my job. So, you know, you're gonna have to call me with my dependencies if you want me to do anything Constructor injection is not the only form of dependency injection It's the most common and it's certainly by far the most common that we use in in Drupal But there are some other forms another common form is setter injection So with setter injection rather than injecting things in the constructor here We have a setter method set mailer that again accepts anything that implements the mailer interface And so your calling code after instantiating the object will need to call the set mailer method and pass in the dependency So that's setter injection There's also interface injection, which is very similar to setter injection It's just that for every setter method that you have for a dependency. That's There's an interface for that. So it's like the class basically declares itself as being mailer injectable for example It's very verbose because for every setter method you you need to have an interface and it's not very common I don't think there are any frameworks that actually support interface injection You'll often hear dependency injection referred to as inversion of control these two terms are synonymous and I don't know about you But when I first heard that it wasn't immediately clear to me why Why it was called inversion of control? I mean I could I saw there was some kind of inversion going on But it wasn't crystal clear until I read one particular explanation of it, which I illustrated here So traditionally you might have a library of classes that your code makes use of so your code is going to Call out and instantiate objects from that library of classes and in this setup the library is passive It's just kind of sitting there going here's some classes that you can use if you like And your code is the active party. It's actively calling out and instantiating objects from those classes But with dependency injection the framework is going to is the active party and it's going to call your code with its dependencies So again, your code this time now is is Passive and saying like I need to be called with my dependencies if I'm going to do my job So that's the sense in which control is inverted here and Inversion of control is often referred to as the Hollywood principle Because as they say in Hollywood don't call us. We'll call you Now that you know if you take away nothing else from this talk Apart from what I've covered so far, which I hope won't be the case But if it is it's not the end of the world because that really is the most important part like that That's why we care about dependency injection, you know, we've created this class that's decoupled You know, it's clutter-free. It's reusable and it's really easy to test And the rest of the talk is about how how frameworks support that but obviously the how is completely irrelevant if you don't understand the why So now that we have now we have our classes all nicely decoupled from each other Declaretively expressing their dependencies The question arises. I mean, I've put that calling code down there at the bottom But where does that go? All right, in other words, where does injection actually happen? So the first option is the most the most obvious like a manual injection Which is just like the code that we just saw the calling calling code that actually instantiated the mailer and injected it into the notifier But you know, does that belong in a class somewhere then that class is responsible for knowing how to instantiate the Dependencies for the notifier etc. And you can imagine in the context of a framework where you want to support Different implementations for dependencies etc. So so that doesn't really work very well Another option is to use a factory a factory is just a class that's responsible for instantiating objects of particular kind But you know, you'd end up needing either needing a separate factory class or needing a bunch of logic to Deal with every possible object graph you could possibly want to instantiate and by object graph. I just mean Different concrete implementations like for the dependencies on there and the dependencies of the dependencies etc So what frameworks do to support dependency injection is they use what's called a container or an injector Actually, it goes by various names. So dependency injector or a dependency injection container Also known by its charming acronym, which in fairness is the easiest way to refer to it The shortest way to refer to it anyway Or it's also called an IOC container for inversion of control Or a service container and I'll explain why service container in a moment But basically what it does it assumes responsibility for constructing your object graphs. So instantiating your classes with their dependencies Uses configuration data to know how to do this and it allows infrastructure logic to be kept separate from application logic So why this word services? So you need to forget about web services or services module for a moment a Service is just an object that provides some kind of globally useful functionality That's best explained within an example. So here's some examples of services a Cash back-end for example, you can imagine Using a cash back-end in your own code where you just you want to say get me something from the cash Or similarly with a logger you would use a logger to just log stuff And you don't want to know anything about how a logger works. You just want to use it A mailer obviously as we've seen and a URL generator is another example Here are some things that are definitely not services. These are data objects right a product a blog post an email message So that should give you some idea of what we're talking about when we're talking about services And we're not talking about data objects like this So I found this nice diagram in a book on dependency injection Which I think gives a nice kind of simple overview of how things work together But I've added my own personal touch to it because basically There are three things you need to be aware of when you're working with a dependency injection container The first is classes and by that I'm just referring to what we've already talked about this the fact that you have This all your classes are nicely decoupled from each other and they're just declaratively expressing their dependencies And then but the classes don't know anything about the container They don't know that they're going to be instantiated by a container. They're just regular classes Then there's configuration which gets fed into the container and the configuration consists of service definitions All right, so for each each service has an identifier and then the definition consists of or specifies which class to instantiate for that service and What its dependencies are and so that the so the dependencies will then be references to other services So you can imagine when the ejector or the container gets asked for a particular service That it's going to look up what class to instantiate It's going to see if it has dependencies if it has dependencies It'll go and go and instantiate those first, but they might have dependencies as well Etc. Etc. So you can imagine there's this kind of viral injection that that happens Once a particular service is requested And then the third piece of the puzzle is understanding the the application flow like how does the application even interact with the container? because obviously The regular code we write isn't going to know about the container at all and it shouldn't but at some point like at the entry point To the application There's gonna have to be first of all it's going to have to instantiate this container thing and it's gonna have to ask it for services So understanding how that sort of that flow works Is important too so once you have your classes all loosely coupled and Declare to really expressing their dependencies the rest of it is all about getting wired in You talk about getting wired into the container So just showing some example configuration Most framework support XML based configuration. This is a kind of made-up Sample it's loosely based on a Java spring Java framework called spring and So here we're just specifying where we've got three services each of them has an ID and You can see two of them have constructor arguments that reference other services So you can imagine You know you'd have a huge big long list of these Services each with an ID and they could be referencing other services and basically saying I need that other service in order to my thing so this is pretty typical of an XML based configuration for a dependency injection container So how it works again service keys map to service definitions The definitions specify which class to instantiate and what its dependencies are and then those dependencies are specified as References to other services using their keys and at the end of the day the container is an object, right? So you're gonna there'll be some method that needs to be called on it to to ask it for a particular service by passing in the key scope is Something that's used this idea is common to most dependency injection frameworks And scope just refers to the context under which the service key refers to the same instance So for example each time a request is made for a particular service Should it instantiate a new object each time or should it always give you the same instance and Different frameworks have different default scopes As we'll see shortly So symphony has a dependency injection component This is a standalone component that can be used in various frameworks So it's used in the symphony full stack framework and it's used in Drupal 8 And what the component is is a bunch of classes including the container class itself and then various Supporting classes for like loading configuration and all that stuff Couple of things to note about how symphony does dependency injection It uses string keys, which is fairly typical, but there are other ways of Identifying services. This is just the sim. This is a very simple way of you can just use an arbitrary string Obviously most frameworks will have some kind of naming convention convention for how to name services And then in addition to being able to specify the class for a particular service and what its dependencies are You can also specify additional methods to be called On the object once it has been instantiated and that comes in pretty handy as we'll see shortly In symphony the default scope is container scope meaning for the lifetime of the container Unless you specify otherwise when you're defining a service then for the lifetime of the container It's going to the same instance will be returned each time that service is requested So if you wanted it to be a new instance each time you'd have to specify prototype scope It can be configured in PHP via an API where like you just make PHP you make API API calls to register services to the container or you can use XML similar to what we saw and you can also use YAML and The container can be compiled down to plain PHP And in order to understand what the hell that's all about We need to look into some symphony terminology now I almost feel I need to apologize for this part of the talk because You know, I was saying we're getting rid of Drupal isms. Yay. Now you have to learn all these symphonisms But the good news is like most of the code you write the regular code that you write in your lovely Decoupled classes won't need to know anything about symphony or symphonisms at all This is just for understanding how your classes can get wired into the container So what's this compiling business? Well, you can imagine that if we're parsing these configuration files to find out about service definitions It's going to be very if you've got a lot of services. It's going to be really expensive to do that on every request So symphony allows us to parse it once or parse when necessary as in whenever that configuration changes And then dump out the result of that into a PHP class. So it actually writes out a PHP class hard coding a method for each service definition for each service and what that looks like So this would be the class that actually got written out by symphony during its compiling phase and In this case it obviously only found one service And it was the example service So it wrote a method for that called get example service and what that'll do is it'll just return a new instance of some class So that's that's what the compiled container looks like synthetic services These are just services that the container doesn't actually know how to instantiate itself But if something gets instantiated outside of the container the container can still be told about it So if anything else expresses a dependency on that thing, it knows it can just pass this this object to it compiler passes This is all about modifying existing definitions of services So compiler passes are classes that you can use to process the container and change what's in there So an obvious use case would be if you want to actually change the class that gets instantiated for a given service Say, you know, you had the Cash back-end service or something and the default one used a database and you wanted to switch it out and make sure it Uses the one that had a memcache or whatever You could just change the class that was used and then another common use is What are called tagged services now? What are they? So tagging you can just add arbitrary tags when you define your services and all that is it's you're just It's just some way that you can then flag certain services for some kind of processing which you do in a compiler pass And this is used for example To register event subscribers to symphonies event dispatcher bundles, I I mentioned these reluctantly For obvious reasons We already have a type of bundle in core and now we have this other one basically bundles are symphonies answer to plugins or modules prepackage sets of functionality implementing a particular feature and Each bundle includes a class Implementing the bundle interface which allows it to interact with the container for example to add compiler passes Now the only reason I mentioned it at all is because we kind of use symphonies bundle idea in core Just for the ability to allow third-party extensions i.e. modules to provide that class that can then interact with the container and modify existing services Now it's worth going off on a little bit of a tangent to look at the event dispatcher. This is actually a separate component It's not part of the dependency injection component in symphony. It's a separate symphony component and we use it in Drupal core And the reason it's worth looking at is not only because it's a good illustration of all that Stuff about compiler passes and tagging, but it's it also plays a very important role in the application flow So if you remember that that diagram with the three things of how everything ties in together So understanding the application flow and how the application interacts with the container Event dispatcher the event dispatcher plays a very key role there So what it is? I mean, it's basically it's very similar mechanism to It's an alternative to Drupal's hooks system So this dispatcher dispatches events those could be events around the handling of a request But it can be used to dispatch any kind of custom event you want to make up Event listeners are registered to the dispatcher so it then knows it notifies them when a particular event takes place and Then event subscribers are they those are just classes that provide a whole bunch of listeners So each listener is a method in this event subscriber class And it's so it's basically is able to tell the dispatcher that for but for certain events These are its listeners So a compiler pass is used to do that to register all event subscribers to the dispatcher using their service IDs And it does that using tagging it tags them you tag a service as an event subscriber And that means during this compiler pass process It'll get added to the dispatcher And the dispatcher actually holds a reference to the container, which means if it's given service IDs It can it can get those services from From the container so it can instantiate these Subscriber services with their dependencies now I have that in inverted commas because when you think about it Events subscribers, they're not really services in a strict sense. They're not like what I defined earlier as Objects that provide some kind of globally useful functionality They're not going to be used by something else But they are their services purely in the sense that they are wired directly into the container and That's just all key in that that sort of Application flow or how things get kicked off in terms of that sort of viral injection of dependencies Okay, so this and and the next slide are as nitty-gritty as it's going to get I promise Just showing you what this is actually Drupal 8 code. This is that compiler pass class where these event subscribers get registered to the dispatcher so The class implements the compiler pass interface which is just that one method for processing the container and doing whatever modifications you want to do So in this case we want to modify The event dispatcher and the way we're modifying it is we're basically specifying that for every service that has been defined with the event subscriber tag We need the container to call a particular method on the dispatcher after instantiating it And so it's going to call the add subscriber service method So that's an example of this The fact that symphony lets you specify additional methods to call after instantiating a service and that's how it's used and How the actual compiler pass gets registered or gets added to the container is using this bundle mechanism. So We have this core bundle which We use to add compiler passes for various things So now that we've seen some actual Drupal code, it's time to talk about dependency injection in Drupal 8 So Drupal 8 has a dependency injection container obviously It provides a whole bunch of services some common ones that you will definitely be using The default database connection is a service There's a service called the module handler, which you'll need You'll need that if you want to invoke hooks in other modules or do anything that requires knowledge of enabled modules The HTTP request object is also a service, but that's an example of a synthetic service, right? That doesn't actually get instantiated by the container. It gets the container just gets told about it So that other things can depend on the request service This is a bit of a wall of text I just wanted to show an example of the configuration for the container in Drupal. So we use YAML and This is just an extract from the core dot services dot YAML file where all of course services are defined If you skip down to the last one pass dot alias manager And just so we specify what class to instantiate for the alias manager and then what its dependencies are So these are just the constructor arguments to pass And each one of those is a reference to one of the previous services The app symbol is just how we tell the container this thing is a reference to an existing service So it'll know then to instantiate those other services first before instantiating the alias manager and I just wanted to show this is alias manager's constructor I'm showing it just to kind of point out that like the alias manager itself doesn't know anything about the container It's just saying like it needs a database connection It needs something called an alias whitelist and something else called a language manager and as long as it gets those things It's happy So if you want to use any of the services provided by core You've got a couple of options The first is if you're stuck in the land of procedural code you can use a helper So it's a static method on the Drupal class Where you just ask for some service Specifying it by its key That's not the preferred method. That's essentially a kind of an anti-pattern known as service locator where you actually you know about the container and So that means in order to be able to do anything with it You need to know the names of actual services And we don't want our code to know the names of actual services, right? That ties our code to the container itself and we want to get away from that So the preferred option is to write object-oriented code and get wired into the container Now this diagram quite possibly breaks all kinds of rules in terms of diagrams It was just my attempt to Somehow get across in a simplistic a way as possible what the actual application flow is in Drupal like how how does The container get instantiated etc So basically what happens is index.php instantiates this thing called the Drupal kernel and asks it to handle a request The Drupal kernel doesn't actually know how to handle a request, but it knows how to build How to construct the dependency injection container? So it does that and that's you know on a regular page request. That's going to be just instantiating that That hard-coded class that we saw where everything has so it's just a class that has a bunch of methods that know how to return objects for services So once it has instantiated the container it asks it for a thing called the HTTP kernel service Because the HTTP kernel is what knows how to handle a request so It gets that from the container and then passes off handling of the request and The HTTP kernel has a couple of dependencies One of them is our friend the event dispatcher and the other is a thing called a controller resolver So the event dispatcher as we already saw it already knows what all of the Listeners are that listen to particular events So when the request is being handled one of the first things that happens is the dispatcher dispatches the request event Basically just saying does anything out there want to react to the fact that this request has come in You know maybe make some changes to the request itself So obviously one way that things get hooked in is you is at these events subscriber services And they will get instantiated with their dependencies by the dispatcher itself And then the other way and probably the more common way that you will end up interacting with the container is code for a particular page so in With symphony we We don't have page callbacks anymore. We have the equivalent which is We have this new routing system which matches a path to a route which specifies a controller And the controller is just the actual page callback for that particular path so the controller resolvers job is just to find what the controller is for for that route and So in a moment, we'll see how you can get hooked in You know how your controller can get hooked in and why I have a question mark around whether it should be a service But first just a quick look at how you would get wired in as an event as an event subscriber First thing is you'd need to implement the event subscriber interface There's just one method in this interface, which is a static method where you tell you're basically telling the dispatcher What events you want to listen to so in this case It's saying it wants to listen to the request event and the method that should fire on that event is the on kernel request method Which refers to one of its own methods and that that method will be called in that event So that's the interface that needs to be implemented to hook in and then the other thing is that it will need to get Defined as a service and the service will need to be tagged as an event subscriber and so one example of this is for example the path subscriber which is responsible for Resolving the request path to a system path. So it's it subscribes to the request event Looks at one of the attributes of the request and then you know It has a dependency on the alias manager to look that up and convert it to a system path But as I said, you're more likely to to be interested in getting hooked in for a code that that should run on a particular page So how do you get your controller wired in? So controllers obviously are gonna have dependencies on services, you know, like the database and various other things But whether they should themselves be directly wired into the container is quite a hotly debated topic in the symphony community So like the core symphony guys are against the idea of controllers themselves being services Whereas the symphony cmf guys, it's another framework built on top of symphony components They think controllers should be services In Drupal our feeling was that they should not be I mean one main reason is when you think about it You're gonna have an awful lot of controllers right controllers are your page callbacks and If every single one of those is a service you're gonna have this your service container is just gonna be a huge big bloated thing full of Services that are really just for glue code because your controller should really just be about matching the route to the code that needs to run So I think it's supported you can your controllers can be wired in directly as services But it's not the recommended way the recommended way is to implement an interface It's the controller interface I believe and it's just one method a static factory method and that Factory method accepts the entire container and can use it then to pull out services and instantiate the controller with whatever services it needs An excellent example of this in core is book module. So have a look at that and there's also Really great documentation explaining How book module was converted to use the new routing system and how the how book modules controller Gets its dependencies it injected First rule of dependency injection containers don't inject the container ever unless you absolutely must and So the thinking behind that is basically once you inject the container into one of your classes Your class is then coupled to the container It the only way it can do anything with it is if it knows about service IDs And why would you want your class to have that kind of knowledge? So the only time you'd ever have a class that has the container as a dependency is if that is just part of your infrastructure logic so not your normal code for You know that does the regular stuff just the code that that is part of the framework itself really For those curious who want to actually dive in and look in the Drupal 8 code base and see where all this is happening So where the I've just listed, you know, where you where you can find this stuff So where the Drupal kernel is where the services are defined Where this bundle thing is which may not always be called a bundle we may we may get to change that in time We'll see we because it's as I said it's just about allowing modules to modify the container in some respect and Then where the compiler passes our core has a number of compiler passes including the one for registering event subscribers and then for your modules if you want to You know write some nice decoupled classes and have them wired into the container You know if you want to define them as services you'll have a YAML file for them and then You'll need if only if you want to if you want to use that compiler pass mechanism You'll need a bundle class as well for your module And all classes including compiler pass classes Need to live in a particular directory. Now. That's just tied into our The PSR zero standard that we're using for Namespacing classes so that our autoloader knows how to where to find them. So that's Basically all I wanted to show you about dependency injection, but I wanted to finish off really quick just to talk about testability because we now have PHP unit in core, which is a really awesome unit testing framework and so that in conjunction with using dependency injection Makes for really easy test ability now this has nothing to do with the container at all so you can forget about that for this This is just about having Lovely decoupled classes and a lovely testing framework to test them with So there's just one thing I wanted to cover with it, which is the ability to create test doubles Or stubs So say one of your classes has a dependency on something the language language manager is a good example because It's a bit of a gnarly one I think it still calls out to procedural functions and If anyone was in marks on a bum's talk earlier this morning about you know We can't have that kind of thing those kinds of hidden dependencies in unit tests because These procedural functions probably end up calling out to looking for database connections and all kind of horrible things can happen So we don't want to instantiate the actual language manager We're just trying to test a class that needs that has a dependency on the language manager. So instead we can create a Stub of it and PHP unit provides these helper methods for for creating these So the get mock method you just tell it what class Move closer to it. How's that? I don't think it's oh How's that okay, right? So PHP unit allows us to create Stubs of things just by specifying what the class is and then you can just tell it what behavior you want it to exhibit In that when you're using it the point here is we're not interested in testing the language manager class itself We just know that the class we are testing Needs a language manager or needs something that it thinks is a language manager And it's going to behave the way the language manager would behave So we just tell it to behave in a certain way and in this case We're saying if the get language method gets called on this class. It should return This a standard class object with these properties representing the English language So that's a very straightforward use of this get mock Method that's provided by PHP unit. Here's a slightly more complex one if we wanted to mock the alias manager So as we saw the alias manager has a bunch of dependencies one of which is the dependency or which is the database connection and then a couple of other things and But we just want to pass in an alias manager to the class that we're testing and know that it's going to behave the way it should so we disable the original constructor when we're getting when we're creating a mock for this and Below there we're specifying how we wanted to respond to the get system path method call and We're using a value map and that allows us to say if get system path is called with the value with the parameter foo Then return user slash one if it gets called with the parameter bar then slash return node slash one So that makes for like really really Tests that are just a joy to write when you can use this stuff Because and and it's because you've decoupled your classes from each other and you know You can just pass in these stubs and it all works beautifully and best thing about it is it's really really fast so I'm just going to We don't have that many unit tests converted to PHP unit yet in core, but Just going to run them there anyway like It's like 165 tests and it took two seconds and you know if you're familiar with watching Using simple tests and you know how long a single web test takes to run because it's like installing the whole system and everything Just because some procedural function somewhere Is this expecting a database to exist and we don't need that for the vast majority of the code that we want to test So PHP unit is awesome Okay, I've just I've put up a list of resources Basically, there's all kinds of further reading you can do sort of general stuff about dependency injection and then I've put links to Symphony specific stuff and then Drupal 8 specific documentation And oh, yes one other thing to mention like by far the best way to get really comfortable with this stuff is to Help in the ongoing effort to convert Drupal To using all of this because we're by no means completely there yet So and this would stand you in really good stead when it comes time to Converting your own modules to Drupal 8 so come along to the sprint on Friday and help out And now I'd like to open it up to questions Oh, yeah, anyone who has a question you need to go and stand up the mic there, please Hello Thank you for your awesome talk very informative. You're a great instructor So this isn't necessarily related directly to dependency injection, but the topics you covered today You know, I feel like this is kind of like a really jaw-dropping Kind of moment even though this has been happening or the past months in the whole D8 build and everything But how do you think this is going to affect the technical part of the Drupal community in terms of Size or I was just thinking about it listening and following along. So what do you think? Do you mean in terms of the fact that we are moving towards more standard ways of doing things and Well, like yeah, I mean the hope is that you know Developers who have been working on other PHP projects or you know who are familiar at least with PHP But not with Drupal won't be scared off because we're getting rid of like these real special ways We have of doing things and we're using Sort of best practices and what the rest of the world is doing So yeah, my hope is that it's going to have a very positive effect on the technical part of the community Thanks. So this may be a dumb question, but it may not be Does this Has this effect like the hooks do we are we replacing hooks with events or our hooks still a concept We're going to be handling that is definitely not a dumb question Some hooks have been replaced with events And there is in fact an issue ongoing that CHX is working on Which would basically support? It would basically I think support leaving hooks in place, but essentially have them fire as as events I haven't been following it too closely, but I mean the the simple answer is no hooks haven't gone away yet not by a long shot But certainly some some things have been converted to events As a follow-up question Sure, how does one know other than you know strapping your boots on and jumping into it? What's a hook and what actually needs to be sort of more object-oriented? Like when do you pick one versus another in the in the new paradigm? Well, everything will I mean everything should be documented So if the hook, you know look at API dot Drupal dot org and I Haven't seen If this is the case, but like if something that has been a hook through Drupal 5 Drupal 6 Drupal 7 and so on and and then no Longer exists in Drupal 8. I'm pretty sure there'll be a link to what the Equivalent way of doing it is in Drupal 8. I think I am not totally certain much appreciated. Thanks. Oh, yeah Go to Drupal dot org slash list changes and you'll see Thank you for that terrific talk. I if you'll permit me I want to make an announcement about something That's totally unrelated. Sure. I just came from a FEMA conference call where they are talking about emergency disaster response to the Oklahoma tornado and so a bunch of people are trying to organize a code sprint tonight Starting at 730 at coders lounge where we're gonna work on building some apps that FEMA that would really help FEMA's disaster response For the tornado victims in Oklahoma. So anyone who's interested 730 tonight coders lunch Thanks, Brian Hi, this isn't really about dependency injection and it's a really basic level of questions. So Hope it's okay But you mentioned like with our modules if we want to talk into this and you actually gave the path name where our Where we would put our information So I don't know if you're able to get back to that slide or not But the path in that you gave was something like my module slash something anything slash Drupal then slash my module and then so Yeah, yeah, my module slash live slash triple slash my module slash my module bundled up PHP So my question is Once we're within my module, I mean I can understand like why do you want live less Drupal? But then why do we put my module? again after that Okay, so there's a huge big debate raging in a particular Issue somewhere on Drupal.org about that very question You know I This is the way our namespaces are registered currently So we have an auto loader and we basically tell it about these particular namespaces So for each module that's enabled it knows about the lib Drupal slash my module namespace So when it finds a class that's within that namespace it knows what directory it's in Get involved in the big raging debate I Don't really you know, I can't really say any more about it. Okay, how would this So how would you deal with cross-service dependency, you know service a says I need service B and service B says I need service a That's just a bad design. Well, I mean there are ways No, it's not ways of sometimes sometimes there, you know circular dependency like just happens to be necessary and there are various ways around that like using proxies and this kind of thing, but I Don't think there's any anything specific in in the dependency injection container that knows how to in fact I'm pretty sure you can't have circular dependencies in the dependency injection container I Have been doing some page conversions yesterday during this code is print great I Have been using like a lot of controller classes and there is so many of them How do you decide which one is the correct one to use for the router conversion because there's so many of them? Another question is why do we use dependency injection through the symphony component? And the third question is what the services dot ml file in the plugins do for the module? So the first question about controller Which controller so I was just like for example user underscore page Converting that hook menu to the new router For the triple eight and then we were we have been using like a lot of controller classes like triple Core and then controller and bunch of the classes name. I don't know I've been told like just to follow the example and do the conversion because I'm trying to learn Okay, well, I'm sorry that you were told just to follow the example And I'm also sorry that I don't know the actual answer to that question I haven't been involved in in these conversions And the best person to talk to is probably Larry Garfield and ask him And don't accept being fobbed off and told to follow the instructions Sorry, what was the second question? Why are we in question is are we still using dependency or I don't know about that But do we use the dependency injection through the symphony component? Yeah, we use symphonies dependency injection component So it provides the classes like it provides the container class and You know in certain cases we're probably overriding some of the symphony stuff by subclassing it But it's yeah, it's the symphony dependency injection component. That's power. Okay, and third question is what? Services yaml file in the plugin directory do for the module What is the services yaml file? Yeah, so that's where you actually define the services So each service has an ID and you specify which class which like actual concrete implementation You know you specify the class to instantiate for that particular service. Thank you So this is related to the question About the screen you went back to Suppose I'm writing a module and I want to You know take take some existing JavaScript library or some existing php library and and provide a wrapper for it with my module wouldn't I then Put files under my module lib and then vendor and then whatever library I'm importing That's a very good question. I'm not actually sure what the What you're supposed to do in that case, whether it's a vendor. It probably is a vendor directory that you need I don't know mark. Do you want to speak to that? And there's a talk about composer, right? I don't know if that's happened yet, but Rob Loach and Larry Garfield are going to be talking about composer okay, but I guess what I'm trying to get at is is Another answer to the question that was asked earlier and I think the idea is that You're supposed to ignore the my module part and and lib slash Drupal is the same whether it's in my module or your module and And there can be other things inside it like lib vendor. Am I right? Okay, thank you You mentioned controller resolvers and I'm sorry, but I kind of went my my eyes glazed over because all I could hear was struts so But I didn't see an example of one. Did you did you show one? I didn't show a controller resolver There is one controller resolver like the controller resolver is just responsible for finding the controller for that particular route But I didn't show an example of a controller either But I pointed to if you look at book module in corn. That's a really good example Of how how that gets wired into it. It's not like struts though, right? Sorry, it's not like struts though, right? I have no idea. Okay. I hope not Don't go look at struts. Okay. I think that's everything. Thanks very much