 Thanks everybody. So yeah, shout out to Andy Plizca of Fivotal Labs. He could not make it today. We were totally bummed, except I loved to give presentations and I was gonna sit this one out and I got a chance to step in, so I'm actually, I'm like, hey, sorry, Andy. So yeah, my talk is about refactoring controllers or writing controllers from the start to be slimmer, hopefully more testable. It involves my kind of opinionated methods of writing controllers and it's something I've come to from working at Jukely. It's also something that people will, very smart people might tell you to do. For instance, Sandy Metz I think was mentioned today or somewhere recently and she has these rules for developers that are lofty. Classes shouldn't be more than 100 lines of code. Methods shouldn't be more than five lines of code. I hope that doesn't include ends because that's an if and an else and that's it. So yeah, like I said, it's very lofty but if you can achieve it, it's wonderful. You have code that is really easy to understand quickly. You're looking at classes that are really, really focused and there will be stickers. So I work at Jukely and we use model, view, controller pattern. And this is what it looks like in iOS. So our views on this screen are labels, images, buttons and that's about it. So views in iOS don't have much logic to them. They're just user interaction and they pass everything to the controller. So if MVC are our three buckets, this is the only bucket where we can put Facebook logging and all these other concerns. So it ends up looking something like this. Nice big fat controller and it talks to everything. Now you might do some things where your models get passed to your view. You might write a custom sub view that extends UI view and can handle that model. That's good. That moves a little bit of code out of the controller. Yeah. What I propose is a little different. Slim the controller down and introduce a few more classes. So the layout class is where the controller talks to the view. Layout would be responsible for building the view, for listening for events. It has a very keen knowledge of the screen as a whole but it also makes decisions on how that user interaction will work. So for instance, I'm gonna be coming back to the login screen example a lot. Login screen is usually two text inputs, a login button, maybe you forgot password, login or sign up, that kind of thing. But maybe you decide that you're gonna be really clever and your password is like a UI picker that they pick an image. Well, it'd be great if the controller didn't know that. If they could just say, hey, layout, when they're done logging in, I need the password. And the layout can say, all right, well they did this picker and here's the string. So now your controller knows how to send that along to the API, but even then it knows how to do it via, and here's my other kind of introduction, a storage class for lack of a better name. Though other people call it storage, I'm not alone. Sometimes it's called an adapter or any number of things. So the storage class is that, again, that interface between the controller and your API, the models. So for instance, on this screen, on the Jukely example, it would be responsible for fetching these events and instantiating those objects. Let's look at these again. All right. So why not NBC? It's just not enough buckets, not enough places for things. So I actually prefer, oh, I swear it doesn't show my notes, because I have a way to pronounce it. So I prefer the muck-vulcus way of writing apps. I think it's gonna be a thing, tongue-in-cheek aside, model, query, view, layout, controller, and storage. And I really do pretty much follow this on every screen in Jukely. I have the controller you must have, of course. It has a storage class. I build those immediately. New screen, okay, new controller, new storage. Followed by the layout. So these three are like my first step. Views are pretty dumb, so that'd be a button. It knows how to be touched. It sends that to the layout, which knows how to aggregate events and send that to the controller. Models get instantiated, query, this one's kind of up to you. I separate out models and queries. So fetching data via an API is one thing. Having models that know business logic and know whether or not they're valid to me is another thing. So if you ask an individual person, where do babies come from? To me, it's like, oh, that's another machine that creates babies, not a human. All right, but, so yeah, model, query, view, layout. I forgot I had that slide. I promise that there are benefits. You don't have to have these big fat controllers that have all these different tasks. It slims down your controller first, but even your storage class is not a big class to maintain. Your layout class is not a big class to maintain. So you can get focused in on what you're doing at that moment. And to me, that's huge. Having your brain not juggle a lot of things, I mean, I mentioned earlier, I don't keep a lot of things in memory. So when you're working in a class, say right now I'm working on UI, not worried about that other stuff. Controllers are much more testable, I think. I can say that I write more tests following this. Because your classes are smaller, it's usually easier to add new features. You're not kind of penetrating lots of things that are going on in one class. You've got a small class and you can just kind of inject it in that one little place. And then for teams of people coming in, when they go into your controller and it's focused, then they're gonna read and understand your code, hopefully, pretty quickly. But don't quote me on any of that. So models and queries, that's up to you. Some people put them together, some people don't. These are all, like I say, these are kind of my opinions. Storage, whether or not you use a storage class. I mean, obviously I think you should use a storage class, but what you put in there, again, this is very, very application specific. And sometimes you might say, well, this isn't about screen. What am I gonna use storage for? I'll say nothing. Don't make a storage screen for an about, it's a static. But yeah, so these are your calls. How about layout? Well, I think there's a gym for that. In fact, there's a bunch of gyms for layout. But what I'm proposing is a class. So don't think of, I need something to help me build my view, build a button. For instance, teacup was very good at building view hierarchies and styling them. But it doesn't accomplish any of this. And that's why I wanted to sunset it, because it's very limited. It moves style code out of your controller. But what about animations? What about touch events? All these other concerns that we have with UI. So the important thing with what I'm calling a layout class is having a class, excuse me, having a class that is focused on that. So for that, Jamie and I built motion kit and props to Gantt LeBord for an excellent graphic. He sent me this, and I love it. So, motion kit. It takes that view controller relationship and brings them together. But that also means that I think you should now keep view and controller further apart. You should isolate those roles, get your UI code out of your controller, and that's not just building and styling a view. Those are important, there's a lot of code there. Also animations, events, so touch events. I abstract those now so that login might be a button, or it might be pressing enter on the keyboard. From my controller, it's one event. They want to log in, and from the layout, I would get username and password, and of course, stops. Some features of motion kit does have iOS and OS 10 support. So it works on both, lots of tests. I don't know the number. It's, I think it's like thousands of tests. Is that right, or hundreds? Where's Jamie? That's a lot of tests. It's really neat, because the way it works is these kind of small classes that add functionality to one class or another. So we can support interesting things like core animation layers, and that can have its own helpers that do things, and we can support on OS 10, In-S Menu, an In-S Menu item. So I'll show an example of that. It's really easy, oh, frame and auto layout. Auto layout is a beast. I mean, everyone's been saying like, stay away from it. I do say learn it, it is a beast, but you'll learn when to use it and when to avoid it. So for instance, on a table view, you probably don't need to use it. But on a large view that you want to run in portrait and landscape, you can do a lot of things with constraints that become very intractable with just auto resizing masks. But then inside those views, you can give up on constraints again. So take them and leave them. You can use them in some views and not others. Auto resizing masks will get you very, very far. And when they don't get you far enough, consider using auto layout constraints and motion kits, DSL is pretty good. In fact, that's what people keep coming back. I think people think that's the only thing it does because that's what I've had mentioned. Oh, constraints, great. And you can add your own helpers. So it's very easy to add a new class, tell motion kit, hey, this class tests, or I'm sorry, supports this class over here, and you can put all your helpers in there. Motion kit code looks like this. So you're building a login layout here. We want to, in this case, expose our views to our controller. I'm gonna show you a way that you don't even do that, that you don't even tell the controller what views you have. But if you're starting out and you're converting code, it's gonna, you're gonna want to do this. So we do have that capability. We have the idea of a context. So there's always an object that's receiving these methods. So here in this background, called a background color, it's just a UI view. It's created by default by motion kit. We add a UI label. We're gonna style it as a login label. Add a UI view, style it as a login container. This is probably very reminiscent of promotion code because Jamin and I work on this together. So we took ideas from hopefully everything that's out there. You know, I was the main developer on Teacup for a long time. But even then, I kicked out a lot of ideas from Teacup just because I said, these don't work, they're overly complicated. So inside of a style method, so this is we're styling login label, we can have helpers to say only do this once, not on an orientation or not on a restyle. So I often start with that. Here's just some more examples. This is a fun one. So layer gets called on the target, returns a CA layer, and within the context of that block, now we're working on a CA layer object. This require no code. This is not helpers, this is not, there's no class coming in to help with us. This is just something motion kit can do. If you pass a block to an object, it sets that as a context and runs that inside this block. And here's an example of auto layout constraints. There's some more, but it looks something like this. I want my width to be, and actually what this gets turned into is a layout whose item width property is equal to one times the super view width property. Constraints are very verbose, this is very terse, so that's nice. And then it's centered. This is enough actually, because the height can be implied, because this is a label, the height will be implied by the size of the text. So adding constraints, sometimes you need to use constraints that you get from the controller. You can hand those in as a controller. Actually another way you can do it, you can create your layout, and before you build it, you can hand it the controller top layout guide, and then just keep that as a reference within the layout, and that'll work as well. But here's an easy example. So we set some constraints, this would be on the root view, and then here's some constraints that we've added to the login label, and now they're based on the controller. So if you have a navigation bar at the top, that top layout guide will push the label down. Has a lot of extensions, I mentioned frames, they look like this. Constraints DSL looks like this, I think it's pretty cool, very readable. Doesn't make constraints simple, it makes writing constraint code simple. Again, constraints are hard. In this menu, if you're writing an OS X application, I think that looks a lot better than the boilerplate that you usually have to deal with. And let's see, what extensions do we have here? I think this is just more examples. Oh, there's a, so yeah, here this is built in where you can use some symbols. The readme has examples of all of those. Passing a block to an object. Here's a button helper that is built in, kind of built in as an example of what you can do. There's not a lot of built in extensions because we want people to build them for themselves or as an external gem. So, plugability is big. Portrait and landscape, so there's that orientation support. All you have to do is call restyle, or I'm sorry, reapply on the layout object. It'll call this again, and depending on what orientation you're in, it'll apply that one way or the other. It wouldn't be complete if I didn't port a sweet tea. Was a teacup gem that brought sugar cubes, shorthands into teacup. I ported that over to MotionKit. So, code that is very verbose and looks like that, looks like this in SweetKits. This is what I use, I'll be maintaining this a lot. Events, this is something I mentioned before where you can have your UI events emitted from your layout and you listen for them in your controller. So, we send the username field text. And sometimes text is nil. It's like this weird edge case. And I don't wanna care about that over here. So, we'll take care of that, the knowledge of UI text fields, gotchas. But we'll take care of that over here and just send it. This is just sugar cube. So, don't get thrown by this, this is sugar cube code. And I'm using the target object. Target returns the UI view you're working on. Sometimes you just want that view. You wanna call a method on it directly. There you go. On my controller, we instantiate the layout. We give it a view, you could do, there's a root view that gets created for you by default or you can assign it. And then on a login event, send that. And that's something I would send to the storage object. So, a little bit about where we're gonna go. View, oh, I think I wrote this one twice. View layout helpers, it's on here twice, that's okay. Would be things like if you want a linear just from top to bottom or from left to right. Very simple, nothing, I'm not gonna try and do a grid system. That's a lot of work, congratulations to Todd. So, these are gonna be very light. Spec helpers, those are specific to UI views. I'd like to get something that does say, hey, does my view look like this? Does it have these features? Some sort of language there that MotionKit can help you. So, I did that twice. More tutorials, or some screencasts, and more documentation. And so yeah, so that's our roadmap. Oh yeah, and Jayman, I forgot to tell you, this is something I've been working on as well, because I do get a little bit of insider knowledge. So, MotionKit on Android will definitely be there. It will not be something where you can say, I wanna copy my UI from iOS to Android because you're gonna lose a lot of features with that. This is just saying, I wanna use the same paradigms, the same language. That said, I do have an idea of having generic views. So for instance, a MotionKit label that works on both, a MotionKit button that works on both. But then they would be subclasses of that native view. So you would immediately drop into using that local code. But you would at least have more similarity there. And maybe very simple UI, you could write the same way on either one. So, that's the idea of kill the controllers with an example of how to do that with your UI for a MotionKit. So controllers should not be doing all this work. They should be trying to focus on the application flow. We can move UI and animations into a layout and let it handle those and the interaction with the user. Move that API code out of your controller, put it into a storage class. Big thing with testing that can help there is if you make that storage assignable, in your specs, you can put a testable storage in place and just have it be based on timers. So, hey, I need my events and it's like, okay. And here they are. And then you can continue with the test and make sure that it had a spinner, then it got the event, and then it hid the spinner, that kind of thing. And you're not making any calls to an API and you're not doing mocking. You're actually putting in your replacing object there. There's more tasks. For instance, things like Facebook, talking to Twitter, make little classes for those. You should definitely be thinking, what does this class do? You should be able to answer that pretty quickly. So when you have a big controller and someone says, what does this class do? And you say, it manages my controller, my Facebook connections, my Twitter sharing. It's way too much. So I'm gonna do just a very quick demo of what this might look like. So I'm making my login controller. It's a subclass of UI View Controller. So when I do these, like I say, I always start with, oh, sorry. And I call them after the controller. And, oops, or. You could definitely pass some things in here if you needed to. And then I'll have a layout as well. With Jukely, I wasn't using MotionKit and so I had these like build layout methods and I would include those as a module. Now the recommended way is to, you can either use load view or view did load, whichever flavor you like. And we'll say, my layout is loginlayout.new and we'll pass it our view. It's usually that's fine. With MotionKit, we've added, because we added this setting the root, you have to build it explicitly, but that's great because now we can assign it our top layout guide called self.top. And now we're ready to, let's see, almost ready to do some work. So let's see, in our login controller, we want to handle, let's see, a submit button and should show a spinner login via API. So let's see, we're gonna get the submit, we'll get that from our layout. So on login and we'll ask it for our username and password. And I'll throw this into a handle and I'm gonna pass that to my storage. And I often, I see the same word a lot in my controllers, login storage, login layout, login action on the storage, but that's all right. And that'll either give me a user or some errors. And if my errors are empty, actually if my errors are not empty, then I'll, let's see, self.navigation controller. Ah, yes. No, not acorn. Is that right? Okay, push and I'm gonna use sugar cube for this because that's annoying. And so yeah, it was our main controller. And if there's not, then layout.showErrors. Is that right? And, did I forget anything? ShowSpinner, hideSpinner. And that's the entirety of my login controller. That's all of it. Like all the user text field, what did they do? Did they press enter? Did they press a button? Animations of bringing in text fields and having that look really great. All that is somewhere else. So someone coming into this project in 33 lines and they can understand the flow of that login controller. I mean, that's huge value to maintaining this code, bringing in new people. Obviously this is maybe a little contrived. This is a simple screen. But it works with, you know, main screens where you have lots of data. Think of this, I was asked about infinite scrolling. And to me, as soon as I hear that, I think storage. Storage can handle that. How much, you know, the controller can tell it. They've seen item 40. They've seen item 50. They've seen item 60. It can just send that kind of dumb information to storage and it can say, oh, they saw item 60? They're near the end because I know there's 120 items. I need to go fetch more data. I need to set an instance variable. It says I'm fetching data and it's not arrived yet. Then when the controller says, hey, they're at the very bottom and he goes, oh, that's fine because I have that data already. Reload the table, off you go. And this thing that sounds really difficult, infinite scrolling, has now been kind of wrangled because storage handles that fetching and can know what's going on. And meanwhile, my layout knows about, do I wanna show a spinner at the bottom? Because, hey, there is more data, I'm fetching it. Okay, here it is. To continue with that, let's see, how am I doing on time? Actually, then I don't have enough time. So I won't do login storage and layout, but you've seen a lot of layout code. Is it still working? Okay, good. By the way, that example, the login example, is in this repository. So check it out, GitHub, and this is the motion kit events. We actually separated out events because we really wanna encourage separate gems. You write your own, you contribute. We're considering moving motion kit out of RubyMotion and into a motion kit organization. We'll see if the demand is there. But for now, it's all under the RubyMotion organization. So it's a community project. Speaking of a team of laser-guided fly swatters. So last year, I spoke, I'm kind of getting off topic now, but last year I did a presentation on what was called kiln. I renamed it to motion xray. I promptly went silent on it. I had a designer, a really great designer who worked in Boulder, and he was gonna help me, if you saw it, it was really hilariously awful UI, because I'm not a designer. And he was like, yeah, man, I'm totally gonna work on this and he kind of talked like that, so yeah. And then he quit and moved out and he's a great guy, but I lost my designer. And so I kind of lost my momentum on it. Andrew Cornett, the designer at Jukely. I kind of did that like hint, like, oh, I have this really cool thing, and I've only had a designer. And he's like, dude, this sounds really useful. He doesn't talk like this, but oh, this sounds great. And so he sent me some mockups recently and we're gonna revive the project. So motion xray is an inspector that's meant to be an all-around development tool, so you can run it on your device in the subway, for instance. So if you need to test whether or not your app still works in low bandwidth situations or with spotty connections, it also had an accessibility. Oh, you can't see it. This word here is an accessibility, and with that dead, it was really cool. You press it and it shows your app by its visibility of the accessibility labels. So I'm gonna bring in the motion accessibility gem that we'll hear about tomorrow. I was inspired to create that by Austin. Actually, at the conference, he gave his presentation and mine was the next day, so that night, I built in the accessibility plugin just because I was like, oh my God, yes, that's a perfect example. And it's all plugin based, so you create a plugin and add it so you could have console logging, so you could watch your network events. A really neat one is the inspector. So with the new UI, the idea is you activate it and it's kind of using this contextual bar at the top that you're telling it, okay, I wanna do this, I wanna undo this, I'm done doing that. So touch an element, we tap label, it's selected. We see the view hierarchy down here so you could traverse up the views and then touch to open inspector, inspector pops up and you're able to change these on the device and then hopefully you'll be able to send those changes to yourself or to another developer. So X-Ray was a really fun idea, I thought it was a really good idea and it never died in my heart, so it's gonna be back. And I wanna mention Sugarcube 2.0, it will have OS 10 support and of course support for Blackberry. So I'm Collin T.A. Gray, I'm the community manager at HipBite, engineer at Jukely and it's been a pleasure talking to y'all, I hope you take these to heart. Thank you.