Summarized using AI

The Secret Life of Ruby: Warrior With A Cause

Dewayne VanHoozer • September 29, 2011 • New Orleans, Louisiana • Talk

The video "The Secret Life of Ruby: Warrior With A Cause," presented by Dewayne VanHoozer at RubyConf 2011, explores the advantages of using Ruby for rapid prototyping and concept development in a defense contracting environment. Ruby's flexibility and dynamic capabilities allow it to adapt to changing requirements, making it an impressive tool for developers working under unclear and complex conditions.

Key Points Discussed:

  • Introduction to Ruby's Advantages: VanHoozer emphasizes Ruby’s ability to hide complexity using domain-specific languages and showcases its application in rapid prototyping.
  • Overview of the Lab's Operations: The Virtual Reality Systems Integration Lab at Lockheed Martin, comprising experienced software engineers and interns, uses Ruby to innovate within a large corporation.
  • Integrated System Environment (ICE): This Ruby-based system integrates various legacy systems that previously operated independently, akin to a United Nations for different communication protocols within the company. ICE facilitates communication and interoperability between different 'kingdoms' or systems in the organization.
  • Project Success and Business Impact: VanHoozer shares that since the implementation of ICE, significant contracts worth over eight figures have been secured. The prototype system enabled the team to attract high-level military clients who were pleased with their solutions.
  • Prototyping and Refactoring: The presentation highlights the iterative nature of software development and the importance of refactoring to adapt to customer feedback and new architectural needs, which can yield significant time and cost savings.
  • Development Practices and Lessons Learned: Key practices shared include:
    • Continuous integration and automated backups are crucial for safeguarding intellectual property.
    • Communication and shared vision among team members help prevent conflicts and facilitate problem-solving.
    • Ruby’s performance, while potentially limiting, can be manageable with proper resource allocation and algorithm adjustments.
    • The value of prototyping for deriving effective designs and discovering potential pitfalls.
  • Use of Ruby in Production: Although the lab primarily used Ruby for prototyping, successful cases allowed some projects to transition Ruby prototypes into operational environments after executive approvals.

Conclusion:

VanHoozer's narrative underlines Ruby’s ability to streamline processes, enhance communication between complex systems, and validate concepts through rapid prototyping. The lessons learned throughout the five years of using Ruby in the lab stress the importance of adaptability, team collaboration, and a focus on iterative development to achieve significant business outcomes.

The Secret Life of Ruby: Warrior With A Cause
Dewayne VanHoozer • New Orleans, Louisiana • Talk

Date: September 29, 2011
Published: December 12, 2011
Announced: unknown

Ruby has demonstrated itself to be an extraordinary tool for the rapid development of prototype systems in an environment of unclear, undefined, ill-defined, missing requirements. As a dynamic language its ability to rapidly morph based upon the needs of the moment is remarkable. The way that it can be used to hide complexity via domain specific languages is unparalleled. This session reviews 5 years of success using Ruby within a research and development lab of a major USA defence contractor. Lessons learned, evolved patterns and suggestions for future improvements are on the agenda. There are movies. Bring your own popcorn.

RubyConf 2011

00:00:17.119 my name is Dwayne van huser if you like what I have to say if not it's Larry Ellison but before we get
00:00:25.679 started I I need to do a little bit of a demographic here so uh if you would please self-identify how many of you are
00:00:32.200 radical terrorists members of losec or Anonymous anybody uh how about theoretical
00:00:41.440 physicist okay so I have a requirement I have to give a joke at the beginning of everything so um the bartender says we
00:00:49.960 don't serve faster than life nutrino in here a nutrino pops into the bar
00:01:04.479 delivery it's you know there's not that many physicists here but that's okay I got it all right so I like to get an
00:01:12.000 image in my mind about the topic that I want to talk about in my image is the
00:01:17.520 minute man this is a statue of the minute man from Concord Massachusetts and the reason I have in
00:01:24.360 my mind the minute man is because of
00:01:30.079 the definition of what a minute man was they were able to do things very rapidly
00:01:35.479 they were able to change from plowing the field to shooting the British any
00:01:40.680 British here okay good so that was it they were agile
00:01:49.280 before agile was cool and so that leads me into basically the topic is rapid
00:01:57.039 prototyping and concept development us us Ruby but not just
00:02:03.719 anywhere here I am the senior staff system engineer at the virtual reality
00:02:10.039 systems and integration lab for locked Martin missiles and Fire Control so
00:02:15.400 earlier we were talking about who came the farthest so who here works for a company with over 70,000
00:02:22.319 people okay so I guess I
00:02:28.400 win I have some things that I want to show you that you've never seen before and if you
00:02:36.239 never see me again that's probably because I'm showing you things that you you've never seen before so the first
00:02:42.760 thing I want to show you is what we do in the versal the very first video
00:02:49.879 doesn't have any Ruby at all involved but I wanted to show it to you
00:02:55.519 anyway as it brings a message
00:03:45.959 so that was a video we produced in our lab no Ruby was involved no Ruby
00:03:51.519 involved dinosaurs sounded like the perfect message to
00:03:58.280 bring now the second video is actually going to be kind of a a demo reel of a bunch of
00:04:05.519 things and uh this demo reel took over one year to get through the approval
00:04:11.879 process to actually make available to the public and we made it available to the public about six months ago it's on
00:04:19.040 YouTube if you go to YouTube and search for locked versal this is what you'll
00:04:24.919 see Ruby was involved in the production of
00:05:50.720 it's the virtual reality systems integration lab we are an incubator
00:05:55.840 inside of a large corporation and there's about nine of us in this one
00:06:01.240 lab uh we have two graphic artist Engineers we have a facilities manager a
00:06:09.080 military operations analyst and then the rest of us are software Engineers uh majority of us have over 25 years of
00:06:16.080 experience in um in doing software engineering kinds of stuff but we also bring in uh College interns and uh help
00:06:24.919 Mentor them so we're not only uh incubating new ideas and new products but we're also incubating new Engineers
00:06:31.680 into the company so within the lab we have two tools two tool
00:06:37.960 sets we have the integrated system environment and then we also have the um
00:06:45.199 Eve the engineering visualization environment and what I'm going to be talking about today is the integrated
00:06:52.720 system engineering environment ice ice is a ruby product
00:07:03.000 and this is why we built ice in the first place because within a large
00:07:09.319 Enterprise like Loi within a large customer base that has many different
00:07:14.599 things we have this kind of architecture we have individual kingdoms that have
00:07:21.599 been around for years these are our Legacy systems when they were developed they were developed with the concept
00:07:27.840 that nobody else in the world world needs to know anything about what we have within uh yesterday uh one of the
00:07:34.919 presentations referred to these as walled Gardens and so we needed some
00:07:40.039 kind of a system that would help us integrate and allow the different wall
00:07:46.800 Gardens the the kingdoms to interoperate with each other and so that's when we
00:07:51.879 came up with ice the integrated system environment now this is what happens
00:07:59.759 let's pretend that we have three kingdoms we have the dog Kingdom we have
00:08:05.240 the cat Kingdom and then the rest of us represent the other Kingdom and in terms of communication
00:08:11.520 protocols we can't talk to each other so what we need is something that sets in
00:08:17.199 between each one of the kingdoms like the United Nations translation service now I'm told that these windows back
00:08:24.840 here in the back these are not corporate Hospitality Suites they're supposed to be they're supposed to be the the
00:08:30.000 translators are back there so everybody at the UN hears in their own language in their own
00:08:35.599 protocol but other people are speaking in different languages so Ice is like
00:08:41.200 that ice sets in between the kingdoms and so when the dogs go woof the cats
00:08:47.320 hear meow when the cats purr the go the dogs hear G and simultaneously to that
00:08:53.959 this is what we hear okay
00:09:02.079 so that's I ice is
00:09:08.640 approximately 142,000 lines of Ruby code that makes up about 80% of ice now
00:09:15.519 whenever a programmer starts talking about lines of code he's probably lying just like whenever a politician moves his
00:09:21.240 lips so what does that mean in reality well I used a utility called schlock
00:09:27.160 count that actually compared it and turns out that it's about the same size in terms of Ruby code as we find an
00:09:34.079 active record and ail together now a couple of things about ice that I wanted
00:09:39.279 to show this is a graph produced by uh
00:09:44.320 stats SVN we use subversion for our source code control and early
00:09:50.720 on we uh we were doing branches based upon developers so every developer had a
00:09:58.120 branch and it just didn't work after about 6 months we threw that away and we
00:10:03.519 said all the developers are going to be working in the same branch and we called that Branch The Edge
00:10:08.680 branch and when we did that U we just had a much better time of it um vertical
00:10:16.200 bars are when our feature branches are brought back into our our main Edge
00:10:21.399 trunk so we had an audit last May about uh the versal and
00:10:29.600 specifically about ice and that audit determined that ice was responsible for
00:10:35.720 over eight figures worth of new business brought into the company that's eight figures to the left of the decimal point
00:10:44.680 so uh so Isis has really shown itself to be a very lucrative um piece of work we
00:10:53.279 actually were expecting to go to nine figures at the end of the summer but uh there's been contracts that have been
00:10:58.839 pushed into next year so our backlog is uh uh not as high this year as we were
00:11:05.120 expecting and of course I only had to say SP say eight figures here because it's one of the things that I couldn't
00:11:11.200 tell you was exactly how much money the lab was making I'm
00:11:16.800 sorry uh ice basically enables us to develop
00:11:23.880 simulations and interoperate between these different Legacy systems one of our largest Sim ulations is an air and
00:11:31.480 missile defense simulation it has it's all ruby the
00:11:38.279 entire simulation so what I wanted to show you here was is
00:11:43.760 that as we were prototyping we were able to get can you
00:11:48.959 see this red line from the back okay six months into our
00:11:55.320 program we got to the point where we were feature complete the principal investigator who asked us
00:12:01.800 to create a prototype said all right that's wonderful now I'm ready to bring in customers so we started seeing
00:12:08.480 generals and other people come through our lab and they thought hey that's really wonderful can it do this can it do that
00:12:15.199 well we say yes of course we can and then the principal investigator said okay now would you build me a prototype
00:12:21.720 to do that well it turns out the architecture that I had put in place was not adequate to do the kinds of things
00:12:29.279 that we wanted to do that our customers said that they would like to see so we had to
00:12:36.279 refactor that's refactor almost starting over so basically I had to throw out a
00:12:42.880 bunch of code don't be afraid to throw away your
00:12:48.000 code because after we refactored we were able to bring in a bunch of the code
00:12:53.760 based upon the new architecture and new features and sell
00:12:59.000 the thing off this is going to account for a large part of that eight figures
00:13:04.320 and it's all because we were able to go to the customer without a PowerPoint slide but with an active actual product
00:13:12.680 prototype and say this is the way we think it ought to work and the customer said you're absolutely right here's a
00:13:19.360 billion dollars go build me
00:13:24.600 one this is a u medium siiz simulation
00:13:29.639 that we developed this one I can talk about a little bit more U again you'll
00:13:37.040 see major points of refactoring this one is a what's called
00:13:43.920 a micro grid uh it's for power management and power distribution we
00:13:50.839 completely did all of the control work of and developed all of the optimization techniques in Ruby
00:14:00.000 and the customer really liked it and the customer said okay go build me
00:14:09.399 some and this is one of our small simulations we've been talking the about
00:14:16.720 mocking and other stuff this simulation is actually um the lab was given the
00:14:23.920 task of being the uh the true witness between two competing
00:14:29.720 interfaces the hardware design team and the software design team and so we said
00:14:35.199 hey we can help you out and so we wrote the interface control document for them but we went more than that we said here
00:14:42.440 is our simulation of what the hardware is going to do and here's our simulation of what the software is going to do in
00:14:48.519 terms of the interface based upon the document that we wrote and then we could give the
00:14:54.120 software side to the hardware guys and then we could give the hardware side to the software guys and they could develop
00:15:00.639 u in parallel and they would verify their code against our
00:15:14.839 simulations so this is how ice works we
00:15:20.199 have a a central database where we store stuff and then we have a uh distributed
00:15:27.480 file system so our database stores things like job configurations uh services that are
00:15:33.839 available on our Network and our shared file system contains executables
00:15:38.880 libraries and other stuff that we want available throughout our
00:15:46.560 cluster we have what we call the pier uh the pier is the mainline logic
00:15:55.000 uh that controls uh basically just the main you would think in terms of C or
00:16:00.399 anything else but it's what loads in different libraries and models and stuff
00:16:05.519 and we actually have three pairs Pier D was the very first one we developed it was developed in
00:16:11.279 C++ and then Pier RB is our Ruby Pier it does exactly the same thing Pier D does
00:16:17.360 and Pier J is our Java Pier it does exactly the same thing the other three do so we developed kind of a pattern
00:16:24.680 that says we have a defined API we have a convention in terms of class naming and Method naming and then we have the
00:16:31.600 Pierce and so what we have are simulations that are running that are a mixture of C+ plus Java as well as
00:16:41.560 Ruby the peers load up what we call models models encapsulate the business
00:16:47.199 logic of the thing it is that we're trying to simulate or emulate and that can span the range of a macro Mega model
00:16:56.399 that just says Hey I want to I'm going to have all business logic of a battlefield or it can be a small model
00:17:03.639 that says I'm going to have all of the business logic necessary to move a fin on a rocket so models span the
00:17:10.760 Gambit but the models are loaded by the peers and so their API is associated
00:17:16.799 with the pier and that's how the pier knows how to call the model to tell the model to initialize for example or tell
00:17:23.480 the model how to shut down so it's when you combine these two
00:17:30.280 things together that you actually get an executable and Piers can actually load up multiple models here that's what I'm
00:17:37.960 trying to show now we have a job configuration
00:17:44.600 language which is written in Ruby and that job configuration goes out to the database and says okay the user has
00:17:51.240 suggest has wants to run this particular job and that job consists of all of these different models and so the uh
00:17:59.200 system and takes those models and flings them out onto our network uh this represents hey two real
00:18:06.559 computers one of them might be uh attached to our Hardware integration of lab devices the other one might be a um
00:18:14.600 high performance computer and those little things up there at the top reference or or represent uh virtual
00:18:22.039 instances of uh a situation so this would be one job running across two real
00:18:28.799 computers and for in four virtual machines um we use
00:18:34.720 VMware quite a bit and virtual box just happens to be my
00:18:43.640 favorite and you noticed the concept of ice
00:18:49.440 router when we first started talking within the company about ice and how it
00:18:55.400 works I mentioned the ice router and I got blank stairs back nobody that I was
00:19:01.240 talking to knew what routers were now I think we all get the concept of what an
00:19:06.880 ice router is but it wasn't until I actually showed this picture to some of
00:19:12.600 the senior staff and said this is what routers do they route
00:19:18.520 messages uh some of them didn't quite get it and I had to give them another
00:19:23.559 example just saw that I wasn't being chauvinist there's all of these messages
00:19:29.400 on the table and the router routes the messages to the right place and so after
00:19:34.679 I showed them that two things they finally got it they said oh an ice router routes messages
00:19:45.799 yeah one of the very first ice routers that was developed we call the dispatcher the dispatcher was written in
00:19:53.039 C++ and this what handles all of our military protocols uh such as link 16
00:19:59.120 link 11 link 22 tattle J we also simulation protocols HLA bis CMD all
00:20:07.480 alphabet sup I'm guessing in terms of you know unless you're in the
00:20:12.799 military so this would be consistent with routing
00:20:18.280 binary by wire our XML messages and converting them from one format to
00:20:23.400 another and we use the same kind of a plugin process where we can plug in different methods for getting the
00:20:30.120 information to the different models either by pipes by sockets or by shared
00:20:37.240 memory we also have the concept of the the filter and the transformation so
00:20:42.880 that we can filter messages based upon a model's subscription says Hey I want to
00:20:49.080 receive this kind of message but I only want to receive it when it's within my
00:20:54.440 geographic area or transform it that say hey I want to receive this kind of a message but
00:21:02.919 please change it for me so that uh it's
00:21:08.360 was produced as big IND in for example but I want to see it as little
00:21:15.320 IND the uh second ice router that we put together is based upon amqp and I just
00:21:21.880 want to say rabbit mq rocks it's uh one of the best little products that I've
00:21:26.960 seen out there rabbit mq we have we pushed over several million messages per minute
00:21:34.200 against rabbit and Q in one instance and the thing has popped it just does a
00:21:39.960 marvelous job every time our key
00:21:47.320 concept is the pattern that we developed and basically we hide the complexity
00:21:54.200 from the developers and we only expose the API now this is
00:22:02.360 um not that new but within the business group that I'm was in U this turned out
00:22:10.080 to be exceptionally well
00:22:15.240 received you notice that was in heberg we also have the concept of the
00:22:22.200 smart message now the smart message is a message that knows how to do things to
00:22:28.679 itself knows how to publish itself knows how to subscribe to itself blog
00:22:36.919 itself and this turned out to be a tremendous Savings in terms of
00:22:46.240 time this this what some of that code might look like this is a
00:22:51.600 message now I know everybody here knows Ruby anybody not know Ruby okay
00:22:59.520 when I showed this kind of code to people who have only been doing embedded
00:23:04.640 C++ or a a Ada code they went berserk you mean you can you can do kinds you
00:23:11.320 can do things like that uh it is just
00:23:18.080 remarkable now actually it was this code they said wait a minute don't you have some kind
00:23:24.400 of you know syntax and they said yeah so you can publish you can publish a message and take all the defaults or you
00:23:31.840 can publish a message and tell that publication process what router you want to use what kind of router what kind of
00:23:38.400 encoding technique you can even tell it which logger to use if you wanted
00:23:43.919 to those C++ guys just kind of stared at
00:23:49.039 me this is the way we subscribe to messages we tell the message class we
00:23:54.840 want to subscribe and then we give it the call back method
00:24:05.440 maybe I went the wrong way yeah there it is
00:24:12.320 sorry so that's the
00:24:18.080 subscription some of the lessons that we've learned
00:24:31.120 but it's more than that Albert you can't rely upon people's brains you know why
00:24:36.200 because they're people's brains so you can't rely upon remembering that you need to do a backup let the computer
00:24:42.320 remember let the computer do all of the automated backups for you we actually had one guy on a different project
00:24:49.279 outside the lab uh never backed up the system never used the source code
00:24:56.520 repository never did any kind of versioning control and guess what happened when his computer
00:25:02.360 crashed 6 months worth of company intellectual property went out the door
00:25:09.080 could not be recovered guess who else went out the door so automated
00:25:20.080 backups manage the configuration and that's more than the source code we already talked about it
00:25:25.600 in the session prior you know you got to manage the config of the machines that you're working on
00:25:30.760 as well and we do that primarily the way that we discovered that was the easiest
00:25:36.360 way to manage that configuration was with the virtual machines so we can create one virtual
00:25:42.159 machine and then deploy it several
00:25:54.000 places no programmers in Island right no problem is too hard to be solved if you
00:26:02.559 use the team because every one of us has some kind of a special a specialty we
00:26:08.440 have certain skills that nobody else has and when you bring everybody together you can solve just about any
00:26:21.080 problem this solved a lot of problems for us we originally started with cruise control about four years ago and we only
00:26:28.960 used cruise control on our Ruby products but uh one of the things I didn't mention was is that we never
00:26:35.919 deploy any Ruby products outside of our lab because all of our products are rapid prototypes are concept development
00:26:44.559 proof of Concepts our deployment process deploys with um a different platform
00:26:50.760 with either Java or C+ plus but by bringing in the continuous integration
00:26:56.360 process one of the things that we're able to to solve was the conflict problem because you commit often you
00:27:03.320 test often you communicate all the time and communication is the key that's the key component of agile if you if you
00:27:10.919 have some kind of a silly agile process in place that says you got to do this on
00:27:17.080 Monday and you got to do this on Friday that's not as effective as just talking
00:27:24.840 to the person who sits next to you talking communication is the important thing our continuous integration process
00:27:31.919 I said we started with cruise control about four years ago this year we have done no Ruby
00:27:38.919 products in the lab because we are actually deploying we've already taken our prototypes that we've developed and
00:27:45.320 now deploying them in Java and C++ in January of this year we moved to
00:27:51.720 Hudson and Larry being Larry uh pissed off more people and Hudson for so when
00:27:59.519 we uh took a look at what was going on with Jenkins uh in March of this year we said hey Jenkins is moving along faster
00:28:06.440 they're solving more of the problems that we're having so what we're going to do is we're going to switch over to jenin so we've been using Jenkin since
00:28:13.279 uh March and Jenkins has turned out well for us it works on on our Ruby products
00:28:18.720 it works on our Java products it works on our C++ products runs all of our regression tests every time we get a
00:28:25.640 successful uh commit we all of our test are successful one of the things that we do with Jenkins is we actually tag that
00:28:33.080 U that particular revision and so for QA we always have within our subversion
00:28:38.799 repository a tagged item that says this revision has passed all of our regression
00:28:52.799 test if you've got two people and they have two different ideas about what the
00:28:58.600 product is going to be they're not going to work well together so one of the key things is to
00:29:05.600 have a shared Vision you have to know upfront within the development team exactly what the goal is when we're
00:29:12.640 going to try to get there you have to have that shared Vision if you don't have a shared Vision you're going to have too many conflicts but being being
00:29:19.760 developers even if we do have a shared Vision there's going to be conflicts in terms of Technology well I want to do
00:29:25.039 something one way why well I never did that before I want to try it out well that's okay so long as you have that
00:29:31.039 shared vision and you know where you're going and what time you need to get
00:29:37.679 there this is one of the most important lessons that we learned time is relative
00:29:42.880 it's almost like to pay me now or pay me later kind of thing don't be afraid to throw away your code and
00:29:49.240 refactor sometimes it may actually take a week out of your schedule okay you may
00:29:55.200 say I've got this entire week and instead of doing the next feature what I'm going to do is I'm going to refactor
00:30:01.399 the previous feature and uh it turns out more often than not that that simple
00:30:07.279 thing of taking a week sometimes as long as a month to refactor your base to
00:30:12.679 refactor your architecture actually saves you time in the end and saving time means saving money
00:30:22.919 right that's the other thing we learned there was not one task that um we gave
00:30:28.919 Ruby that it couldn't do well now okay I take that back so when we took our our
00:30:36.399 some of our cluster uh based simulations and the client said hey remember that
00:30:42.240 that little six-month thing where we dropped down to zero the the client in our case it was the principal
00:30:47.840 investigator said hey I want to put a road show together and I want to take this simulation on the road and show it to people I need it to all work on one
00:30:54.360 little laptop okay so we have this super cluster where we were running the simulation and things were kicking and
00:31:00.360 and just doing wonderful and then we put it onto a laptop and guess what it performance slowed down significantly so
00:31:06.519 that was one of the reasons why we had to do the refactoring but what I'm saying about
00:31:12.760 Ruby is even with performance if you've got the horsepower in terms of iron you know you just change your algorithm a
00:31:19.240 little bit and Ruby takes care of
00:31:25.399 it because who's more expensive me computer right we
00:31:30.919 are and uh did I mention backups backups it's
00:31:39.120 plural we back up daily from one server to another
00:31:46.960 server we back up weekly from our main server to a network based system where
00:31:54.720 that network is also backed up and we also back up to removable media that we
00:31:59.799 take offside so one backup by itself is not necessarily sufficient and what do
00:32:06.639 you call a backup that's never been tested failure failure exactly right you
00:32:14.039 should always whenever you do a backup the very first thing you should after taking that backup is to do a restore
00:32:19.320 make sure everything works because a backup that's not tested is a failure
00:32:36.960 in this particular case this Warhead Builder is management who can blow you up more than
00:32:43.320 anybody else management never surprise management if you're going to be
00:32:50.360 late tell management as early as you know if you're three months out from a
00:32:56.559 deadline and you know it's going to take an extra month after that in order to get something done tell
00:33:03.080 management even though the risk is something that they can handle it they also like to know if you're
00:33:10.720 three months out and you're going to be done in another month they want to know that too so never surprise management
00:33:18.320 always let them know what's going on
00:33:29.720 now you're looking at the board over here right and you're saying hey that's the
00:33:35.159 design and this is what was delivered that's wrong this was the design this was the
00:33:42.760 Prototype it was from the Prototype from the proof of concept that the
00:33:49.399 design was derived so don't be afraid to do
00:33:56.000 prototyping because you will get a much better design if you
00:34:04.279 prototype and when things work exactly the way you expect them to work celebrate you know I told you earlier
00:34:11.200 that we never deployed Ruby outside of the lab that's not entirely true we had
00:34:17.960 uh one uh group come by a uh a group
00:34:23.440 that saw our prototypes they said that solves the problem that we have right
00:34:30.240 now would you please let us use your prototypes and we said well we would be happy to let you use our prototypes
00:34:37.399 however your regulations say that you cannot deploy Ruby in this fet so they
00:34:44.839 went through higher headquarters and they got written permission that says that allowed them to deploy our
00:34:51.399 prototype and that gave us an extra contract for not only building the real
00:34:57.760 say but also supporting the prototype in the field so that's all I had to say
Explore all talks recorded at RubyConf 2011
+55