 All right, everybody. I want to get started only about 30 minutes and I got a lot of things. I really want to talk about Right away. I want to ask how many people have read either of these books design patterns in Ruby or design patterns elements are reusable object software alright excellent, so I'm gonna we're gonna talk more about these these Principles up here, but if there's if you only dip into this talk for two minutes, and then you leave I one thing I'd like you to take away from it is how much I believe design how important I believe in upfront design is in startups and These principles have been very helpful to me And I wish I had read these books earlier because I feel like I would have saved myself some pain My name is Mike Sebelsky. I'm one of the co-founder of the company other inbox which is based here in Austin and This talk is really just like what have I learned while building the product So if I could go back in time and tell you know two years ago tell myself Here's all the things you're gonna encounter and ways to save time. Here's what you really should have been trained to do This is what I would tell myself All right, no problem So I the question was do I would run on a treadmill why program I have a treadmill desk And it's it's on our recruiting page Which could be a good excuse to talk about recruiting so thank you I Have a desk set up with to write code on but I don't actually use it that much because if you think about when you're doing a task Where you have to turn your music off? That's the kind of thing we have to stop the treadmill So if you're walking at one mile an hour you can easily comfortably type So it's good for like I can treadmill and write emails and things like that But as soon as I write code I find I have to stop it And so well what happened is like three hours would go by while I'm in the zone and I realized I haven't been treadmilling So what's the point of having this elaborate desk? So it's a nice gimmick to be able to talk about at conferences, but practically not that interesting But there is a whole community of people on the internet who are into treadmill desks So if you Google it that sounds intriguing to you go check it out or you can buy mine for me All right, so my talk is called Ruby for startups really I mean You know good code is good code no matter what environment you're in So but that what I'm talking about is it what's unique about being in a startup as opposed to other environments as opposed to Building a project for somebody else for your consultant or doing something open source or doing it for yourself Well, it's really these things Typically in a startup you're you're building you don't even know what problem you're solving So you're creating an unknown solution to an unknown problem Maybe this isn't true 100% of the time But at least with other inbox and a few other of my friends that I've helped The idea that we started with is so radically different from what the ending result is that even when you think you have it Really well-specced out. It's gonna be so simple. It's really gonna solve this big problem Ultimately you were you were on the wrong track So you're gonna be changing your tracks and you almost always have scarce time and resources I mean unless you're spun out from some bigger company that's funding you Hypically you're writing code under kind of uncomfortable Circumstances you need to start making revenue right away. You need to prove out your idea right away And so that colors everything you do At the level of your craft in fact Like I don't know if anybody reads Eric Reza's blog startup lessons learn But it's extremely influential to me and he has this great line in here His whole point is that startups are really learning engines And so what it's like to be writing code inside of a learning engine like that is this ferocious customer-centric rapid iteration all right, so This talk is loosely organized and it's just about what I what would I tell myself? About how to thrive in these conditions. I really boiled it down to two things one I would spend I would not I would resist the urge to be a cowboy and just write off and start writing code And start you know fulfilling the Requirements You know for what I thought the software had to do I would spend a lot more time On the whiteboard not doing like formal documentation or do anything, you know with like I don't know all the special case tools or fancy things like that I'm just talking about thought experiments Imagining things really taking the time to talk about some of the stuff that we've already seen today about you know How different ways you could use modules and namespace and the kind of things that that you talked about in the in the classes yesterday I mean it I'm self-taught as a programmer and as a Rubyist I don't think there's enough material out there for for auto didax on on good design That's one of the reasons I wanted to start with those two books because I think especially the Russ Olsen book is so Accessible to somebody who's never been formally trained in design. So that's the first thing I would tell myself to do is spend more time designing and Learn more about design so you can your the result is better And then I would also just give myself like a long litany of mistakes to avoid or good practices And then you know, I would be spewing them at my myself as I'm fading back into either returning to the future time I wouldn't stop. Oh, it's gonna be really hard to implement SSL. You're gonna work about this disappear alright, so First part of my top now that we've gone done with the prefatory material good design Russ Olsen pulls out four ideas from the original gang of four book the design patterns book And then he adds one that's kind of more unique to our culture And I'm gonna go through these one at one at a time here Some of these I have more specific examples from others because we haven't encountered all of these problems in even order I just wanted to mainly give you as much a real-world stuff as I could so first of all Separating out the things that change from the things that stay the same if you've read like other kinds of software development literature It's something this is called design for change also and the idea is you want to take things that are That are that are general like that like they're actually for example the preceding talk from from thought bottom I mean that that's like core to what they do anything It appears to me that if they build anything that is not absolutely specific for one of their clients They make an open-source gem or a plug-in out of it And then that can that lives far away from the application code. That's more likely to change or Things like you know the formats of a file or global global variables or input and output formats These are all things that over the life of your project are going to change So what you do is you isolate those design decisions into their own modules and use things like encapsulation and information hiding So that you can mess around with the internals of that stuff You can swap out external services and API's without having to really do a whole bunch of changing for the rest of your app So here's a specific example First time in other inbox like when we started to really deal with the heavy volume of mail We need we used simple queue service from Amazon to scale to be able to share the workload across boxes So this is probably what a lot of people would do. I'm using this jam that gives me a nice interface to ask us I just threw it into a constant and they had it in an initializer in our rails app And then you know first time I needed to use a queue inside of one of my classes I just used that constant to initialize it and that's actually fine. There's really nothing long with that We weren't even sure we wanted to use sqs. So Great. Well, then we started to like use it for everything like every part of our app You know, we have a significant amount of back-end processing that we do and we'll pipe a lot of it through sqs So this pattern started to appear all over and you know We were moving a million miles a minute with our ferocious iterations and nobody ever Really thought, you know, this is getting to be pretty brittle and if we ever wanted to like use a different Messaging provider or something significant like what if we want to change? Oh, like well here I'm fancy little graphics here Like what if we want to use a different provider or what if we want to change the naming convention for what these queues look like? Well, that happened at the same time Amazon deprecated or got rid of the original version of sqs and we had to move to sqs too and We need we had so many of these sqs queues going on that the naming conventions really had to change So we took this is a good time to do some refactoring and we never had to worry about this again And this is what the code looks like now now whenever you want a queue You just ask the queue fetcher Module to get it for you You just give it the simple name like a queue name would be something like Mail like I want to look at the mail queue and you don't really care how it's namespaced or organized You don't even really know at this point that you're using Amazon you're you're really dealing with like a general type here, and then you just manipulate that queue however you want and the actual Queue itself looks like this or that class. It's very simple It does what we did before but now anytime we want to change something to do with our queuing system We only have to change it in one place. It doesn't really have a big ripple effect to the rest of the app This is even a little bit more isolation. I'm gonna talk about later It's our config variables or our global variables or sort of our application state We put that we put that into its own Module which I'll show you about how you do later. I'm actually not hundred percent sure I like the way that is when I started putting this slide together I'll show you some other principles like other ways to equip an object with references to other objects That might be a little bit better I'm just not sure I really like that because that means when you want to use a queue fetcher You have to assume that somebody has already initialized sqs 2 for you and it I don't know where is Something about that just seems fishy to me another thing that you should Hide away is business logic So or something that's likely to change that if you can you'd be better to encapsulate it So when we first receive a message into our system, there's like a hundred different things that we want to do to it to Make sure it lands in the same place, but all that code only applies when the message initially arrives So we used to have a bunch of this stuff inside of like we have this giant message Model right now, and we used to have all this logic that was only ever used one time and that's it's pretty Complicated a lot of conditions in it You know that was all mashed together in this one module Well at some point it became too hard to add new features too hard to fix bugs So we created this envelope class and an envelope is like a think it's just a module that has all the rules to do with Has to do with routing a message now. We have something that we can test separately There's not a lot of coupling between the message class and all this code that has to do with delivery another principle is a program to interfaces not implementation which Means you want to like don't call it a car if you could get away with calling the vehicle I think that's the the example that that rust uses And it's easy for rubius to do because we're you know duck typing is like baked into everything the best example I can come up with from from other inbox is like I Never I'm not really sure what we should call the fundamental unit of thing that we manage for our customers Like it started out with we just had email messages on certain point. We added features to be able to read RSS feeds for you and then we also Let's see like We also now have the idea of We get messages from other sources other than SMTP and so what we ended up doing is like is using inheritance There were some reasons because of the way active record works that we wanted to have all the stuff in a one table The point I'm bringing up here is like I Maybe we don't need all these subtypes Maybe we just need to have a more generic name for message and then you know include different modules Or extend objects that like if it's okay if it's an RSS article in this one context I want to handle it a little bit differently because it's not it's not an HTML message Anyway, I just wonder if there's some if you know a good synonym for message that's very general that would include like Content that arrives via RSS or that you've created and sent through our system like let me know but right now it is message But this is something that we have some struggle with another principle prefer composition over inheritance This is actually something that's come up a couple times in the in the conference already Which means it could sort of doing what I just showed you where you inherit from other objects You should favor this kind of I'm going to show you two different examples actually so When we are pulling in those RSS feeds for people Like at runtime you when you want a feed reader you could tell the feed reader What what queuing system you want it to connect to this is like a maybe a different way of handling that sqs2 problem I showed you before and in this case we almost always know what it is We want so we provide a useful default. Maybe a better example of it would be We use a s3 a lot Amazon's s3 service throughout our our app And there's a lot of different objects that need to have the behavior of being able to send a queried s3 Or you know get data back and so this is like a very small example Mostly the most of the stuff actually didn't write. This is our team So I don't want it. I'm not taking credit for any of the cool stuff They're doing it's just this stuff. I dug up from our code and I really like this module because all you have to do is Include that s3 message content module anywhere. You need it and then you get a whole bunch of Behavior for for free and you didn't have to mess up your inheritance chain and it's easier easy for us to test that module Add new things to it without having those that change replicate throughout our app. All right another principle is delegate delegate delegate You have objects that express certain outward behavior, but and so as far as anyone who's using that object knows That's that's built into your the class you don't have but they what under the surface you're actually forwarding Those methods to some other sub-objects So an example is like this works really well with active record relationships if you're building a rails app which In fact, there's even a helper to make it super easy So in this example, I have an external email account It has a relationship to an extra email server and anytime like but if you if you're using my external email account And you want to know this information like well, what's the server info? What's the mail server? That's not something I actually know I just forward that to an object that I control But now this gives us the ability to change where that information is stored how it's computed anyone who uses an external email Account doesn't care and this is how you can help avoid law of demeanor violations Not if you're not using rails That's totally fine because Ruby comes with two different Library modules in the standard library that help you implement adult delegation So the last thing is not what doesn't come from the the original gang of four book It's you ain't gonna need it and You ain't gonna need it Comes from the fact that we as programmers most like if you're worth your salt as a programmer You love cool new problems or you can use cool new toys You can use the latest thing I mean, I'm always looking I'm always excited about the new cutting edge ways of doing things But sometimes well all the time you have that demon over your shoulder That's always looking into the future for opportunities to deploy that stuff right now to start using it So you can get away from all the crappy crappy legacy stuff. You've been doing well I think this is a fatal instinct if you are writing code in a startup and something you have to fight all the time So like in other inbox only two years old. I was the only person working on it for nine months I have built things To be super scalable that you're not not to be core to the product like this is our web interface It has features on the server side to make this like I Like we have a pretty complicated way of giving you differential updates to this web client that I'm not actually sure We're ever ultimately going to need that's not turned out to be the big sticking point for what makes our apps Low the things that make us slow and perform it have to do all that back-end processing So I could have just saved myself a lot of time and gray hairs by not worrying so much about making this super scalable right at the beginning, so I Think most people probably Like you probably have that level understanding of you ain't going to need it But here's how I combat it in my own mind Because it's easier to say this than to actually implement it because sometimes you really can convince yourself You are going to need it. I recommend that in the early days you focus on learning You're getting more data about what you're building and what your customers want and not performance And I would also ask yourself if there's ways to build an 80% solution Because if you're starting from scratch getting 80% of the way there might be enough for you to learn enough to know Whether this is worth pursuing or whether all of this really is going to be a performance bottleneck Do people even care about the thing that you made so those are the best strategies that I know of for combating the tendency to Want to Overbuild and over design over engineer Okay, so I've got 11 minutes left I'm going to go shotgun through a list of Things that have plagued me or that I thought would be interesting to you guys if there's any time at the end for questions I can delve more so that's our game plan. We're going to go. It's gonna be really quick Okay, I would tell myself plan to move everything out of the web request So now there's all these really cool tools out there that weren't as available or I wasn't aware of two years ago things like AR mail or delay job event machine or SQS rabbit MQ I mean there's all these ways to take all the load Basically to avoid your web app having to do actually any synchronous work inside the web request But then again also remember you ain't going to need it So, you know, it's probably fine to start off doing something inside the web request like sending out an email message or something like that But you always should keep in the back of your mind like I wonder if there's a way to pull this out of the web request because the less time you have to spend worrying about your Server load more time you can building new stuff the better because you're probably at the beginning not going to have a network Operations person on that note I would say make careful use of concurrency because that is Something that we have battled with over the past year since we launched right after how last year's loans are really conference I would prefer. Yeah, I think you should prefer Different processes communicating via some kind of shared bus and there's a million different examples out there Not, you know, not even all just Ruby stuff Because this is just simpler and if you're building something that's a learning machine Using this kind of gear where it's all loosely glued together Just means you can move faster at a certain point though It doesn't really make sense to like spin up a new process and you know that can be Overmuch and so if you if you do want to use multi-threading in your app And especially if you're building a rails app event machine has been a really big win for us So this is like a really typical pattern that is in our code now We send you know thousands of email messages a day now and some certain percentage of those Take like a really long time five ten seconds just because this is a dependency on Third-party gateways out the third-party SMTP gateways. So we Do email sending asynchronously now through event machine. There's more sophisticated ways to do it But this is just one one quick example. We just hand it off the event machine All right about that then the web request isn't blocked our mongrel stay happy Consider your relational database relationship. So I you know We avoid touching our database when we're not storing when we're storing non-critical data when we don't need like OLTP acid level awesome integrity in our data We try and use something else store that information somewhere else We don't use the database for things that it's not good at and we like I've already mentioned To meet put the to meet the our problems in light of these two concerns We use something like Amazon web services, but there's a million other cool Alternate database or alternate data storage systems that have come out in the last year or so for us The biggest the most of the data we store are the contents of messages So we dump all that into s3 So when you actually view a message in our interface, you're seeing an iframe that's fetching the data from s3 To a community to distribute the work across different machines. We use sqs queues They're just a list of things that need to be processed For like we log a lot of performance data. It doesn't really matter if we miss any one log item And so and rather than just dumping it all into a text file that we have to then parse later We just push it into this effectively unlimited infinite database called simple DB and then We you can use s3 is a kind of interesting caching system Which I can talk about later. We use the data fabric gem that Mike perham wrote. He's a Austin Programmer. It's really awesome. This has helped us reduce our database. Well, so I just want to put in a plug in there Okay, so I bet everyone in here who has a blog has already written the blog post about how you should use my sequel explain to find your tune your queries If you use my sequel and you know make sure that you have your indices indices set up properly But I you know prior to embarking on it there about to not know very much about the analyze and optimize commands That my sequel has and other databases have their equivalence the point is that You can have all the indices you want but then once your app starts to really experience some good usage They're going to degrade over time And there's this kind of tech that you're going to have to learn to be able to keep your database healthy and Keep yourself from being awake at three in the morning along those lines You if you are using something like my sequel I recommend you learn more about how the query planner works The one of the biggest speed-ups that we've seen in our app has been not from changing any of our code But just from upgrading to the latest minor version of the database because it had a better query planner and that That made a huge difference to us Our code is not as well organized as I would like it to be and it's just because we're moving super fast It's just sometimes easier to dump something into the lib directory But this is getting pretty unwieldy and like half of this stuff is plumbing code that could be extracted that That would be of use you know to other people that we could use in our other projects if you want to learn more about code layout I really like the active merchant gem. I'll give them that's like I always return to that when I want to know What sub-director does this file going what's pattern should I use to require this stuff? Okay This is something I really am proud of that we do. I've identified three low three types of configuration variables That you should be still you should have a different strategy for first so for stuff That's dangerous or difficult to change like that shouldn't ever It's never going to change like these refer to Interger values that we keep in the database like we're never going to make a new message is never not going to be a new message I recommend we make those constants because they really are immutable. There's another kind of layer of stuff That's like doesn't really change that much It's not there's not dangerous to change it, but you don't really You kind of want it to be somewhat solid and that's stuff like your host name or these timeout settings We just dump that into a YAML file that gets loaded at runtime, and then you can create different Override those defaults for different environments And then there's a category of stuff that like if any if a non programmer wants to be able to mess with it or look at it then We keep that you know in the in the database or I guess you could stuff it in a memcash or something like that So for example Admins at our company need to be able to on the fly change like what addresses you're not allowed to use We use to provide this facility. I'm showing you we use the settings plug-in, which is really cool You should check it out and also this blog article is this is something you're struggling within your app He does a really good job of explaining Why you should do things this way or actually a little bit better approach on what I showed you I Every time we use Boolean columns I've always regretted it because you always want to know the time that something changed or you end up needing more than two states So I always like work really hard to make sure this is really going to be a true or false Because something like this once the table grows to like a million two million rows It can be very difficult to make a change like this So I'm always like really paranoid about it now If you know about if you've heard of how many people have heard of presenters before Jay Fields has blogged about it This has been a huge win for us encapsulates a lot of complex logic Just in that advanced refresher class there if you want to know see more about this come find me I'll show you an example And I would say don't maybe you shouldn't test all the time at the beginning It's a very controversial opinion. I know I'm sure we'll upset some of you But in the first weeks of building other inbox, I feel I felt like I was overly zealous about testing and it slowed down Exploration half the stuff I wrote I threw away anyway I changed the names of a lot of the stuff that I wrote even while I was being so diligent about test first development But on the other hand if you use the test as a design tool as you would in the BDD approach Maybe it you know Maybe this actually will help you save time and make your decision get to your finals on quicker All the code that we use to get your messages from SMTP. That's really mission critical I wrote using the BDD approach and it's been some of the most reliable stuff that we have So I'm kind of on the fence about that and that's why I'm really curious to know if the rails rumbles teams You know like do the ones who write tests are they faster? Do they win more often? I think somebody should do that. I'd be really interested If you are a running a development team where you're the owner of a startup I encourage you to afford regular access to graphic designers because Even if you have developers that are talented at design or that can you know can mess with Photoshop It's really expensive context switch So the best time I ever had working on another inbox was when we built this interface because we had a designer who knew how to use get and knew you know herb and hamel and could really like was making commits to our repository and it just was so much easier than having to like Take the output of this designer and somehow translating something that would make sense in rails And so it was just a really happy productive time that allowed me to get through more of those ferocious iterations Okay, so we have a minute and a half. Does anybody have any questions? Well, I mean it was nice to have a designer who could speak a little bit more of my language than I was used to Well, the alternative would be like a designer who just gives you a You know like the cutout cut up of a Photoshop file and maybe some CSS and it's like up to you to figure out to integrate it into your app Yes, the key key success factor for us to so far is that we had this guy who was able to work with our tools We had a really short deadline last year because we had a big PR event when we launched it And they're like if I had to do all that integration it would have taken a lot longer So one more question Okay, this is this I'm about to show you it needs a whole lot of refactoring So I'm not saying this is good code. It started off a lot smaller than this That we have a presenter that is kind of based on what Jay Fields presented on his blog. Oh Me oh, sorry It's not very helpful so This needs to be refactored to be a bunch of separate classes and modules But I think this will give you the gist of what I'm talking about The idea is I have a controller here that Is that we that's really all it does it just wants to return a chunk of JSON to that web client But to make that chunk of JSON we have to join together information from like six different Objects in our in our system. So that's all the advanced refresher does it has this to hash method that builds up ultimately This hash down here of Objects that the client should create objects that the client should delete and objects that the client should change and then it Like the way we get those that list of things to create is we just it's just calling It's like this is a really just one giant function composed of smaller functions. So if we go to created messages You know, I just it just kind of this has gotten really overgrown and wieldy The point is like I have all this crazy Logic because we're using archive tables and triggers and stuff like that Well that all this complex logic is completely abstracted away from anyone who needs to know about it So if you ever want to get a list of things that changed updated or deleted since you last asked about it You just call advanced refresher and then I have a lot of work to do here to clean it up But another common example is if you have a form like with an account name and like if you have a form That has three objects on it that all have to be created at once or presented at once People will use a presenter so that when you're writing the view code You just have to worry about your one presenter not these three different objects. So that's a really quick example I look at J fields is blog for more So, all right, I just want to end by saying all the slides are at my blog Spellty.com. Thank you very much. All right. We got a 15 minute break