AngularJS NYC Meetup – Feb 2014

JEREMY ELBOURN: OK Hello I’m Jeremy Elbourn I am a front-end engineer I work on double click campaign manager here in the Google New York office It is the largest Angular application in the world that we know about, and because of that, we have learned a lot of things about building really large Angular applications And so as a part of that, what I’m going to be talking about today is organizing your Angular application Now during this talk, I’m going to talk about three different parts of this organization First is how you’re organizing your files within your project Second is organizing your logic within your application, and then organizing the code itself And I’ll try to explain the distinction between organizing your logic and organizing your code once I actually get to that point So to start off, I’m going to talk about organizing your files So a lot of you are probably really familiar with the old or current way of organizing your files This is what is currently represented on Angular Seed if you go to GitHub, which is the Angular team’s really trivial sample app that they have It is organized by services, controllers, views, et cetera So things are categorized by type They have one module per directory in this way, or per type of these things So there’s a services module, controllers module, directives module, and this is not really an ideal approach for building an application that is more trivial than something really trivial So a to-do list It gives you really poor control over your dependency injection configuration, which is what the Angular modules are really for And the directories become really bloated It’s hard to find a particular service in a directory that has 20 or 30 different services in it Same goes for directives, et cetera So the Angular team realized this, and just last week, they published to their blog a new recommendation The new recommendation is to organize your project by component or feature Doing this in such a way that it will probably mirror your application structure itself This is going to make it easier to extract and share different components, and it allows you to create Angular modules that are– or it forces you, rather, to create Angular modules that more accurately reflect your injection dependencies So we have an example of this here So this is just a fake little project I made in IntelliJ to highlight what it looks like And so at the root of this, we have two folders inside of our sample app One is called App, and this contains all of your application stuff It has your JavaScript code, your CSS, your HTML, everything that is actually part of your application There is another top level folder here– you can see it towards the bottom– called Scripts This just has some demos, server shell script I included this to demonstrate that anything that you have in your project, that you have maybe in source control or whatnot, this goes outside of app It doesn’t have to be scripts It could be anything It could be documentation It could be games As long it’s related to your application, and you’re keeping it in your same ID project, then you could put it in a root folder outside of app Now looking inside of app, this is what we actually care about We have one top level folder called Components, and this is where all of your shared components for the whole application go So in this example, I have a date picker directive and a dialogue service as the two components that are used in this application The date picker has its CSS, its template, its controller, its directive of configuration, and its test all on that one file Same goes for the dialogue service All of its own files are within that directory Then outside of Components, we have what we’ve been calling Sections, so these would be the different pages or views in your application In this sample application, we have a sample list and a sample properties, and each of these just has a template controller test, template controller test And then inside of app, just by themselves, not in any other directory, is your app.js,

which is going to have your app module, your one core Angular module that is going to have its dependencies on everything else, in addition to your App Controller, which is for your application Chrome, the things that are outside of your ng-view and your index.html And this is much neater than the old way when you have a really large project It makes it easier to find files that you’re looking for, and it makes the– having each of these sections be its own Angular module lets you more easily just say, this module has a dependency, or your app has a dependency on this module, and when you’re running tests, you can only load the module that you want to load You can read more about this I’m going to have a link at the end, and it’s also linked from the Angular blog So in terms of setting an example from the Angular team, this new recommendation is going to be reflected in Angular Seed, Angular Phonecat, and the Yeoman Generator Angular sometime in the not too distant future They’re not updated yet, but it will happen at some time So that pretty well covers organizing your files with the new recommendation And so now I’m going to talk about organizing the logic of your application So Angular talks about services and controllers and directives and filters, and you are probably all very familiar with this And so it’s great You know exactly how to break up your code, until you have something in your application that looks like this This is something we have in the application I work on It’s this giant hierarchical list where you can open things up at a side pane There are lots of different buttons for doing different things There’s inline editing, bulk editing, sorting, paging, carouseling, the works And this really brings us to the problem with controllers When you have a big app, you’re going to have lots of common functionality And when you have very complicated views, the controllers for these views can end up being thousands upon thousands of lines long, which is really undesirable And how many of you like to work with a file that has 7000 lines of code in it? So how can you break up your logic that is going to be used in many controllers, or break up your logic into one from one very large controller into more encapsulated pieces? So my team’s tried three different approaches for this Well, maybe more than three, but I’m just going to talk about three So the first is inheritance And this is what we did when the application started, your traditional object-oriented inheritance, or if you’re being technical, prototypical inheritance for JavaScript So we would have a base controller, and then a base list controller, and then from that, a base editable list controller And this runs into some problems Your hierarchy can become too deep and confusing, so we ended up having some controllers that were five or more levels deep There’s some logic that doesn’t fit neatly into a generic parent, so we would have something like a list of ads, and then we would have an ads properties page, and we would have some logic that needed to be used in just those two places, but that list page, inherited from base list, and that properties page inherited from base properties page, and so where does that go? And as always, when you’re using inheritance, you have imperfect encapsulation, because implementation details of a parent class, like a base list controller, are going to leak into that child, even though the child doesn’t really need to know the details of how that base list controller is doing things like paging and sorting It just needs to know the API for doing those things So we tried to move away from the inheritance model a little bit when we could to try using mixins For those who don’t know, mixins are kind of like atomic pieces of functionality In JavaScript, it’s essentially creating an object that has some functions defined and then extending another object with those functions In this case, we did that with controllers So as an example, with the same list idea, we would have a controller that mixed in a list mixin,

and this mixin would have the functions for pagination and sorting and filtering and what have you And we ended up really hating mixins They did not work well for our project It became really unclear where code came from, so you’d have a controller with some property or some function, and you wouldn’t immediately know if this function– did it come from a mixin, or did it come from inheritance, or who knows? It has it defined in this file Mixins could also potentially conflict with or overwrite each other or functions on the controller, and this got confusing, because we were still using some inheritance at the same time So there are some cases where you’d have a mixin that overwrote a function that was already inherited from another class, and that just became really confusing, and it also had a problem where mixins were tightly coupled into the mixed into object So for this list controller, this list mixin rather, it would have dependencies on certain properties being present on the controller already or on the scope, and those dependencies were super unclear as to what they were, and it was very easy to mess stuff up and break your tests Fortunately, we did have test to catch that kind of thing So overall, not a fan of this And so what we’re doing now, and it seems to be working pretty well, is to use traditional object composition that takes advantage of Angular’s dependency injection And so what I mean by this is– this is taking forever to update What I mean by this is– OK Finally Is by just on your controller, saying, controller.listmanager equals, and then creating an instance of that List Manager, where List Manager is an entirely separate object that is going to manage all of your list operations– paging, sorting, filtering, et cetera And in this case, I’m using $injector.instantiate to create that instance of the List Manager Now in normal programming outside of Angular, what you would do here is you would do something like controller.listmanager equals a new List Manager But that is not going to totally work for us here, because we have dependency injection And, well, in an ideal world, we’d be able to inject an instance of this list manager, just like you would if you were using Juice in Java or an Inject in C# Angular, unfortunately, doesn’t support this right now, because the dependency injection system in Angular is based on singleton So any service that you’re going to be injecting is a singleton Constants are global throughout your whole application, so when we have something that is stateful that we only want to have a lifetime of one route, as opposed to the lifetime of the entire application, it doesn’t really give you a way to do that Now you could create a service that was a List Manager factory and inject that and use that to create your instances, but that seems like way too much work, and we didn’t want to do that So instead, we just use injector.instantiate to create these as if we were doing new List Manager in the controller constructor And looking at– so this is a side note on injector.instantiate The way this works is we have some class, in this case, app.cake, and it has some parameters for it’s constructure It takes dollar out, and pastry service, and frosting But if we were just to do My Cake equals New Cake, then that dollar route is not going to be able to be injected That pastry service is not going to be injected So we need to create the instance of the class in such a way that it receives this dependency injection, and the way we do that is with $injector.instantiate You pass at the constructor, and then you can also pass at another object that is the parameters that will be injected So if you don’t specify something, it’s going to fall back on whatever the default is So in this case, I’m only specifying frosting, which is like a setting for the cake controller, or cake class And Angular is automatically going to figure out that dollar route and pastry service

are already services that have been registered The dollar controller service kind of does the same thing It’s just weird to use dollar controller, if the thing you’re creating is not a controller, semantically So there’s not really any difference that I’m aware of between the two, other than dollar controller might require you to pass a scope in I’m not sure about that And so using this object composition, you get some really nice benefits You have better encapsulation, because the details of the implementation of that list manager, in this case, are totally hidden from the consuming controller, other than the API that you have designed for that List Manager And because of this, it forces you to come up with a more coherent API for your List Manager, in this case, or what’s happening with your controller Normally it can sometimes be a problem where you’re designing your controllers in a really ad hoc fashion You’re writing your template, and you suddenly realize, oh, well, now I need a function to do this, and now I need a function to do that It ends up being pretty tailored to your view But in this case, by creating the separate object that has an API that’s going to be consumed across a lot of controllers, it makes you really sit down and think about what you’re actually having people consume, and it also makes– by having separate objects, you are making it easier to reuse them, because now you can compose these different managers or whatever you want to call them We’ve come up with like eight different names for doing this on our team from Companion Controller to Scope Buddy, or things like that And so you can have a page that has a list on it, and a properties pane, and some other stuff, and all you’re doing is composing these different pieces The problem with not being able to inject these objects themselves, hopefully, that’s going to be solved in Angular 2.0 as the team is working on totally reinventing the dependency injection system And so the moral of the story with looking at these different logical organization schemes is that just because a framework gives you some guidance as to the objects that it’s using, in this case, controller services directives, it’s important not to forget everything you’ve ever learned about software design With a shout out to our “Traditional Design Patterns” book, great reading for everyone of all ages throughout time So the last topic I’m going to talk about is actually organizing your code Soon as the slides change I don’t know why it’s taking so long I’m going to skip the slide that just says Organizing Your Code It was nice though It had contrast and everything All right So for the things I’m about to talk about, these are rules that are used by my team and used by teams throughout Google internally They work pretty well for us, but your mileage may vary A lot of people have some very strong opinions about things like the way objects should be defined or created or instantiated in JavaScript, and I’m not going to really argue about that I’m just going to talk about what we do, and that it works for us So the first thing is that we treat controllers and services like classes So here we have an example, app.mycontroller and app.myservice, a controller and a service Each one is set up such that it has a constructor, which is the function That’s the first thing that it is And we put functions on the constructor’s prototype, normal JavaScript prototypical inherent stuff Really straightforward But by doing this, we can talk about things in a very traditional object-oriented sense We have classes, and we have their constructors We have class methods, and we can make static properties or static functions by putting things directly on app.myservice instead of the prototype So really the vocabulary and just the consistency across other different programming languages and talking about object-oriented design makes this really useful Next piece of advice is to use directive controllers So a lot of people end up creating a directive

and putting the bulk of the code for that directive inside of the Compile function or inside of the Link function And what this does is it just gives you a super bloated and hard to read Compile or Link function The real purpose of those functions are to do things that have to happen in the compile stage or have to happen in the link stage, or to try to manipulate the way in which those stages operate But for the logic that’s just operating your directive, it’s best to stick that inside of a controller You can specify this in your directive with the controller property And this is going to just have Angular create a controller instance, just like it does for any route that you would normally go to inside of your ngView And the controller for the directive is injected with four different things that are specific to directives Well, I guess $scope isn’t, but $element, $attrs, attrs for the attributes, and there’s also $transclude, which is the pre-bounds transcluding linking function if you are using transclusion I did not include that in this example And you can do with your directive controller anything you would do with a normal controller It’s perfectly OK to do DOM manipulation inside of your directive controller I know the adage goes, never put DOM manipulation in your controller Always put it in your directive In this case, this counts as being in the directive So you can set up event antlers from $element here You can read properties from $attrs and put that on the scope, and so on We found that following this has helped our directives be a lot more understandable, and keeps the code cleaner And we saw the benefit of being able to talk about these controllers as normal classes, object-oriented stuff You can even, in some cases, if you need to do something really complicated, have directive controllers that are inherented, and create another directive that is an inherited version of another controller that has stuff overridden with actual functionality But that is a very advanced and somewhat tricky use case One thing you might notice in this example I have is also specifying this controller as property in the directive And so we actually use that a lot internally Our style guide dictates that for anything that is written new in your template, you bind to things through the controller So really, we pretend that the scope almost doesn’t exist, and everything that you’re binding to in the scope is really accessed through this controller property But we just pretend it is consuming the controller directly And so this helps us look at our controller and say, this is the API for my template versus having properties that are just kind of stuck on the scope at random points throughout the controller’s life cycle It can be hard to track down where a scope property is coming from By doing it this way, we find it just to be easier to maintain what’s actually being exposed on the view and making sure it conforms to a consistent API You can see my example here We have a button that [INAUDIBLE] as controller.dobarrelroll instead of having it in your controller, and saying scope.dobarrelroll equals some function And the very last thing I’m going to talk about is using highly granular Angular modules for your code So the idea here is to use one module per service per directive, et cetera And by doing this, you’re going to have the greatest control over how your injector is configured So the Angular modules, the whole point of them is to configure a dependency injector A module is used for saying, this module has these services, these directives, these controllers, and by making it such that each atomic component has its own module, it gives you the greatest control over how you’re actually configuring that injector It also makes it much easier to extract code in a shared component, so we had an issue on our team where we would have one module for all services,

and then we wanted to take a service, and bring it into a shared library But then we had to refactor some of our code, such that the modules were ordered differently by having modules just for every component Instead, if we wanted to take that service, and put it into a shared library, we would just remove it, and its module would still be standalone and not have dependencies on other stuff that were hard to codify And it also makes testing much easier Similarly, like we had a problem where when we wanted to test our one service, like all we would need to load is one service, but because they’re all in the same module, we would end up loading every service we had in our application in order to just test one This made our tests really slow, so it’s much better to just load your single module Your test will run much faster, and I have some example code here where you can see you’re creating some service This is its constructor And the angular module for the service, you can just set it as a static property on the service So in a way, you’re just saying, I’m creating this class, and it does this stuff It has this API And one of the things that is exposed on this class is a static property that is an Angular module that tells anybody who’s interested, this is how you would configure this class for use in Angular, if you’re so interested And configuring that to be used in your application is, I’m sure you’re all familiar with just creating your main module and adding the dependency on the module A little note about this You’ll see that I’m referencing the module via the module’s name property, instead of using the string directly We do this, because it becomes problematic when you start using the strings everywhere, because you can accidentally include a string for a module name without actually setting up your dependencies correctly for your compile time dependencies or your minimization dependencies So in our case, we use the Closure Compiler, and it’s possible to put a string name here without doing a goog.require for the file where that module is actually in And the Closure Compiler will yell at you if you actually try to reference it this way without requiring the file, but if you just use the string name, it’ll turn that into a runtime error where you’re going to have to open up your console, and say, oh, this module is not actually defined So it makes it a little bit easier And this is true if you’re using RequireJS or whatever else to manage your file dependencies And some links I have here– one is for the new best practice recommendations for the Angular app structure, which was published to their blog last week We also have a public version of our Angular JS style guide for Closure users at Google This was also published at the same time in the same blog post It’s a subset of the style guide we use internally for Angular It’s pretty heavily focused on closure right now, because that’s what we use at Google, but I believe the Angular team is looking for people to make contributions to that that are less closure specific I also have a link to a somewhat related talk from ng-conf that my team gave about building large scale web applications The video for that is on YouTube It has some related content It’s a little bit of the same content in both talks, but that one has a lot more And I also have some JS Fiddle links for the three different patterns I talked about for organizing your logic, the inheritance mixins, and object composition Those examples are actually from that talk from ng-conf And that’s all I have today Oops This is going the wrong direction, but any questions? The lapel mics weren’t working very well So I’m going to stick with this hand one, and we’ll just live with it MALE SPEAKER: There’s a question AUDIENCE: Hello? Hey It seems weird to me that the test code is like interspersed with an application instead of in its own directory, and the fact that usually you share it at least your production code separate from your test code, and they should all be in one place So why is it organized like that? JEREMY ELBOURN: So it was weird to me at first too, because I was used to seeing it the other way But after a couple of weeks of working with it this way, it just kind of got to seem normal, and it did make it easier to say like, oh, here’s everything related to this component It’s all lives in one directory If I want to move it to a shared library, I just copy this directory over

You do have to do a little bit of dancing with your build rules, whether your grunt or anything else to make sure those tests aren’t actually included with your production code But that is more of a one-time setup cost of going this route AUDIENCE: This is a pretty technical question for using the controller as How do I set up a watch when I use controller as? JEREMY ELBOURN: So you can still inject scope, and still do scope.watch whatever you want The only difference is your expressions that you’re watching are going to start with CTRL dot, or you can also just give it a function that pulls things directly from the controller instance In our world, for new stuff, the only time that you are injecting the scope is to set up watches or event handlers for like broadcast and omit We’re never actually putting properties on the scope to go on to the template anymore MALE SPEAKER: Raise your hand if you have a question AUDIENCE: So when you have the controller that’s specific to your directive, and you said you could pass through, say, attributes and element and transclusion, is that like the linking function where it’s specific of order, or is it more like the controller? JEREMY ELBOURN: No So with the linking function, the arguments are actually passed in as a normal function call But for the controller, it’s actually using the dependency injection, which is why in the example I had, it is– well, if this refreshes– OK It’s $scope, $element, $attrs Those can be in any order They’re just injected like normal services would be Anyone? We normally have so many questions AUDIENCE: I hope this isn’t off-topic, but could you talk a little bit about how you do your build process and how you structure each component of your application? JEREMY ELBOURN: So in Google, we use a proprietary build tool that I can’t really talk about, and it’s not really useful for me to go into any detail, because it’s all pretty much tied into that AUDIENCE: If I want to profile my application, do you have any tools you would advise, because I know there’s like [INAUDIBLE] with Chrome, but it does not provide enough details JEREMY ELBOURN: So as far as profiling goes, we don’t have any special tools that we use on my team for doing that Any profiling that happens is just happening with the Chrome dev tools We have one person on our team that really ends up doing most of our optimizations, and he gave a talk at ng-conf about performance, and that video’s on YouTube if you want to find it He goes into a little detail about his process for trying to track down problematic performance issues However, there is work being done by the Angular team to add performance profiling into the framework itself I believe it’s like James [INAUDIBLE] I don’t know how to say his name, is working on that So something is in the works AUDIENCE: I don’t remember what the originals, the new structure you showed, but do you ever like create modules within those modules that are organized in a consistent matter? JEREMY ELBOURN: Oh, yeah I probably should have mentioned that So it is recursive, so you can have a component that has subcomponents, or you can have a section every application that has subsections unto infinity However, getting your build rules set up to handle that is not covered by the recommendation So good luck with that AUDIENCE: Are there like– and I’m kind of new to Angular– are there any kind of generators that’ll generate a model for you in a system structure? JEREMY ELBOURN: So there are Yeoman generators for Angular

That’s the generator Angular, if you install that with MPM But it’s not yet updated to reflect this new recommendation It is probably going to be some time this year I don’t really have any insight to when that’s going to happen, because it’s– I mean I’m not that heavily involved with how the Angular team’s getting this stuff up MALE SPEAKER: Anyone have a question? JEREMY ELBOURN: I can tell some jokes AUDIENCE: Hey, I’m pretty new to looking at Angular and just the whole framework, and I’m just wondering, how does Angular deal with security and like reverse engineering of code, things like that when you have like an entire one page app on the client? JEREMY ELBOURN: OK Well, this isn’t really a problem that’s specific to Angular This is just for any client side development whatsoever And I mean, your normal standards apply of you should be minimizing your production code This obviously obfuscates that and makes it pretty difficult for anyone to really get a hang of what it’s doing There’s like a lot you can read about the topic I think it’s a little bit broad for me to go into right now I think– we’ll do one more AUDIENCE: How many like controllers and directives did you have before you thought it was too hard to manage? JEREMY ELBOURN: So it’s actually an interesting question that you ask that The project that was really, really large is actually still using the old directory structure, because it would be a lot of work to change it And my experience with the new structure is from the new project I’m working on that is starting brand new and doesn’t have very much stuff in it yet So we’ll see how that goes But we probably have like somewhere between 30 and 40 services in like one Services folder, and there’s probably like 60 to 70 controllers in another folder, if not more Maybe like 30 to 40 directives So there’s a lot in there However, most of the time, I’m using Webstorm or IntelliJ, so I just jump straight to the file I want But if you’re not super familiar with the file names, or you’re browsing for something, it is like a lot of files to go through AUDIENCE: So how do you decide, do these things belong in the same module or in a different module? Is it service-driven, or is it controller-driven? JEREMY ELBOURN: It’s a lot of times, it’s whatever you feel is right and can convince your teammates is the best way to go But obviously things like a service are pretty easy Directives are pretty easy As far as controllers go, if you’re like building a song application, what goes in the song section? Well, do you put the list page in there and the properties page, or do you have a separate section for long list and song properties? It’s really at your discretion All right I think that’s all the questions we have for tonight, so thank you, and we’re going to take a brief break for everyone to mingle And then we’re going do lightning talks, so thank you [APPLAUSE]