Good afternoon.  I have the pleasure of introducing Jesse Beach. One of the overarching themes of the front-end track this year is pushing boundaries, going beyond Drupal and taking what is already a powerful tool and pushing it to become even more. So, naturally, I reached out to Jesse because he's one of the people who have been pushing Drupal. You saw Dries' keynote this morning. You saw the accessibility. Maybe you saw the toolbar. And this is the work Jesse has been working on and taking an already complex system and then pushing it. And yesterday, I was tweeting with her and she was at the sprints. And, naturally, she was in the hard problems sprint, cracking the problems that nobody else can. So, without any further ado, introduce you to Jesse Beach. So, how many people here are front-end developers? Fantastic. I am too. Excellent. I was hoping I could get a lot of people in the room. Front-end developers. So, the name of this talk is evolving front-end development, but it's a bit of a pun. Because front-end development is something that we are evolving in Drupal. We're making it better, but it's also something that evolves around us. And I'd like to refer to this field as dancing on the tip of a hurtling rocket. Because as front-end developers, we're in a field that changes what feels like almost daily. So, I absolutely love the web. This picture, to me, just expresses the feeling that I have almost every day when I get to sit down and write code. To invent things and to make content findable. But the front-end is also a place of mystery and, in fact, terror some days. I feel like I'm presented with problems very often that I don't know how to solve. That require me to dive into forums and lists. So, I wanted to kind of get a sense of how much information is out there that a front-end developer might possibly have to know for becoming an expert. So, I counted all of the specifications and the recommendations out there in the W3C that you might one day have to read or have to be familiar with.  And it ends up being a lot of documentation. I mean, just for JavaScript, there are over 80 things you might have to read and they're not exciting reading, to say the least. And as I was counting those numbers, I got this tweet from Kevin Suttle. Talking about display properties that I hadn't known about up to that point. And I just had this moment where I was like, and now there's something else I have to go and research. Like, I have no idea what indent edge reset is for display mode. And I felt like I understood CSS completely up to that point. I also put together a list of responsibilities that a front-end developer might have and went and counted all of the different libraries, the third-party libraries that you might have to someday evaluate or understand to know, like, should I go with Angular or Backbone? How are we going to do our behavior-driven development? You know, any type of responsibility that you have as front-end developer is probably already represented in some library. And there's probably 15 of them that do the thing that you need to do. And it just creates a lot of noise in the front-end development space to understand, you know, how do you choose the best path to get your job done? So I tweeted out this list and I asked for input from people that follow me. And Mark Drummond responded that of the list of things that I had put up as responsibilities for front-end developer, I forgot crying. And I had to agree with him. When you look at this list that has like 60 responsibilities, it feels completely overwhelming. So whereas some days, you know, I feel like this most days, there are definitely some days where I feel like this. Looking at, you know, how we as front-end developers complete the requirements that we have to do and how we do it in the best way possible that makes our users as successful as possible. So during this talk, I really want you at the end to feel good about what you already know as a front-end developer and to understand that there are areas that we all don't understand. Within this community, we're constantly learning from each other. In the group plate itself, we're trying to build in support structures and features that allow us to develop, you know, as quickly and to the best practices possible. So we have to talk about doubt. Doubt to me is something that I feel every day. And I like to express this because I think too often we get the sense that people that we aspire to or esteem know a lot more than we think they do. I certainly feel this. When I look at someone like Leveru, I get the sense that I just don't understand CSS given, you know, the types of things that she's doing in her research. So a really good example of, you know, this kind of fundamental moment of doubt that we experienced came during the development process of Drupal 8. So in 2011, Drupal kind of opened its arms wide to outside libraries. You know, we pulled in Symphony, we pulled in Guzzle a little bit later on, but we also pulled in some things in the front end. We pulled in two libraries. One was Create.js. Create.js is a library that essentially looks to the page, finds anything that's editable, makes that editable, takes those changes, saves them, and provides them through an API for you to push back to whatever, you know, system you have behind that to save that content. In our case it was Drupal. So this allowed us to very quickly, you know, short-circuit that piece of the puzzle that we were trying to solve for in-place editing by giving us something that understood the DOM, understood it semantically, and then gave us information about how users were editing those pieces. Create.js was also nicely coupled with a front-end editor that we wanted to put into core, Aloha. Aloha was being developed as an HTML5 standards first in-place editor, just like CK Editor, a tiny MCE. We had this crisis moment in late 2012 when we had been pushing forward with Aloha Editor. We knew there were some gaps in the functionality that they supported. One very striking gap was the fact that you couldn't use Aloha on the back end, on a back-end form to edit your content. And we kind of had the sense that we were going to have to solve that problem in the future. But then out of the darkness of their closets where they were developing, the CK Editor folks emerged with not only an in-place editor but an editor that could work on the back-end that had 10 years of development behind it and had excellent support for accessibility. They also came to us with about four developers in two weeks of their time to make an integration with Drupal. We reached this point where we had to make an incredibly painful decision to break the ties with Aloha, the relationships we had formed, and to also give up in about eight months of work that we had put in up to that point and essentially take a dive off a cliff and take a chance that we were going to make the right decision to switch editors essentially while the plane was in mid-air. So I want to take this point just to mention, and this is something that I think about as a front-end developer every day, that behind every line of code there's a fragile ego seeking affirmation, you know. We write code because I think we love it, and when someone else loves it as well, it's a good feeling. I know that someday as I'm not the best at being a positive force in development, specifically when people mess with my passwords, not making or allowing me to make my passwords as strong as I'd like them to be.  I step back and say, you know what?  All right, anyway, so back to Create. We pulled out a lo-ha, we replaced it with Seek Editor. The reason that we had Create in Core now was becoming less and less salient, and we were running into problems with the model that Create has for editing content in place.  We were trying to move to an entity-based editing model where you'd edit multiple fields in the front-end, get all those changes into a package, and then push that change back into what maps nicely to a revision on the backend in Drupal. The problem was that the model inside of Create was almost impossible to change, and I personally sat there for about 48 hours coming up to a weekend trying to decide if I just didn't understand it as well as I could. You know, was I not understanding this library, was I really not do what we needed it to do? So I spent a weekend looking at the possibility of running through this code, essentially bypassing Create and getting to the point where I could edit something on the front-end of Drupal and save it on the backend without Create doing anything, and I managed to do that. So with that very hacky prototype in place, we looked at some of the other factors that affected this decision, and being the commit history of Create up to the point in April where we were faced with this decision to pull it out and build our own code or to keep it, and we had to recognize that there just wasn't the activity in this project that we had hoped was going to be there, especially because there are other CMSs that were supposedly using this piece of code. So around April last year we made another decision to jump off a cliff, essentially invalidate 10 months of code that we had put into place at that point, rip it out and write our own. And this to me was probably the scariest decision I've ever taken as a developer, because we didn't know if this was going to work. We had no idea if we were going to, you know, bog ourselves down in custom code and then have to backtrack or, you know, waste time that we could spend developing other things, fixing our bad decision. And I've kind of come to this place with front-end development where the strike that I'm anticipating, the sting of that decision, I find is never as bad as I think it's going to be, because the time that you spend, you know, building out one approach to a solution is often the time you need to understand the problem. So for us, the 10 months that we spent integrating Create and Aloha Editor was time for us to really understand what in-place editing meant in Drupal. So when it came time for us to build our own version of Create, you know, it really only took about five weeks. And this comes down to this idea of confidence in front-end coding. So when I'm feeling a lack of confidence, let's say, I like to think about World of Warcraft. So do we have any World of Warcraft players in here? Any recovering? So I'm a level 55 hunter. I got out of Warcraft just out of grad school where my addiction started. And I remember something very specific about Warcraft when I'm feeling that I don't understand a problem. So when you're fighting a monster in Warcraft, you have the monster up in this little circle, and you have its power represented by a number. And the color of that number tells you your chances that you're going to be able to either defeat it or not. So yellow means that you've got a pretty good shot as long as you're clever. Red means that you're probably not going to survive, but lucky you might make it through. And if it's the skull, you just run. So for me, the skulls are anything to do with PHP and Drupal. When I see that, I just want to take off. But anything to do with JavaScript is kind of a yellow at this point. And what happens with the monsters in World of Warcraft is as you level, they become relatively easier to tackle.  When you get to 84 and 82 is boring. So I've read this in a blog post and I wish I could... I think it might have been Sarah May who said this. Wish I could remember. But she says that for expertise really comes down to the number of tricks that you develop over time. A seasoned developer just has more tricks that they can bring to bear in a problem. And one of those tricks, just to give you an example that I have, is jQuery underscore data. So this little method, which is extremely poorly documented, I think I've found it like looking through the jQuery object one day, allows you to pass in a DOM element into the first argument. And if you want, you can ask for the events. You can just pass in the element and get an object with the events key back. But it'll tell you on any particular DOM element in the page what events are associated with that DOM element. What this allows you to do is to say, well, I have an A tag that has a click event on it and it's messing up. I can go through and tunnel back to the function, right click on the function, get back to its declaration in the file and figure out what's causing the behavior that's, you know, the mystery. And before I knew about this, I would go from the other direction, you know, grepping the code base to find something that looked familiar to get back to the bad behavior. So this is a, you know, just a little trick that I've had over time. And the other bit about expertise that I've learned is that edge case awareness is something that you kind of develop intuitively. And to give you an example of that, I see a lot of new developers in Drupal who don't realize that this attached behaviors method is going to be called over and over and over again on a particular page load when an AJAX call is made. Any time that there's new DOM elements coming from the server side into the page that need to get re-initialized, this method gets called again. And it's the source of a lot of trouble because if you have code in there that gets declared, variables that get declared, they all happen, that all gets run again.  So I was trying to think of some tips for honing personal value, sort of personal value and expertise as a developer and I just put up the list of things that I'm working on right now. But I think they have a lot of value for developers as you're coming up and the one thing that I've really learned to value is writing tests. They're really painful. If you follow me on Twitter, you'll know the day that I'm writing tests because I am just a whiny, whiny son of a gun. But once you have them, they're amazing because you can make changes and not have to worry so much about what you're breaking. I'm currently reading a lot about performance in JavaScript just trying to understand how do you make a loop more performance. And the things that seem to be surfacing within the front-end worlds that I think will have value going forward are the basics. Like we're coming back to the basics after a decade of abstraction and libraries on top of those, like DOM methods, the query selector and query select all that find things on the page. What in the past would have been something that we would have worked with jQuery for are coming back because the browsers and the user agents we work in actually support them. And I had the opportunity last Tuesday to meet Brendan Eisch in Douglas Crockford at the TC39 meeting in Boston. They're talking about the ECMAScript 6 specification that should be coming up pretty soon. Sorry, it was a big moment for me. Brendan Eisch was the guy who invented JavaScript developed like 16 years ago. So my recommendation to you as if you're like sort of a novice front-end developer is really focus on the basics of ECMAScript 5 and 6. I know there's a lot of talk about the copy script and stuff like that, but knowing the basics allows you to understand those structures in those high-level languages in a way that allows you to become a better developer. And then although I love SAS, I can't say enough that when I have someone come up to me and say that, and this happened at a Drupal meetup in Boston the other day, she said, I kind of know CSS, but I really have to learn SAS. And I said to her, you don't really have to learn SAS. You really have to learn CSS. When you get good at that, SAS is going to be the thing that makes you a better developer. And then working with someone who's better than you is probably the best way to become a better developer. But I've also found, and there are many people here who will agree with this, that mentoring someone who isn't good yet is probably the best way to get better.  So if you don't know how something works, and I tell this to my JavaScript students all the time, you can't break a page. You can only break it for that one refresh. All right, so we've talked a bit about how to become a better developer. And I find that one of the shortcuts to becoming a better developer is to talk to people who already know what they're doing. But in our industry in particular, we seem to have a lot of what I call celebrity developers who gain a lot of the oxygen in the room. They really kind of steal the spotlight. And this becomes a problem because the problems that we focus on as a community tend to be the most rarefied and important, but somewhat, I don't want to say insignificant to downplay the problem, but they're very particular. So let me give you one example. We have 20 million high-density screen devices sold in 2011. This was by Apple, so we have high-density screens on laptops, iPhones and whatnot. In that same year, there are about 6.5 million Americans with visual impairments that lived in the United States, so either completely blind or somewhat visually impaired. I had this tweet come across my Twitter stream. If you're into front-end development, you probably follow Brad Frost. You probably hear about these responsive patterns days. So we have responsive patterns with Brad Frost sold out over the weekend. He agreed to add four more seats. Fantastic. How many of you can imagine a tweet like this? Accessible authoring tool patterns with awesome dev, sold out over the weekend. And then she agreed to add four more seats. Fantastic. I personally can't imagine having an accessibility event be as popular as we might imagine, responsive web design or some sort of semantic authoring tool. But the thing is, if we look at our user bases, we find that there are a lot more people than we might realize who are accessing content that we're trying to provide to them in ways that are not visual, that have nothing to do with responsive screens. So in 2012, the WebAIM survey surveyed 1782 visually impaired individuals and asked them, how do you access the internet? How do you access information? When they asked them about mobile devices, what they found is that 72% of those visually impaired people access the internet through a mobile device. Of that 72%, 58% access the internet through an iPhone. So that's, if you do the numbers, 6.5 million visually impaired people, 70%, 52%, you end up with like 2 million people in the United States potentially are using their iPhone with your slick and squishy responsive web design with absolutely no need for that slick squishiness. They're going right past it to the content through the screen. But what I don't see in our industry is the type of interest and enthusiasm about that kind of content access that we have for these sort of high profile things like CSS3 and animations, gradients and responsive web design. So Nathan Smith is a fantastic person to follow on Twitter. He expressed the sentiment that I was feeling as I was writing this presentation that, concepts of responsive web design and AJAX have come in and killed as a strong word. And you'll notice that Ethan Marquette gets a little incensed at the bottom there. Nathan apologized a little bit. But they've overshadowed, let's say, progressive enhancement, which really underlies responsive web design. I mean responsive web design is progressive enhancement for visual interfaces. So let's take an analogy to understand what progressive enhancement really means. A Drupal Gov days a couple months ago, Catherine McNally was talking about accessibility. And one of her examples was this idea of an elevator.  You have to be sure that your elevator, this slick, futuristic transportation method is 100% safe. It can't fall. It can't stop.  In contrast, if we look at something like an escalator, it does the same job, carries people from one level to another. But when it breaks, it becomes a flight of stairs. You can still get to the top of that conveyance without needing outside assistance. And I've been working on accessibility up to this point for a couple of months, but this analogy really struck home for me about what progressive enhancement is. It's starting with escalators, starting with stairs and building the escalators on top of them. It's making sure that the fundamental pieces of our interfaces are going to work when everything breaks down. So personally, as I think about the front-end development space, I'm trying to distill it down into the primary values. One of those is content. So to me, what we do as developers is provide content and we provide access to that content. That is essentially the value that we provide as professionals. There's information out there. We're making it possible for individuals out in the world to get to that content, no matter what means they have available. If they're sighted, they're not sighted. If they can only use their tactile sensory inputs. And I really have to remind myself all the time that the page is not the content. The page is one of the means that we use to present the content. So by training, before I got into development, I was a linguist. I focused on studying languages of the world, what we call topology, or comparative linguistics. And I wrote a grammar of verbs and noun declension in a now extinct Native American language. But the thing that struck me, I think as a freshman one day, was a professor who focused on child language acquisition. And her thesis was that we don't know of an upper limit for children and the acquisition of language. She was personally studying children acquiring four languages at once, English, French, American Sign Language, and Kipakwa Sign Language. And what she proved to us over the course of a semester was that the human capacity for language is not expressed or bound up in any of the medium or the media that we use to express it. So specifically, language is not speech. And we can see this in the way that a child learns how to babble and sign language. So that child wasn't saying anything with those hand movements. They were like, you know, ma, ma, ma, ba, ba, ba, as it's learning to articulate. This professor said to us that, you know, there's a common held misbelief that if you teach a child sign language, it's going to learn how to speak sooner, learn how to communicate sooner than it would if it were taught spoken language. But the reality is that the child is incapable of producing spoken language until about two months after it's capable of producing signed language. What you're doing by teaching that child sign language is you're accessing the capacity for speech or for language that exists there already, you know, at the age of eight or nine months. They're already capable of producing, you know, words and babbling. You can just get to that capacity faster through hands. So I'd like to take this analogy from my past life and bring it forward to the current. I understand that the content that we're providing to end users is like our capacity for language. It exists, and we as professionals are simply providing the means of getting to it. We're, you know, teaching our users to speak. We're teaching them to sign through the interfaces that we build. And I personally break the delivery of content down into four different areas. The first and most important to me is accessibility. And I don't define accessibility as simply non-visual interfaces. I lump visual interfaces in that category of accessibility. Because what we're doing is making content accessible to visual people. As a profession, we tend to think about our interfaces as visual things. We get caught up in responsive web design. We get caught up in high density scalable images. It's probably true that the major percentage of our user base is visual. But at the same time, we can't focus on that exclusively. It's like building, you know, an apple tree that only a 10-foot pack of Durham standing at a time length of the 4-foot trunk is able to access and saying that those are the users we're going to support. The rest of those people on the ground can figure it out for themselves. The other aspect of content is findability. And what this essentially comes down to is the URL. So if you remember back in 2010, when Twitter broke the Internet, they introduced the hashbang pattern into their URLs. And they turned what was a findable, locatable resource into a hidden resource. They took a tweet that you were able to, you know, address through a single URL. And turned it into something that had to be interpreted by a user agent in order to get that content. They broke the Internet. Yesterday, I had someone come up to me here and say, we have to build for Drupal 8 a completely separate content administration layer in backbone or Angular, what have you. And just rip out the theming layer. And I said, yes, I totally agree. And then I asked, but the one problem I have with that solution is what happens when you go to node one if we rip out the theming layer? How do we provide content to someone who is arriving at our website through a stable URL that perhaps hasn't gotten into our application yet that we built on top? And I think we always have to remember as front-end developers that it's the content that we're getting to the end user. All the goodness that we sprinkle on top cannot make that, you know, cannot undermine that basic tenant. So another piece of content is personalization. And this is something I think that's coming up more and more in Drupal development. I'm certainly getting pressure from people above me at Acquia to work on this. The problem with personalization is it conflicts with performance. So in Drupal 7 and into Drupal 8, we had this situation on node pages, especially lists of node pages, where you were told, you know, how many comments in a particular node you hadn't read yet. This is a really interesting piece of personalization, because when you're on a list of ten nodes, you can know immediately how many you have to drill into to see comments. The problem arises is this information is specific to you, how many things you've looked at already. And once we get into user-specific information on a page, we've got into user-specific cache, right? We can only cache this item and reuse it for you, personally. So Wim layers spent quite a bit of time over the past five months figuring out a way for us to provide this information to the end user in a way that doesn't make the page itself from the server unique, essentially, you know, providing the information on the client side. And then the other aspect of content delivery is speed. We have to get information to people as fast as possible, but we're also limited by the devices and the user agents that we're working with. So something that I think just came to my attention within the past couple of months is that a mobile device spends about 450 milliseconds before it's even gotten any information from the server, just establishing communication between your device and the server. So about 150 milliseconds to send out, 150 to get a response, 150 to say, I got your response, and then we get data. So as we're trying to make Drupal 8 faster, we're very aware that we have these very hard limits sitting just underneath us. If we make a page load in 20 milliseconds, it's still going to be 470 on your phone. OK. So with that incredibly long preamble, let's look at some of the things we're going to get in Drupal 8. Personally, the thing that I'm most excited about in Drupal 8 is REST built right into core. I've tried to install services module, maybe like 510s in my life, and I've never succeeded in getting it to work. REST for me works right out of the box most of the time. And sorry, I just like that picture a lot. When I think about HTTP methods, I think about throwing fish and how like if someone threw a fish at me, I'd be like 403, not accepting that. All right, so here's a bit of a video. I'm using Postman to do a post into my Drupal installation. We're going to create a node with some data. We've got a title and a couple other things you have to send to it. We get a response back, 201, this thing was created. Inside the headers that we get back, we're told the location of that new piece of content we just created, and we can go look at it. So we get that piece of content we just created through an HTTP method back as JSON. And if we look at an installation that had no content up to that point, we see that we now have a new node. So you can imagine what this means for your front end applications. You can very easily create content, update content, delete content. We're working at the moment on a backbone module that extends the backbone model for you and creates the syncing endpoints to update things like nodes and pages and articles. A layer that automatically understands the structure of that data that is coming back from Drupal and will allow you to simply extend the Drupal backbone module extension of the backbone model. There's a lot of very similar words. So we're getting backbone with Drupal. This was an incredibly contentious decision when we decided to go with backbone. It took months of back and forth to get this into core. But once we got it, we really took off and started using it heavily. I think there are many good examples inside of core right now of patterns that we're developing that take this idea of content, sort of capital C content, and expose it to the end user through whatever medium they're most comfortable with. Specifically, we've broken the interface into visual and oral components that are all driven from a common backbone model. So this model stores the state of the application, so the state of your toolbar or the state of your contextual edit links. And it expresses that state to the end user in whatever form they're most comfortable in, specifically with the oral. When we have something like the open or closed state of the trade change, we're able to express that out to a spoken user agent. At the same time, we express that state of the model out to the visual layer, so the screen, by opening or closing that drawer. And this leverages some bits we've gotten to core here, the Drupal announce bit. So again, we're thinking with backbone in a content first way and using it to enhance the experience. I know you've probably heard about twig templates a bazillion times so far, and it's only Tuesday, and you're only going to hear about them more. The only reason I really bring it up at this point is because I need to tell you about something we're not going to get later on. But for anyone who hasn't heard about them, because you've been under a rock perhaps for the past 12 hours, the twig templates on the server side are brought in from the symphony import, and they allow us to expose content to end users without using PHP, so you don't have things like database access in a twig template. And we also have a kind of a common syntax, this percentage syntax that a lot of other templating languages use. So if someone coming in from a different project using smarty templates, I think, uses the same thing, they're going to recognize this syntax and be able to use it really quickly. And then the fourth bit in Drupal 8 for front end developers that I'm completely excited about is something I'm personally naming the semantic application layer. So this comes from work we've been doing in the accessibility side. We're taking in this technology called accessible rich internet applications. It's acronymed as ARIA. And we're taking this capability that was meant to provide a way to express the semantics of an application to a screen reader. And we're using it to drive the semantics of the application for everybody. Essentially it's a way of describing the state of your application through a layer that is agnostic to the means of presentation. So if we look at a quick example, I've got a Drupal 8 page. And you're going to recognize ARIA in the role attribute. I think WordPress introduced this like four years ago in their standard template, and we put it in since. This is essentially telling a user agent that this piece of HTML is going to act as something else rather than the native semantics. It's become a bit redundant because we have things now like the nav element. We just got the main element. But it's not redundant for pieces of HTML that don't have native semantics yet, like content info or application toolbar group. So what we're doing on the semantic application layer is we're taking a concept like active, and we're encoding it instead in this ARIA pressed attribute. So when something is pressed, we switch the Boolean in this attribute from true to false and false to true. And the fact that it has a class active is just an artifact of the visual presentation layer. We're not using that class to drive any of the behavior. That class appears because of the state that we're representing farther down. And this is a really big mental change because in the past what we normally do is we create a class, we put it on the DOM, when we want to know what state that piece of DOM is in, we go get its classes and say, do you have an active class? Well, you do. You must be in an active state. Let me do a bunch of stuff here that responds to the fact that you're in active state. We're doing all that stuff, and at the end, we're throwing the class on. We also have ARIA to change, again, this role. An A tag that's acting as a button, we say, hey, user agent. This is not really an A tag, this is really a button. And when you have a spoken user agent go through the DOM, instead of saying link, it now says button. And with the ARIA pressed attribute, it says button active. I'm not sure if this is gonna be a thing yet, the semantic application layer, but if you all start using that word, I think we're gonna make it a thing. It's kind of like fetch. We're gonna make it a thing. Okay, so all the good stuff we're gonna get, there are big gaps in what we're going to get in Drupal 8 in terms of frontend support that are going to have to be filled in the contrib space. To me, the most important one is this idea of a big pipe. So if you're familiar with Facebook, they have this capability of taking all the requests for information that come from their page, bundling them up, sending them as one request back to their server, processing all those requests, bundling them back up again and sending them back to your clients where they get disassembled and then passed to the different pieces on the page that requested that information. For us, we're essentially making a single request per piece of information. Do you need to know if your comment, if you're no need to comment link? Do a request. Do you need the submenu items from your toolbar? Make a request. It's not that bad now. And we're taking steps for the requests that we know about to make them less aggressive. So we're only making them when something in the cache changes. But going into contrib, I have this fear that we're going to see our pages get really greedy for requests from the server. And I'd like to see us as a community focus on how we solve that problem. Some sort of common system where I can register the fact that I need data with a controller on the page and it takes care of fetching it and giving it back to me in an efficient way. All right, so the twig templates, is twig sharing, get it? We're not going to get sharing of twig templates from the server side to the client side, which means as a developer, as a module developer, you define what a node is supposed to look like. You provide that template and then you get to the client side and you have no idea what that definition is on the client side. It's a very tricky problem because in order to get that template from the server side, we have to run through the entire process of determining what template to get. Do you want the one from core or from a module or from your theme? And then we have to check access. We have to run all the alters and everything until we figure out what that template is and then give it to you. And then you're kind of still responsible for formatting the data correctly to pass into that template. It's a tricky problem and at the moment, we just don't have a solution. We're still using the old Drupal 7, Drupal.theme, create a string, pass it up to whatever your caller is. We also didn't get themagnostic layouts. That means that when you put a block in a region, that region is still associated with a theme. We don't yet have a construct that is theme independent where you can specify regions, responsibility, block placements and then share them across themes. I really see this as something that would have made composable front-end applications a lot easier if we were able to request large chunks of the page to slot in on our basic piece of content. And we're also not getting some sort of conditional asset loading. So this would be a library like require or YupNope that checks the feature capabilities of the user agent before loading the JavaScript or the code that's going to respond to that feature. At the moment, it's still Drupal 7. We statically define all of the code that you might possibly need. We run through the library dependencies and you get this big chunk on the front-end even if your user agent doesn't support any of the features that that code drives. We could vastly reduce the amount of information we're sending if we had a way of holding off on requesting assets until we knew what the user agent was doing really quickly when we run through this. So I wanted to end on another linguistic thing just to kind of get your minds warmed up for the rest of the conference. Metaphors to me are an incredibly powerful tool for anyone, for designers, for developers. They define the way that we understand a problem. So let's take a problem like time, a problem you didn't even know you had. When we think about time, we think about moving into the future, right? We move forward, the future's ahead of us, the passes behind us, we're constantly making progress, the drop never stops. So down in South America there's a group, a linguistic group of people called the Imara and for them they have a completely reversed model of time. For them, moving into the future is moving backwards.  This is encoded into their language directly. So when you ask them how was the movie they say, or when was something they'd say, well it was in front of me a couple of days. To them, the things that we can see are the things that we know. And when I first learned about this group of people, it completely floored me that something as fundamental as our concept of time is completely arbitrary, it's plastic, it's the outcome of our society and our language, the constructs that are built for us. And when I'm thinking about front end development, I like to come back to this example because it causes me and pushes me to question the fundamental assumptions we have about what we're building. I didn't arrive at accessibility because I wanted necessarily to make things accessible. I arrived there because I was starting to question the infallible and sort of omnipresent nature of these screens that we were working with. I was wondering, is there some other way that we, we're going to be delivering information in the future? And it just happened that accessibility is a model and a way of thinking about content that is going to prepare us for a future of auditory interfaces, you know, screens and devices that we talk to rather than interacting with our fingers. So just to sum up, big points, content. Content is the primary asset that we're working with as front-end developers. Access is the thing that we as professionals provide, be that visual or auditory. And we're building escalators, we're not building elevators. When you build something, ask yourself, when this breaks, what is it going to look like when it falls backwards? So just to sum up, if you're interested in backbone and learning more about backbone in Drupal 8, I recommend the talk right after this one in the North Hall by D Lancer. There's a buff where we're going to be talking about the backbone module in Drupal specifically happening on Wednesday at 3.45. And if you are interested in helping out with any of the front-end code, come to the sprints on Friday, and I will be there as well. There we go, thanks. I guess people ask questions at this point to have them. On your earlier sort of points that you made about having unique URLs, having web-accessible content and using backbone, say you were building a Drupal site that used Drupal as a back-end and backbone as a front-end, would that be something you'd just say never do or other ways that you could make that better, that you could do it differently? Because some cases, JavaScript web apps seem to work very well for certain things, but I definitely see your point that it's not necessarily the most accessible, the most web-friendly way of implementing it. Yeah, so it can be accessible. JavaScript doesn't mean inaccessible. 98.6%, 98.4% of people that access information through a spoken user agent have JavaScript enabled, and it's actually 0.2% more than the general population. So you have a better coverage in JavaScript with blind people. What makes it inaccessible is when you change things on the page without telling someone about it. So just changing a class on an element isn't going to be apparent to someone who doesn't see the color of that element change. So you have to be expressing these changes through this semantic application there that I'm talking about, so using ARIA. And then to address putting some sort of backbone front-end on top of Drupal, I love that idea. I would rather be doing front-end code in the browser than kind of half-composing it over in the server and sending half of it over to the browser. I think the thing we really need to solve is what is the layer just underneath there before the JavaScript runs? We wanna make sure that the constant items, all the nodes and the entities in the site have some sort of representation, which may be completely bare bones, maybe a header and some navigation links and that item, no sidebars, no related nonsense. Do all that in your client. But we need something there. So when Google comes by and crawls that site, it has to find some semantically significant piece of information. And I think Drupal is well-poised to be the system that kind of sits in that middle, produces semantic output, but just enough to get you to that point and then says go, go build your crazy interactive thing. Cool, thanks.  With the semantic markup of the area roles and that sort of thing, is there like a standard that we should be following? I know there is for the, it's usually targeted at screen readers and that sort of stuff, but I really like the idea of actually using it for just everything on the page and maybe having something like when you build a view in Drupal, usually you just have a little custom class that you can put in, but maybe having a role that you can put in there or for JavaScript events, for triggering, for telling something to the screen reader, is it something, because the HTML of five ones like the nav and the header and the footer, I just don't think they're enough and usually end up just running out of them and just doing section class this, section class that. And I think the area roles seem to be much better way of doing it. Is there like a standards move in to use those as semantics and ignore the rest of them? Yeah. There is a standard, if you Google Aria, you'll find it. The language isn't completely built out. Like I often run into a point where I can't find an attribute that describes well the thing I'm trying to do, so I try to do the best that I can with it. It's always evolving, but it's not an open set. You can't just invent Aria hyphen something and expect it to do anything. And even the user agents, like JAWS and voiceover and Chromebox, they're still developing support for it. And blind people are, people that use screen readers are still learning how to use this stuff. It's kind of new. But I think on a project like this, we should be pushing that sort of, the envelope of that technology because it is the adopted standard in the accessibility world. And it's something that we can co-opt in a really good way, like you were saying, to define the semantics. I don't think it's been explored completely yet, in terms of performance, in terms of just the edges of how you can cementically describe your application. But I think it has more promise than just using arbitrary classes. So I'm kind of committed to finding out what are the limits of it.


Family Theater presents Ralph Edwards and Victor Moore. Network in cooperation with Family Theater presents the payoff, starring Victor Moore. Ralph Edwards will be your host. Family Theater's only purpose is to bring to everyone's attention a practice that must become an important part of our lives if we're to win peace for ourselves, peace for our families and peace for the world. Family Theater urges you to pray, pray together as a family. And now to our transcribed drama, the payoff, starring Victor Moore as Mr. Mary B. An old man slowly makes his way through the busy downtown traffic of a large city. Finally, he stands before the big building housing the Courier Journal, and then slowly moves up the steps through the doors and across the crowded vestibule that adjoins the city rooms. Excuse me, sir, but I wonder if... Sorry. I beg your pardon. Ask for the reception desk. Yeah, everybody's so busy. Oh, the reception desk. Courier Journal, good morning. Oh, good morning. Mr. Johnson is nint just now. Oh, but I'm not looking for Mr. Johnson. Mr., can you just wait until I'm off the line? I can't hear two people at once. Oh, excuse me, you're on the phone. I thought you were talking to me. My eyesight isn't as good as it. Now, can I help you, sir? Yeah, well, my name is... Yes, yes, you can. You see, my name is Mary B. Well, who do you want to see, Mr. Mary B? Well, you used to have a lady named Ms. Wilson, and she wrote stories for your newspaper. She wrote one about me and my birds once. Would that be Ms. Amy Wilson? Yes, yes, that's right. She wrote a story about my birds. All about how I... You have an appointment with her? Well, not exactly, no. It's about the birds. I thought she could help me. I don't know what to do. I don't want to go to the police. Hold on a minute. I'll see if she's in. Well, thank you, thank you. I think she'll remember me. I don't like to bother her, but... Ms. Wilson, there's a gentleman to see you, a Mr. Mary B. Maybe if you mention the birds. Yes, yes, yes. That's the one. Fine, okay. I don't mind waiting. I could come back later. No, she'll see you now. Oh, that's very kind of her. If you want, you can leave that package here at the desk. No, no, I want Ms. Wilson to see it. Okay. It's the evidence. Mr. Mary B. Mr. Mary B. Is someone calling? Over in the archway, it's Ms. Wilson.  Mr. Mary B, how are you? Ms. Wilson, fine, fine. I didn't see you. Come on, we'll go into my office. Thanks, Margie. You bet. It's very, very nice of you to let me drop in like this. Nonsense, it's a pleasure. Here, right in here. Oh. Sit down. Thank you. Well, how are the birds, Mr. Mary B? Still feeding them in the park? Oh, yes, yes, they wait for me every afternoon. Even when it's raining sometimes. Wonderful. It's about the birds, the ones in the park that I came to see if you could help me. Well, I will if I can. Oh, here, let me take your package. I'll put it over. No, no, please, I'd like to hold it. Of course. It's about this package, too. I guess it started last spring, right after you wrote that story about me and your paper, about how I was always in the park feeding the birds. What started? These letters here. I have a few of them with me. I thought it was a joke, the first one. Oh, let me see them. Say, Amy, have you got the proofs on the... Oh, beg your pardon. Come in, Stan, it's all right. Mr. Mary B, Mr. Harris, one of our photographers. Well, I didn't know you. How do you do, Mr. Harris? Mr. Mary B, how many of these notes have you gotten all told? Oh, almost 30, I guess, Ms. Wilson, about one every week since I started. Well, look at this, Stan.  Well, I don't get it. Two dead birds like what? Like I have here in this package, a dead sparrow. There's a little pellet from an air gun I found right under his wing. It must have killed him. Well, that's a shame.  Have you been answering these notes? Well, yes, I didn't know what else to do. Then you've been paying out money? Yes, I didn't know what else to do. It was just a little at first. Oh, this is awful.  I know they're just birds, but I didn't want to see them kill.  I think it's a boy in my neighborhood, a young boy, but I don't know his name. You've seen him? Not close up. I wouldn't recognize him, but he had an air rifle. How much money have you paid him? Oh, five or $10, whatever he asks. For each note? Yeah, almost each one. When I haven't left him money, I didn't have it. Then he kills a bird, like this time. I didn't know what to do. I have lots of birds of my own right here in my house. Remember Miss Wilson, how they used to fly all around the second floor in and out of the window? I remember. I don't cage them up, they fly all around. I started with them when my wife first got sick, Mr. Harris, so she'd have company. Sure. And then after she was gone, I kept them for company. That's how it started. Now they're all I have. How much have you paid this boy, all told? Oh, I'd say about $250. Good grief. Oh, Mr. Merribee, you shouldn't have done that. Well, I didn't want him to kill the birds. Why didn't you go to the police? No, no, I didn't want to do that either. But this is blackmail, Mr. Merribee. This boy's a criminal. Yes, but I don't want to hurt him or make any trouble. I just want him to stop. You're on a pension, aren't you? Well, I had some savings. Now they're gone. Yeah, that's why I came down here today, Ms. Wilson. Not for money, but to see if you couldn't help get the boy to start. And that's the square where you feed the birds now? Yes, I used to go to the Lincoln Park, but it's pretty far these days. Left on Winchester Street? Yes, next corner. I'm the third house on the left, the brown one. Mr. Merribee, you keep saying you don't want this reported to the police, but... No, please, please. I don't want to ruin the boy's life. If you ask me, he's doing a pretty good job of that himself. Well, you can't tell why people do things like that. Maybe he's, I don't know, sick, perhaps. Do you know most of the boys in the neighborhood? Quite a few of them, the teenagers. Then he might be any one of a number. That's possible. Well, here we are. Well, I'm very grateful for the ride home, Mr. Harris. Not at all. I was wondering if you'd mind showing us that place in the vacant lot where you've been leaving the money farm at night. I'll be glad to. It's just down the alley here. Mr. Merribee, there's one thing that puzzles me. Yes? The dead birds that this boy leaves when you miss a payment. Where does he leave them? Well, in the vacant lot there. There's a whole dug there, just a small one, where I put the money in a coffee can for him. When I don't leave any, he puts a dead bird in the hole. Brother. That's the lot over there with all the weeds. The hole in the coffee can is near the middle. Hi there, Mr. Merribee. Oh, hello. Who's the kid coming down the alley on the bicycle? Well, I think it's... No, he looks familiar. Here's your paper, Mr. Merribee. Oh, Tommy, thank you. I thought I'd recognize your voice. This Wilson, this is Tommy Barton. He works for the Correa Journal too. He's a delivery boy. Well, how do you do, Tommy? Hi. And this is Mr. Harris. He's a photographer. Glad to know you, Tom. How do you do? Same, Miss Wilson. You probably don't remember me, but I was one of the 20 news boys you gave the bicycles to at the contest dinner last April. That's where it was. I knew I'd seen you. Yeah, and this is some bike, too. Thanks. Oh, don't thank me. You won it. You live around here, Tommy? Over on Greenwood, a couple blocks down. 1758. Well, I'm real glad to have met you, Mr. Harris. Miss Wilson again. I'll remember you next time, Tommy. OK. Oh, by the way, Mr. Merribee, this is collection day, buck and a quarter. You told me to remind you. Oh, Tommy, I forgot all about it. All I've got is my pension check, and I don't suppose you could cash that. Could you? It's $85. Are you kidding? I can't even count that high. Well, I'm sorry. Well, I'll drop around tomorrow. Don't worry about it. Well, it's a long, folks. Gotta keep hustling. Yeah, I'll be sure to have the money then, Tommy. OK, Mr. Merribee. Bye. Goodbye, Tommy. Bye, Tom, fella.  Yeah, he seems to be. Well, we'll drop around some other time, Mr. Merribee. Maybe we can get a line on who this kid might be. I'll appreciate anything you can do. I'll pay him much more tonight. Oh, Mr. Merribee, don't please. It isn't going to stop him. Oh, I know it won't really stop him, but at least he won't kill any more birds for a little while anyway. But you can't afford it. Oh, yeah, I said I don't need much, really. He's killed one bird this week already. Amy, I think I understand how Mr. Merribee feels. Oh, but Stan. Let him handle this his way, until we have something definite. Well, if you both feel that way, I guess they're... He only wants $5 this time. I'd rather give it to him, Ms. Wilson. Can we drop you anywhere to cash your pension check? Oh, no. Thank you. I always go around the corner of the grocery store. I buy everything there, and it must be almost six. They'll close then. I'd rather hurry. OK, Mr. Merribee. We'll be around later. All right. Thank you. Thank you both. You bet. Bye, Mr. Merribee. Bye. Bye, Ms. Wilson. Mr. Harris. Bye. He's quite a guy, huh? Yes. And you too, Mr. Harris.  He can't afford it. I don't think you'll have to. What was the address for that newsboy Tommy said he lived? Oh, um, Greenwood, um, Greenwood. You called yourself a reporter. 1-7-5-8, come on. You can still back out if you want to, Tom. Oh, I'd like to be in on it, Mr. Harris. I know most of the guys in the neighborhood. I'd like to recognize them. Still no ideas, though, on who he might be? No, I've been thinking that, well, far as an air rifle goes, I know five or six guys who own an air rifle. I got one myself.  Couple of times when I first got it. Now I'm glad I missed them. It's almost midnight, Amy.  I figured on more light in the alley, but that one pole there, that's the whole works. Oh, what's the difference? Mr. Merribee's got to come that way when he brings the money. Yeah, but the boy doesn't have to. Shh, listen, someone's coming up the alley. Keep down, keep down. If you can see anything, yell. Oh, it's Mr. Merribee. Look, he's carrying something. Looks like a coffee can. Look, he's putting something into it. It must be the five. Wait. Who's that? Who's out there? Light, somebody shot it. Stan, Tommy. There he is, running down the alley. I see him, come on. The kid ran into this house. Was he carrying an air rifle? Yeah, let's see what gives. The place looks like a rat's nest. That makes sense. Who's there? We're newspaper people, ma'am. We'd like to talk to your son. I don't have a son. You mean Eddie? Yeah, Eddie. We'd like to see him. He's my nephew. It's a funny time to come call him one o'clock in the morning. We won't keep him long. I don't even know if he's in. I'm gonna do what I tell him out till all hours. He's in? Will you call him? He in some kind of trouble again? No, we just want to talk to him. He's always in some kind of trouble. Eddie, some people here to see you. They know you're in. Did you buy him that air rifle, ma'am? Air rifle. I'm not buying him any air rifles. If he were my sister's boy, I wouldn't even have him here. You want to see me, Aunt Ruby? No, these people do. What kind of a jam you in now? I'm not in any jam. Hi. Hello, Eddie. You know these people? Yeah, I know them. Well, why don't you two say so? All this pity pattern around. I'm going back to bed. Now, don't mess up the living room. You followed me, huh? We followed you. Yeah. I heard you tell Aunt Ruby you were on the newspaper. Why did you do it, Eddie? I... I read about the old guy in the newspapers. That's what made me think of it. I don't know. Aunt Ruby never has any money. For money? I guess so. Then I got afraid to spend it. I still got it, $250. Except what I paid for the gun. Do you like killing birds? I didn't care. They weren't my birds. They weren't anybody's.  You feel kind of sorry for sparrows, though. They're so little. Nobody seems to care about them, except the old guy. I never have any money, even for a show. I sent them a couple of birds I just found dead. I didn't shoot them at all at first. Eddie, have you ever met Mr. Merribee? No. But I've got all the money. You can give it back to him after you tell the cops, except for what I spent on the gun. He could sell the gun secondhand, I guess, and get something. You live alone here with your aunt? Uh-huh. She's a waitress over at Demex. Knights. She never has any money. Eddie, we'd like to show you something if you'll come along with us. You don't have to give me that. I've been to the station before for hawking bikes and everything. I don't think the station's what Miss Wilson has in mind, Eddie. Come on, let's take a ride. Don't forget now, Tommy, you and Eddie are friends. Whatever you're saying, Miss Wilson. Well, hello. Good morning, Mr. Merribee. Well, come in. Come in. We know it's late. Oh, I'm glad to see you. You know Tom Barton, Mr. Merribee. Of course. Hi. And this is a friend of his, Eddie Randall. Glad to know you, Eddie. Eddie was there tonight when we ran by you in the alley while chasing that kid with the air gun. That really had me flabbergasted. I didn't know you were there. Did you catch him? Well, uh, not exactly. But we know where he is, thanks to Tom and Eddie. We were wondering, Mr. Merribee, if you'd mind showing us your birds. Oh, I'd be happy to. I used to keep them up on the second floor. But my legs got kind of wobbly. So, well, they're all down here now in this room. There's a lot of them, Eddie. But they're a good company. Ever see this many birds in your life, Eddie? Why, no. No, I was singing. This powder pigeon is... Hello, Mr. Churchill. He's Mr. Churchill, like the English Prime Minister. Oh, yeah. You know all he needs is a cigar. He'd be all set. Yes. These are my hospital cases in these cages. This little fellow, the sparrow broke his leg. You see the splint? Gee, it's no better than a toothpick. Why do you ever get him to lie still while you put a thing like that on their leg? They seem to know you're trying to help them and they lie still. You ought to open a bird hospital. You could get rich. Oh, I thought about it, a bird hospital. But it'd be a lot of work. Well, it wouldn't be so much work if you had someone to help you. Would it, Mr. Marabee? Well, no. Not if it was someone young and strong. But I needed a little capital, money for cages and a sign out in front. Well, that doesn't sound like it would cost much. Oh, it wouldn't, Mr. Harris. They turned this place into a regular pet shop. I could stock up on some more parakeets and maybe carnaries, too.  Well, how do you mean, Eddie? I mean, who'd take care of them? Even if you had someone to help, they couldn't learn that, could they? How to take care of the ones that were sick? Oh, sure, they could. Just have to be gentle with them and let them know you love them a little. And that, they're find alone and forgotten, that's all. Gee, they're all such little fellas.  Well, yeah, but I... Would you like to go into the bird business, Eddie? Like this? Sure. You couldn't dog around on it. It's a lot of work. Sure, sure, but I like to work. When there's some fun in it. Well, you may even have to stay here, Eddie. Would you mind that? Well, no, no, I'd like to. Sometimes at night, the birds get upset and frightened. Why? I'd be good to them, Mr. Mary B. No kidding. So they'd know they weren't alone. Or think nobody loved them. Are you sure you don't mind putting your money in this, Eddie? Oh, no, Miss Wilson, I... I want to. Well, Eddie, that's wonderful. Knock them over here. I want you to get acquainted with your new family. You met Mr. Churchill, but... Well, here's a sick bird I found on the street the other day. He's still a little mean and suspicious and he picks at you. But I think he'll come around eventually. I've got him so he don't pick at me anymore. Oh, here is your host, Ralph Edwards. I have the good fortune to appear on a television program called This Is Your Life. Now, basically, it's a surprise package. We bring an unsuspecting person up before the TV cameras and much to their amazement, review their entire life, introducing them to friends they haven't seen for years, and reminding them of places and incidents they may have completely forgotten. As you can imagine, it's very affecting and in a way pretty instructive to see how people react to the knowledge that the story being related to them is their life. And I've often thought, how much good it might do us all if just for a short half hour we could have the experience of seeing our life as it looks to others, especially as it looks to the one all-knowing observer who gave us that life. For it's really God we're hearing when the voice of our conscience says, this is your life. Are you leading it well? Unfortunately, we can answer God through prayer. We can get down on our knees and speak to him whenever we're worried or ashamed, just as when we're happy and grateful, and he'll always hear us.  I have given it to you, and I'll help you guide it along the right path if you will but ask me for that help. Something else too, folks. The family that prays together stays together.  From Hollywood, Family Theatre has brought you the payoff starring Victor Moore. Ralph Edwards was your host. Others in our cast were Gene Bates, Ruth Parrott, Barney Phillips, Sam Edwards, and Jeffrey Silver. The script was written by Roderick Peterson with music composed and conducted by Harry Zimmerman and was directed and transcribed for Family Theatre by Luex Lansworth. This series of Family Theatre broadcasts is made possible by the thousands of you who feel the need for this type of program, by the mutual network which has responded to this need, and by the hundreds of stars of stage, screen, and radio who give so unselfishly of their time and talent to appear on our Family Theatre stage.  This is Tony LaFranco expressing the wish of Family Theatre that the blessing of God may be upon you and your home and inviting you to be with us next week when Family Theatre will present Journey of the Pegasus, starring Ray Burr. Bob Hope will be your host. Join us, won't you? Now an interlude with the music of Jerome Kern. Two melodies from the musical production Music in the Air.  Now another familiar one from Sonny, who? From Hollywood, this has been a brief interlude with the music of Jerome Kern. This program was transcribed. This is the world's largest network, the Mutual Broadcasting System.


This study examined changes in vegetation activity over the past three decades using satellite data. It was found that global vegetation has been increasing at a rate of 0.46 times 10 to the power of negative 3 per year since 1982. However, this increase was not consistent across all regions, some areas experienced a decrease in vegetation while others remained relatively stable. The authors attributed these differences to both natural and anthropogenic factors such as temperature and precipitation levels, as well as human activity. They found that human activity had a greater influence on the amount of vegetation in certain regions, particularly in Asia, Africa and Europe. These findings suggest that human activity may be contributing to the acceleration of vegetation growth in some parts of the world. This article was authored by Yalu, Yenli, Shuanchingli and others.


Thank you. Good morning. It's so nice to see all of you. This is literally my favorite thing to do is to stand in front of a bunch of brilliant, talented, beautiful Rubyists and talk to you about programming. This is my happy place. I'm also really, really excited to be sharing this stage with amazing speakers. I feel like this lineup is kind of ridiculously good and ridiculously intimidating. It's kind of awesome. Also, I'm super psyched to notice that 33% of our speakers are thought about employees, which I think is kind of cool. And if I can just recruit one more before the end of the day, that's 50%. So, Linda, I mean, think about it, Sandy, you know, Tom, anybody, talk to me at the break. So, I, like Linda, am a higher education dropout and mediocre programmer. But I'm trying to get better. I'm trying to become a better programmer. And one of the ways I'm doing that is to focus on the fundamentals. So, this talk is going to be a live coding talk. We're going to write some code here.  But the point of all this is actually not for me to reach the end.  The point is interaction. Imagine that we are all pairing. I'm driving. And you are navigating. So, please talk. Please give feedback. Please ask questions. I want to hear from you. My bar for success of a talk is how much back and forth we have. I want to have conversations. I want to stop and talk about things and delve into little side things. I love that. It's my favorite thing. So, let's do that. Let's get started. Let's look at some code. This is, by the way, live coding in the bath. Can I have a monitor? There it is. Excellent. Reason Vim, by the way, obviously, right? Any Vim fans in the audience? Yes. Excellent. Any E-max fans in the audience? Wow. Okay. I kind of like E-max too. It's nice. Okay. So, please read this code. I can bump the font just a little bit. So, here's something I realized. It looks like when I run my tests. At this font size, it actually works. But if I bump up the font even more, it doesn't work. So, I'll prove it to you. So, here's a fail. And when my tests fail, it looks like this. You can see at the bottom, there's the failure. And here's what happened. Let's do that again. I'll get rid of the fail. When they do work, that goes away. But I'm going to add the fail back in there. And I'm going to bump my font one more time and see what happens. So, unfortunately, this is the max font size right here. I'm really sorry. This is kind of one of those things I don't know how I could have anticipated this exactly. So, please bear with me. My apologies for any hardness to read. But, please squint and read this code. I'm going to scroll down for you two once you get the gist of that. So, just a quick overview. This is a class that sends invitations. It takes a CSV of people who want to invite somewhere and a message that we want to send each of them. For each of the recipients, which we'll get to, we create a mailer. We send a mail to their name and their email. We include the message and then we deliver it. And the way we get the recipients is by parsing the CSV that comes in and turning it into a hash. So, how do we feel about this code? Any comments? Initial impressions? What's that? What's that? Ouch! Is that your response? Often code I wrote makes people say, ouch, yeah. What's ouchy about it? Yeah, so one feedback goes, what if parsing the recipients fails? And I'm sort of in the middle of delivering, so I'll send like 50 emails and then I'll hit a parse error. And then like, what happened to the rest? Well, who knows, you know, air break exceptions. Not sure. Yeah, that's good feedback. That's good. So, this is a man who sent a lot of email, I imagine, probably through background jobs with retriable jobs, I hope. Other thoughts on this code? Yeah. You're about 25 minutes ahead of exactly where we are, so nice job. His feedback was, he expected CSV to be an injected dependency and he thought it was weird to be sending in a CSV full of names and then parsing it in there. Is that a fair summary? That is exactly what I was hoping you would say. So, to me, this is not ridiculous code to me. This is code that I actually probably would write as a first pass. So, my general approach to solving any problem is to first make it work, make the test pass, and then make it beautiful later. So, I would look at this and say, okay, we've taken a CSV full of unparsed data, we parse it, and then we send email for each of those things. And that sounds like very much like we have multiple jobs in this class, right? There's multiple responsibilities here. And we all know that we want to follow something called SRP, single responsibility principle. We shouldn't say we all know. You might consider following SRP. It sometimes can make your code better if your classes have a very focused job. And so often, I will find myself in this position where I'll muddy up a class with another responsibility, and I'll say, okay, now it's time to extract it. So, let's extract this code. And we're going to do the extract class we're acting right now. We're going to do it sort of slowly, and I'm going to try to do it as cleanly as possible. And this is how I try to do it day to day. Again, we're focusing on the fundamentals. It's going to get a little more complicated soon, but we're going to start with some simple stuff. So what's the first step in the extract class we're factoring? Anybody? Name the class that's reasonable. Yeah. The parsing of the recipients. What does that mean for a first step? Okay, so there's an instance variable for the recipients instead. Yeah. So for me, the thing I like to think about for my first step is I like to sort of write the code I wish I had. This is kind of a classic TDD trick, and we are going to be TDDing this. By the way, I have tests. This is what it looks like when the tests run and they pass, all the thing pops up and it goes away. If they pass, you don't need to see anything, right? That's just no information needed other than success. When they fail, that little box down there will stay with the error message. And by the way, notice that it takes me two key strokes and basically no time to run my tests. And that's important.  You're kind of doing TDD, but not really. People that tend to do that will abandon TDD and say it's too slow. And it's like, well, TDD isn't too slow. What you were doing is too slow. So running tests should be, do not leave the error activity. It should be in the error activity. So let's start writing what code we wish we had. I wish we had a parser. Whenever I have to parse something and something else, I always want parsing to be on its own. There's one of those great tasks you can just always pretty much draw a box around it and say parsing happens over here. Great job for a single isolated class. So I wish we had a parser. What do we do now? Run the tests. Correct answer. What happens? On a new slide is constant parser. That's pretty fair.  So let's make a parser. Is the next task, is the next thing we do, do we make a parser? What's that? Just the class. I'm going to go even one step a little bit more. I'm going to move an even smaller step. I'm going to make the spec first. I know I'm going to have a parser. I want targeted specs for the parser. So the next thing I'm going to do is make some specs. Spec, parser, spec. I'm going to run this again. I get the same failure. This is actually great. Because I'm extracting a class from an existing class, the unit tests for the invitations class are now basically an integration test. The integration test, this invitation class and the new parser class I'm creating. And so when I start to create a, when I'm writing code in general, I start from an integration test. I let that fail and then I start writing a unit test and watch and make those past. And we're going to jump back and forth between the tests for these different files and take turns and make sure that the message in them stays similar. So we have a test for our parser. We get this uninitialized constant parser. I'm going to vertically split this. We'll see how that works. We don't have a ton of resolution to play with. But here's our parser. This is how I work most of the time in like 640 by 480. It's pretty awesome. Okay. That right there, that was that test passing. See how it went away out of our face? That means, okay, now there's in fact a constant called parser. And we found it. So now let's go back to here and rerun the test for invitation spec, for the invitations. So I run the invitation spec and those passed. Those happened to stick around. Okay. So now we're green again. So again, next step, write the code we wish we had. Now that we have this parser, it doesn't do a lot, but we have it. I wish in recipients I could just ask the parser to handle the recipients like that. So let's run our spec again and see what we get. No method error. Undefined method recipients for parser. I should give you a second to read these errors. I've done this talk a couple of times. I might be able to read them faster than you. No method error. Undefined method recipients on parser. That's reasonable. It's a brand new class. It has not that many methods. Except what Ruby gives us and certainly does not have a recipients method. So now we need to drive out the behavior of the recipients method on our new parser class. So at this point, we basically are moving, we're in the middle of extract class as a refactoring. But we're actually going to now descend one level of abstraction. Or I guess, yeah, sort of. We're going to push one level down the stack into the refactoring of move method. We basically want to move the contents of this recipients method into the parser class. So I actually kind of have a test for this already. So here's the tricky thing. There's a difference between move method when you move a public method and when you move a private method. You okay? Cool. And because we're moving a private method, we actually only have tests that sort of indirectly test that behavior. So I write direct tests for all my public methods on my classes. But for my private methods, I do not test them directly. I let them get tested implicitly as part of testing the public methods. Are you okay with that? Yeah. Sandy says yes. Yes. It's nerve wracking. Sandy is sitting right there. I know if I mess up, she didn't come yell at me. She's an aggressive person. You don't know that better. Like physically, like, she'll hurt you. You test a private method directly. Sandy will seriously like, I've had it happen. Okay. Just kidding. She's super nice. She's the nicest. Ridiculously nice. Okay. So we are going to, so here's what I'm going to do. I'm going to do every programmer's favorite thing and we're going to copy and paste. It's going to be great. So I'm going to use the tests for the deliver method and invitations. This one right here, which is only public method to drive out the behavior of this private method that we're pulling out into our new parser class. So let's go look at the tests. This, by the way, are the tests for invitations. This should be, oops. This is actually deliver. That's embarrassing. Cool. So it sends emails to all the inviities. We first stuff out the mailer. We'll come back to that. I make a CSV. By the way, this little dot strip here doc thing, I stole this from ActiveSupport. It's super handy. Have you ever had a here doc and you have to jam it all the way over to the left and it looks totally goofy? You familiar with this idea? If you're not, look up here docs. And then once you look up here docs, look up strip here doc and you'll have an awesome pair of wonderful power. Okay. So we grab a CSV. We throw that CSV into the invitations class with a string and then we expect the mailer to receive two method calls for invitation for each user in our CSV. So again, now that we're extracting a parser, it's kind of become a like a component test. It's become a test that tests multiple classes at once. And so I'm going to copy over this test and I'm going to fiddle with it so that we have something that works for the tests are our recipients method directly. So let's grab this. I use visual mode, which is a total smell and you shouldn't do it, but I did it because my screen is too small. Let's print this. Yeah, there we go. The mailer is here too. Juniel, vim master extraordinaire.  All right. So let's change this around. We're not going to stop the mailer. It doesn't happen anymore. We still have this CSV string. I still want to do that. But now we're not going to check if messages get sent. We're in fact going to check the result.  And then I'm going to expect this result to equal an array of hashes. So let's say that's going to look like name. And that goes to user one and your email. I have to use string keys here. You'll see why in a moment. One at example. Okay. So that's our first hash. There should be two. This should be to user two. That should be to user two. Let's lose that. And if all has gone well, which probably hasn't, we should get an error and not a syntax error. Ha, just kidding. We need to close the equals and whatnot. Good. Believe it or not, that's what we want. Okay. Run over arguments. So just a recap. So I'm calling, I have a CSV, a string that represents a CSV and CSV pretty simply has an email and name in it. This email and name and that email and name. We ask the parser to parse it given that string. And we expect the result to be an array of hashes with name to name and email to email. And we have a failure. So just a quick recap. We had an integration type test. We pulled it in here. We modified it. So we're testing this method more directly now. Let's now fix this argument error. We have a wrong number of arguments, one for zero. Anybody know how to fix that? Yeah. Confidence. Someone's like, yep. I got it. How do we fix it? What do we do? He's like, oh, I have to actually answer the question. What's that? We need an initializer. Absolutely. So this class needs to take a, whoops. I have a snipper for this. It's my favorite thing. CSV. What? Hold on, Vim. Get it together. There we go. We'll come back there. I will turn this talk around. Okay. We're going to rerun our test.  I'm going to be harping on these fundamental little things, by the way. All I did was have that, I had an error which said, hey, I'm calling initialize with one thing and you don't accept that. And so all I did was say, okay, initialize takes that one thing. And then I just throw that result on the floor and move on with my life. Because all I want to do is get that message to change. That's it. I want that message I got from my test to be a new message, to give me something to tell me the next thing to do. So I'm intentionally moving in very small pieces, very small steps. Next, unify method recipients for parser. Okay, no problem. I don't want to make that work. Actually, let's do it this way. So now I could go right this recipients method, but what I'm actually going to do is I'm going to steal the recipients method from parser or from invitations. But I'm going to comment it out. Because the test just told me there is not a method called recipients right now. And so I'm just going to make a method called recipients and then let the test tell me what it actually needs to do. And here we have our first actual test failure as opposed to test error. We expected the result to be an array of hashes that look like the array of hashes I typed up there. But we got nil because the method has no body. So we had to comment this. We ran our test and it blows up. Can anybody know why that blew up? This is not a great error. Can you figure it out? It's admittedly a little bit confusing. Just shout it out. Exactly. Yeah, we're calling. See, we have at CSV in here. And because we made that small step up here, we didn't actually assign it. But if we do that, hey, green. Excellent. So we have just extracted. We're working on extract class. As part of extract class, we did move method. We're making some good progress. Now let's see. Let's come back to this is parser spec. We're good. Invitations. We're good. Now I want to come back to the invitation spec. But first questions, comments, concerns. How are you feeling? How's your mental state right now? As my pair, I need to know how you are. Yes. We have a woo. Yes, sir. We're still not using the parser. Totally right. We should come back and use the parser. I think that should do the next thing. Other comments, concerns, thoughts. Yeah. Great question. Would I inject a double instead of using the actual class or object? And we were going to do exactly that in just a moment. That's a great question. Perfect question. Awesome. So let's actually use our parser. Crazy idea. Let's use the Kobe row. So let's get rid of this. And let's run the invitation spec, which is over here. And it blows up. And we know why. Or I know why. Because of that. Great. And now we're green again. We're using our parser. We've extracted it. Hopefully your mental state is now great because we are now actually delegating to the parser correctly. Here's your test. Here's the parser. Things are going well. This is good. So let's go. There's a quick change we can make to invitations, which is this. We don't need to store off CSV anymore, right? Because we pass it right into the parser. And that's actually a little bit weird. Let's go look at our tests now for invitations. We'll lose the parser for a moment. Come back to here. Invitation spec. You know what I just had the impulse to do that was really strong? Anybody know? Commit. You know? It's like, if things go all bad, okay. So no matter how much trouble we get into, we know we can get back to there. Tests are green. We're feeling pretty good. So let's make sure. Yep, green. Everything's green. Okay. So if we get in a lot of trouble, we know we can rescue. I do that when I'm working by the way. WIP commits work in progress. WIP are underrated. They can save you. Okay. So let's look at our tests right now and see how they make us feel emotionally. I think the tests are a little smelly. So right now, this is still basically an integration test. I think component test is maybe the better word. Component test meaning testing multiple components simultaneously. I'm pretty sure that's the right terminology. I might refer to them as integration test again. But we are testing the parser through the invitations now. And we already have unit tests for the parser. So what I'd actually like to do now is isolate the invitations from the parser. Because right now they're very much, they're joined together as we test them. And I like to have the invitations tested independently of its collaborators. Now we're already doing this with this stub mailer business up here. So here we're creating a double mailer. And we're allowing it to receive invitation and return this double. So we've already isolated the invitation from mailer. And that lets us do expectations like this or assertions like you must have received this message. And I want to have a similar situation for parser. So let's start out by extracting a stub parser method from our tests. And some people I think don't actually realize that you can extract methods from our specs. I do it all the time. This is my default first refactoring that I go to to clean up duplication and whatnot. So let's call a stub parser method. And into it we will yank this. Let's grab these five lines and throw them here. And what do we need to do? We need to isolate invitations from the parser. So we need to create a parser double. So here's our CSV. We have a parser. This is going to be a fake parser that we'll stand in for our real parser. We are going to say, hey, parser, when someone asks you for your recipients, we're actually just going to give a canned response of recipients. So actually we're going to change this. We're going to steal from the parser spec. Oops. Let's steal our beautiful array of hashes. Don't worry about that styling. Cool. Recipients equals an array of hashes. That's some nice indentation. Good job. Good job, Vim. That's the automatic indentation that Vim has chosen. Close enough. So for now. This is the kind of thing you come back to before you push it up and ask for the review. It's cool. We make a mess first and then we clean it up. That's my style. Now I need to say, hey, when the invitation class uses this parser, use this fake one. I have a snippet for this. We're going to allow parser to receive new.  And return the parser. So when I, let's wrap this. When someone calls parser.new with CSV, return parser. And we need a CSV, which is a little bit weird, but we're going to talk about that in a second. And then, okay. So now, if I want to use this, let's see what happens. Here is a smell that we have just bumped into. Undefined local variable or method CSV. Where is that coming from? Well, it is coming from right here. So my invitation needs a CSV, which is kind of actually kind of goofy and was pointed out by someone very astute in the fourth row over here. But for now we need to give it a CSV. So let's actually, for now, just return a CSV from here. Okay. And then let's be fancy. You guys like being fancy? Do CSV. And that'll be here. And that should bring it. If you want to tap, this is going to return the CSV at the end. It lets us refer to it in here and then returns the CSV at the end. So cool. Back to green. So we extracted our stub parser method. But this is extracted. This method has, I think, revealed us interesting smell, which is that we need the CSV and the CSV is basically unused inside invitations, right? That is going to become important. So let's, but let's talk about what we just did. We isolated invitations and parser. Now, why is this good? Who has reasons for why it might be good to stub out a collaborator like we just did there? Yeah. It lets you unit test them separately. Other benefits. Why might you stub out collaborators like this? Why am I going through all this work? Yeah. You can swap out CSV. Yeah. We can swap out messages. So, for instance, I have, it makes it really easy to specify exactly what I want the parser to say. So before I had to give it a literal CSV string and let the parser parse it out. And now I can just say, here's a fake parser to stand in for the real one. And when you ask it what its recipients are, here's a prerecorded answer. Now that's nice. That's nice now. And it's nice at other times, particularly because it lets you make something that's not deterministic, deterministic, right? For recipients, recipients is always going to return the same thing if you give it the same string. But let's imagine this was something that used time or hidden external service. These are all really good reasons that you would want to stub those things so you can always have the same response come back. This is kind of the idea behind something like VCR or fake web or mock web or something like that. Yeah. Right? Web mock. Web mock. There it is. Yeah. Awesome. Okay. So, this is nice now. We've extracted a class. We've moved a method. We've isolated this. I think we're steadily marching towards, like, better code. I think things are good. But there's sort of one nice thing that we can do now. And this is, in fact, just kind of almost the point of the talk is to get to this point, which is I would like to invert control. And this is what was roughly suggested earlier in the talk, which is it's actually kind of weird that we pass in CSV at all two invitations. Now we're passing in CSV. Let's go check out invitations. So here are all the instances of CSV. This should move to the parser. But here, just two. We use it to build the parser. Here's the CSV. And it's like, thanks. Making it a parser. Cool. Wouldn't be great if we just got a parser. It would be great if we just got a parser. There'd be some definite benefits for that. And the process of instead of, so right now, here's what our control looks like. So I'm going to go, let's move up a level to the invitations controller. So we create an invitations controller. This is a fake controller. By the way, I'm totally like pretending this is Rails. It's totally not Rails. I got you guys good. You should see what's an application controller. Jokes galore. This is all online. You can check it out later. But this is fake Rails. This is not real Rails. So here's how control is structured now. We have invitations controller, which creates invitations, which creates a parser, which uses CSV to parse things. So everything kind of points down. This is normal control, like top down control. It's kind of a standard way of thinking about programming. Inverting control flips that around and says what if you instead built your dependencies at the top level and then pass them down to lower levels so that you actually don't see the word new very often in your lower levels. It's an interesting way of building and this is part of solid. You've heard of solid? The solid principles? This is the I. I is inversion of control. This is something that confused me when I first heard of it. Inversion control sounds weird, sounds funky. Not super hard. One way to accomplish inversion of control is with dependency injection. So this just says, rather than giving invitations the CSV and then having invitations build a parser, what if we just build a parser and give the parser to invitations? That is using dependency injection to accomplish inversion of control. And that's going to be our final refactoring step. How's the mental state? Yeah, question. What if we just gave invitations the recipients? What if we just gave invitations the recipients? Yeah. I like that even better. Version two of the talk will in fact probably just pass in recipients directly. We may even get there. We'll see. Maybe we can get that. That could be our final refactoring if we're speedy and awesome. Other questions? What other thoughts, concerns? I said a lot of like large three word things there that are potentially a little scary. How are you feeling? What questions do you have? Great question. Yes. So in the specs, I extracted methods. Could I use before? I could. I don't generally reach to before until later. So my first pass of refactoring specs is always to use normal Ruby things. Use methods. Methods work great. I occasionally will reach for let's and before's, but pretty rarely. Those are like kind of my like last resort things. What I typically find is when I pull stuff into a before, what I typically get is like I add a new test and the new test doesn't really want exactly the world that's in the before. It wants something a little bit different. So it kind of modifies the world a little bit before it runs. And then we have kind of this weird thing where I need to like go like read the test, see the changes of the world, go read the before, figure out what the world is. Okay, see changes here. And I find like bouncing around a lot in my tests and it sort of creates this complexity. So I will occasionally put stuff into before, but it's sort of my like every once in a while refactoring and not a routine refactoring for me. And I find it tends to make my tests a little bit cleaner. Okay. So let's interrupt control real quick. And this is actually going to be pretty straight, pretty quick. So last page. Let's do this in our tests for invitations. Instead of passing a CSV, let's pass a parser. So let's say we're going to get back a parser instead of a CSV. Actually, and then here instead of this, we get a parser. And then we can actually lose this whole CSV thing, which is beautiful. And we can lose a little of indentation. We can stop stubbing parser. And in fact, just return this parser right here. Let's see if we're green. We're so close to green. This is again a weird and crazy error message because of, this is CSV, the built-in standard library CSV, not being super helpful. But basically what we're doing now is passing in a parser here. And then in the class, we're treating that as a CSV. So we're passing a parser to a parser, which is very interesting from a computer science standpoint. And it reminds me of a Tom Stewart talk about decidability. But for our purposes, it's not super helpful. So let's instead just say, hey, actually this is just a parser now. And if we rerun our spec, something blows up. Thank you. This is why it's great to pair with like 400 people simultaneously. Because all errors are shallow when you have 400, 800 eyes looking at it simultaneously. Awesome. So now we've inverted control. And we've also broken something.  By the way, my .files are online. So if you're curious how I'm getting this cool test thing at the bottom and how I'm doing off in the editor, it's all on my .files. Go check it out. So I just ran our sort of integration spec that's tests through the controller, which means let's go to invitation controller, which I showed you a little earlier. Here we're still passing in this parameter directly. But we actually need to do. This is where the actual version of control is happening. OK. Rather than passing in a CSV file that we read, let's make a parser right here. And the parameters of that will be the CSV file. And we'll read that. And now we can change this to parser. And we can run our tests again. And they pass. That right there was the inversion of control. That's where we switched from, hey, invitations, you build your own dependencies to, hey, invitations, I'm going to build your dependency and give it to you directly. Is this better or worse? Well, like all things in programming, there's a trade-off. Don't ever let anyone tell you that there are hard and fast rules in programming. Anytime someone says something is always good, they're pretty much always wrong. Crap. I'm back myself into a corner. There may be. They're often wrong. Pros and cons. Well, cons are, some people find this a little bit more confusing. You end up with dependencies in a controller. You specify a ton of dependencies in the controller and then dependencies sort of flow down into your system. That kind of weirds people out. So that's one of the cons. It can sometimes be hard. You end up with these classes that are, this class right here takes a message and a parser. What are message and parser? Who knows? I'm just going to take your word for it that parser parses stuff and messages is some sort of message that is message-like. But you can't really see what's going on here. It's actually probably a little bit more obvious when there are class names. But this is maybe a little bit harder to read. Context might be a little bit harder to get. However, testing becomes more simple.  So the tests can get simplified, which is a big win there. This is also interesting. If you're into solid in general, you should check out solid as a set of principles. This makes it easier to follow something called open-close principle because it lets you, so basically on apps where I follow this, I will have commits adding functionality where it is purely green and there are no changes. It's just new code. And if I want to remove functionality, it's purely red. And that's basically what open-close principle gives to you. It's worth digging into that, playing with that a little bit. But one way of achieving that is using getting inversion of control with dependency injection. And we're towards the end. So I have a couple of closing questions, and then I'll let you head out. So before we go, I just have one, I have a jingle for you that I crafted, I wrote for you to remember the main principle of this talk, which is, if you want to follow SRP, don't manage your dependencies. Thank you.