![]() |
Articles Feed |
Categories
Archives
- July 2010 (5)
- June 2010 (4)
- April 2010 (3)
- March 2010 (2)
- February 2010 (2)
- January 2010 (1)
- December 2009 (1)
- October 2009 (2)
- September 2009 (2)
- August 2009 (1)
- July 2009 (5)
- June 2009 (2)
- May 2009 (2)
- April 2009 (8)
- March 2009 (7)
- January 2009 (2)
- December 2008 (3)
- November 2008 (5)
- October 2008 (4)
- September 2008 (6)
- August 2008 (4)
- July 2008 (5)
- June 2008 (5)
- May 2008 (4)
- April 2008 (2)
- February 2008 (4)
- January 2008 (2)
- December 2007 (2)
- November 2007 (2)
- October 2007 (2)
- September 2007 (1)
- August 2007 (3)
- July 2007 (1)
- June 2007 (4)
- May 2007 (7)
- April 2007 (2)
- February 2007 (3)
- January 2007 (3)
- November 2006 (3)
- October 2006 (3)
- September 2006 (17)
- November 2004 (1)
JRuby Helps Us Craft Quality Software
by: doug | April 6th, 2010 | 0 comments »
"It's kind of a Frankenstein." We've used this phrase more than a few times to describe the architecture and technology used to design a product that was recently released after almost a year of development by the software craftsmen of 8th Light. The product is a multi-platform, PC management application for library computer labs written primarily in Ruby, run on the JVM with JRuby. The user interface is written in erb-templated HTML and Javascript, and is displayed in an embedded web browser. JNA (Java Native Access) is used to call operating system specific functions that enable an insane amount of control over the desktop. The various JRuby components communicate with each other over DRb.
But the most amazing thing about this project is that we are using JRuby to deliver a portable, rich desktop app using the best of web technologies. We chose JRuby because it increased portability and performance and reduced development time.
At 8th Light we had tried before to build products for our clients using Ruby, but we always hit a dead end when it came to deployment. For our clients who provide software products instead of software services, the applications must install easily and completely on the end customers machines while still protecting the intellectual property of our client. We tried very hard to make technologies like RubyScript2exe work, but in the end a packing and unpacking solution was too slow and still left our client's source code open for the reading on the installed computer.
As we began the project about a year ago, we discovered that JRuby had reached the point where it could be a viable platform for us to be able to build products that our client's customers could easily deploy in their own environments. Our solution was to bundle all of our JRuby code into jars after it had been encrypted. By patching into the JRuby load service we were able to decrypt the source on the fly and leave the code bundled and encrypted on the disk at all times.
JRuby allows us dirt simple access to Java's huge collection of libraries, along with plenty of custom Java libraries our client had already written. We also go back the other way, implementing Java interfaces in JRuby and using those objects in Java code. This fluidity allows us to always pick the best tool for the job. Early in the project, this also helped to sell the technology to our client. They were wary of a new language that none of their in-house developers knew, but we were able to reassure them that they could easily drop back into Java at any time.
At one point in the project, the client's development team jumped on the project to add a new configuration interface to the server side of the application. The team wanted to use a set of Java tools that they were already familiar with, but needed to make calls into the JRuby side of the application to get and set the configuration values. We built a new Java interface for them and implemented it in JRuby—then from our Ruby initialization code, called a static Java function back on the Main class, passing in the configuration object. This allowed the client's team to initialize their java objects with the instance of our JRuby class that we had provided.
- //The Java Interface
- public interface ConfigurationStore
- {
- void put(Map<string> pairs);
- void put(String key, String value);
- String get(String name);
- }
- #The Ruby Implementation
- class ConfigurationStore
- include Java::package.ConfigurationStore
- def get(key)
- .....
- end
- # Notice how we were able to implement the function
- # overloading present in the interface by
- # using a variable arguments in one ruby method.
- def put(*args)
- if args.size == 2
- ....
- elsif args.size == 1
- .....
- else
- raise ArgumentError.new("put() takes a Hash
- (or a Java Map) or a key and value pair")
- end
- end
- end
We wanted to be extra sure that the class we were writting in Ruby would work from Java before we handed it over, so in addition to the rspecs we wrote to test the Ruby class, we also wanted to write a JUnit Test. Normally, we inject a JRuby object into Java by calling a Java function from a JRuby method and passing along the JRuby object that is to be used. In this case we wanted to actually instantiate the Ruby object in the setup of a JUnit test. We dug around in the JRuby APIs and were able to leverage the fact that the RubyRuntimeAdapter returns the last thing evaluated. We were able to use the toJava() method on the IRubyObject returned from eval and cast the result into the interface class. Then we were free to write JUnit tests exercising the functionality of the JRuby class.
- // instantiating a Ruby object in Java
- RubyInstanceConfig config = new RubyInstanceConfig();
- Ruby runtime = JavaEmbedUtils.initialize(new ArrayList(), config);
- RubyRuntimeAdapter evaler = JavaEmbedUtils.newRuntimeAdapter();
- IRubyObject result = evaler.eval(runtime, "require 'configuration_store';" +
- "config_store = ConfigurationStore.new");
- store = (ConfigurationStore) result.toJava(ConfigurationStore.class);
We do a lot of things at 8th Light to ensure that we can deliver very high quality code to our clients as fast as is responsible. One of the most important things we do is work in highly productive languages. JRuby enables us to write most of the complicated business logic of our application in the highly productive Ruby language and still provide a viable deployment scheme that allows our clients to successfully sell their product to their customers.
This article appears in the April 6th, 2010 Engine Yard Newsletter
Makin' somthin'
by: doug | March 15th, 2010 | 4 comments »

Today (March 15th, 2010) is my Grandfather's 90th birthday. We celebrated with him this weekend in Pike County, IL.
I spent quite a bit a time growing up with Grandpa. On many weekends and for entire weeks of the summer, I'd join him on his farm in Perry, IL. By the time I came a long, grandpa had mostly retired. He rented out his farmland, but still kept some cows around, mostly so that he'd have something to feed every morning.
Grandpa dedicated his retirement to a variety of woodworking pursuits. He made scale models of local buildings, wooden carousels, clocks, toys, banks, and even the occasional joke piece. One of my favorites was a small base with a US quarter mounted to it. A tiny dowel rod mallet slid into a hole in the base. Hand stenciled on the base was the title of the piece: "Quarter Pounder." He refinished furniture, built us an elevated playhouse, and built a scale model of our house. He'd see plans for something in a magazine or pick something up on a trip, and go to work on it in his workshop. I would tag along for much of this activity.
When I was 7 or so, Grandpa did something that I think more than anything, shaped what I was to become and do in the future. He built me my own workbench. It was kid height with kid sized tools. I know that now you can buy playschool workbenches and tools for kids. But the tools on my workbench were no plastic toys from China. They were real: a real saw that was really sharp, a vise that could crush things, a hammer that could actually drive nails. He set it up in his workshop down at the end of the big workbench.
So the story goes like this: (This is how grandpa tells it anyway.) He had lost track of me in the workshop. He had gotten involved in something and I had gone quiet. When he found me, I was hunch over the blue workbench furiously working. Grandpa asked me what I was doing, and I responded "makin' somthin'" I guess grandpa got a real kick out of my response because it's one of those family stories that has been told over and over. Here is what I remember. I really didn't know what I was making. I just knew that I was consumed by the desire to make something. So I was cutting pieces of wood and nailing them together all because I wanted to make. It was part emulation. I admired Grandpa and wanted to be like him. But it was more that he had infected me with this bug. I had caught it. I wanted to be a maker.
I studied engineering in college, but ended up gravitating towards software. Fairly recently I've discovered just why it is that software appeals so much to me. It is because software is making. In engineering, we'd design something and send it out somewhere to be made, but in software, everyday I get to step into a the world of the maker and just build stuff. Every time I open my laptop, I'm 7 years old again and hunched over my workbench consumed by the desire to make. The tools are different, the raw materials are different, the end product is different, but that feeling and that drive to make is just the same.
Thank you, Grandpa, for putting tools in my hands and showing me how to use them, and letting me make something. Happy 90th!
The Hammock
by: doug | March 12th, 2010 | 0 comments »
The Hammock

Our secret is out. A recently published photo revealed it hanging lazily in the corner of our office: a hammock.
Why would an office of software development professionals have a hammock in it?
Well the short answer is that it's always been a dream of 8th Light co-founder Micah Martin to have a hammock in the office. For me, it's an indispensable part of my daily rhythm.
The Reboot
I remember when I started my first internship while in college just how hard it was to stay alert for an 8 hour day. I was reminded of this this summer when I watched the head of one of our interns start to bob and shake at around 2:00 every afternoon. My solution early in my career was caffeine. That sweet green bubbly nectar of the awake dropped out of the vending machine into my hand each afternoon.
I've since given up caffeine, and have learned to get adequate sleep. But there are still some afternoons when everything catches up with me and I just stop making progress. Maybe a particular problem just won't budge, or I have to read some dry documentation. Whatever it is, my brain just shuts down. I sometimes describe it as a fog. It's like that feeling just before getting a headache.
Enter the hammock. Instead of just pushing through and making no progress for an hour or more, I go lie down in the hammock. I lie there and focus on my breathing until I just barely fall asleep. When that first dream sequence starts to roll, I get up, shake out the weariness and start back to work more focused and more alert. I like to call it my personal reboot. Like a sluggish Windows box, I'll I need is to shut all the way down and then turn back on again.
I've heard a story about how Thomas Edison would do a similar thing to refocus himself when he was working. He didn't have a hammock, but he would sit in a comfortable chair with a pile of ball bearings in his hand. When he would reach that just barley asleep state, his hand would drop, the bearings would fall and wake him back up.
Step Back, Go Around
The hammock to me is also a reminder to slow down. As Bob Martin's popular mantra goes "The only way to go fast is to go well." It is also an aid in stepping back from a problem to find that area of minimum resistance. Richard Sennett talks about this idea in "The Craftsman." He says that one of the qualities of a craftsmen is finding the most forgiving approach to a problem. That skill requires stepping into and out of detail on a problem. That is, focussing on the point of tension, but them zooming out to see if going around might be better than going through. A little bit of time in the hammock is great for that. Many times, I've gone to the hammock frustrated with a problem, only to emerge with a completely tangential solution.
It's a Team Thing
Here is what some of the other craftsmen at 8th Light have to say about the hammock.
Short cat naps help reset my brain to keep me thinking clearer throughout a long day.
-- Paul Pagel
I often head there at around 3 (which is coffee time at the client office). In addition when I'm stuck on something I'll try and clear my head in the hammock, when juggling doesn't work.
-- Eric Smith
After a lunch that was a little too big. A 10 minute hammock-nap gets me back on my feet. In moments of coding frustration, a quick trip to the hammock helps me relax and clear my mind.
-- Micah Martin
These guys echo my feelings about the hammock and affirm how giving ourselves the permission to lie down in the middle of the day is beneficial not only to our own health, but also the health or our projects. It's one of our practices that helps to keep us delivering great code day after day, week after week, month after month.

Walk and Code
by: doug | February 25th, 2010 | 43 comments »

The Motivation
A few years ago when we were buying furniture for the first 8th Light office I came across a piece called the WalkStation. It was an adjustable height desk with a treadmill underneath. I had just started to get myself into better physical shape, and thought this would be a unique way to change a sedentary job into an active one. The price tag turned out to be way to high ($4500+).
Fast forward to January 30th, 2010. At ORDCamp, Zach Kaplan, founder of Inventables, gave a presentation about Dr. James Levine and the research he's done creating active computer workstations. It turns out that Dr. Levine is the guy behind the WalkStation that I had seen earlier. Zach had thrown together a treadmill and a laptop desk to try out the concept and was raving about the benefits. It was the motivation that I needed to finally get to building my own treadmill desk.
Acquisition
Using Craigslist, I found a treadmill just blocks from my house. It is a ProForm 830QT. Sears sells this brand, and I think this one retailed for around $900. I paid my neighbor $140 for this one.
My next stop was Ikea. Somewhere in the back of my brain I remembered seeing a desk at Ikea that was adjustable on-the-fly. I went searching, but found nothing that could be adjusted without tools and without unloading the desk first. I had done a bit of a web search earlier for adjustable surfaces, but hadn't come across anything in a reasonable price range. I headed downstairs to the "as-is" section of Ikea and snatched a Gallant table, frame, and T-Leg combo for $60. The legs alone cost that much new. The combo had been a display model and we a little bit dinged up, but the price was right.
Construction
My first concept was to build a free standing table that would sit over the top the treadmill. The table I picked up was wide enough, but the Gallant legs maxed out at around 36" and I knew that wouldn't be enough. I began envisioning ways to make the legs longer.
In the meantime I started to take apart the treadmill. I just started unscrewing and unplugging everything I found until I was left with just the touch-panel unit and circuit board in my hand. There was one cable running through a leg of the treadmill that was pretty obviously the main control cable back down to the motor below. There was also an audio cable, a cable running to the hand-grip heart rate monitor, and an extra heart rate cable leading to nothing. After a look at the manual, I discovered that this cable can be connected to an optional sensor for heart rate chest straps. The whole idea of this setup is to walk slowly and keep the heart rate down, so I just yanked out all the heart rate cables and sensors.
With all of the electronics off of the treadmill, it was back to figuring out how to mount the desk. This treadmill has hand grips on either side. I yanked furiously on these for several minutes trying to pull them off to see what was underneath. After consulting the assembly manual, I saw there was nothing holding them on, so I got out a pry bar and went to town. They eventually gave way and revealed the horizontal supports that were to become the foundation of the table mount.
A 2x4 set across the hand grip post put the work surface at just about the right height, so I drilled a hole through the posts and bolted on the 2x4. The Gallant table frame has lots of mounting holes, so after removing the frame from the desktop, I chose two holes and bolted the frame on top of the 2x4.
Things were looking good, but for the two post that would prevent the table top from being installed. At first I thought that I could cut the uprights off. But my dremel cutting wheel and hack saw were no match for the thick posts. Without the right tools or know-how to deal with metal, I resigned myself to notching out the table top to fit around the posts. This operation was a measure twice, start over, measure twice again kind of affair. But with some care, I was able to cut the notches with a drill and a jigsaw. A quick tip here. When you cut through a laminated surface like most Ikea stuff, masking or packing tape on your cut line will prevent the laminate from chipping.
Amazingly, I had measured and cut the notches right and the table top slid in place and the old holes to the frame lined up nicely.
With the table top mounted, it was time to get control of the treadmill back. First the touch-panel and circuit boards needed to be contained. I didn't want to spend more money on a project box, so I started hacking away at the plastic enclosure that I had disassembled earlier. I was able to cut away everything but a box the just enclosed all the pieces and was even left with two screw holes for mounting. The problem was where to mount it. I wanted the controls accessible, but out of the way most of the time. They couldn't interfere with walking or typing.
I settled on a keyboard tray that would mount underneath the desktop. It could slide under most of the time, and then pull out easily to start and stop the treadmill or change the speed. Ikea has a tray for just under $10, so it was back to Ikea for the Summera Pull-out keyboard shelf. With the touch-panel mounted on the keyboard tray, there was just not quite enough slack in the control line to be able to pull the controls out far enough to see the entire display. I took the cover off on the base of the treadmill to investigate the control cable and see if I could create any slack. I was able to free up enough cable so that the tray could come out far enough, but it came at the cost of the treadmill's incline feature. The cable will bind now because of the re-routing when the incline it pushed up.
Results
So it's been about 3 weeks with the treadmill desk. Here are some of the question I've received:
Q: Don't you get tired?
A: Sure, then I sit down for a while.
Q: Isn't it distracting to your work?
A: I'll admit it took a little while to get over the novelty of walking and coding. Once the meta-conversation in my head stopped ("Look at me, I'm on a treadmill, and I'm writing code!") then I think that low level physical activity has actually helped to keep me focused. Walking engages a completely different part of my brain. I compare it to how some people will pace when they are making a decision.
Q: What about pair-programming?
A: Colin and I have been experimenting with pairing on the treadmill. We've integrated it into our normal ping-pong rhythm. The one coding is the one walking. One green-red cycle, and then we switch. It's a little bit hard to stand and look over the walkers shoulder, so we've been using a second laptop sharing the screen of the first. With both laptops on the same network, the point-to-point screen sharing is pretty responsive. We've had the best luck with Skype. A second screen also allows the pair to sit for a while. I'm still imagining how two treadmills could come together for a fully-walking pair station.
Q: How fast do you walk?
A: 1 MPH for the most part. We've done okay at 1.3 - 1.5 too. I can stay pretty stable even up to 2.0, but I start to get overheated at that speed.
Q: What effect has it had on you?
A: My knee hurts a bit after being on all day. Colin and I have both noticed that we get hungry sooner when walking. I think that mean that our metabolisms are running faster. So I make sure to eat a good breakfast everyday, and we are really ready for lunch at noon now.
References:
Dr. James Levine talk about treadmill desks
The Mayo Clinic's Non-Exercise Activity Thermogenesis Lab
Jay Buster's Treadmill Desk
Treadmill Sensei - Good reviews and info and treadmills
Photos
From the Side:

The touch panel mounted beneath the work surface:

From the Front:

Underneath / Mounting detail:

Update 2/28/2010: Here is some video footage.
Why Software Development is a Craft
by: doug | October 22nd, 2009 | 4 comments »
Craftsmanship has been used as a metaphor for software development. Pete McBreen argues in his book “Software Craftsmanship” that craft is a better metaphor for software development than is engineering or science.
I take the association one step further and claim that it craft is not just a good metaphor for software development, but that software development is literally a craft.
The Hand and the Eye

A key facet of historical craft is the intimate connection between the hand and the eye. A furniture maker cuts a joint with his hands, then fits the two pieces together. If the alignment isn’t perfect, he sands and trims and fills until the joint is true. It’s a cycle of shaping and observing. A glass blower turns the bead of molten glass over and over in a steady rhythm as she shapes the glass towards its final form. Her eye informs her hands and she constantly sees the effects of the changing speed and angle of the turning rod.
Code is a physical thing. Though technically code is nothing more than some states stored on a fast spinning magnetic disk, it is just as physical as a lump of clay. Consider the language used when talking about code. It is touched, shaped, moved, broken, cut, pasted, fiddled with, tweaked, and played with. It is the physicality of code that enables the feedback between the hand and the eye. It is touched and a change is observed.
This is why Test Driven Development is such a key practice in software craftsmanship. There was a time when a programmer would write a bunch of code and try it out hours or even days later. The time between making something with the hand and seeing the results was long. When a programmer writes a little bit of test code and runs it, then a little bit of production code and runs it, this cycle shrinks to minutes or even seconds. The connection between the hand and the eye increases. The craftsman immediately sees the work of his hand.
Making
Another element that makes software development a literal craft is that software development is a process of making. Contrast that to engineering. What is the primary activity of an engineer? It is design. A civil engineer designs a bridge that an ironworker builds. The electrical engineer doesn’t typically etch or populate the circuit board. She designs a circuit that is printed on a board and populated by either machine or technician.
In contrast, the software craftsman doesn’t just design the software (though she does do that), she also makes it. She writes the code that makes it work. There is little manufacturing involved in taking the made software and putting it in the hands of the person who will use it. Sometimes there is a deployment to a server or perhaps a CD is burnt and packaged in a box. But often even these tasks are performed or automated by the maker herself.
Material
Historical craftsmen have always been makers. The potter makes a vessel; the blacksmith, a horseshoe; the weaver, a garment. These makers have always had close connection to the raw material of their work: the wool, the iron, and the clay. What then is the raw material of software craftsmanship? What is the material of which software is made?
The material of software is language. Java, Ruby, C, Scala, Clojure, etc.: these syntaxes are the medium in which the software craftsman works. What makes this media so interesting is that the materials themselves are composite materials made of more primitive materials. Beneath Ruby code lies an interpreter built in C which is compiled by a compiler. The most basic of which is built in an assembly language which is assembled by an assembler which is built in the most primitive machine language which is read directly by the computer’s processor. Each new language emerges out of other languages as craftsmen explore the materials and invent new ways of combining and deconstructing what they have at hand.
It’s similar to metal alloys like steel. Iron is combined with other metals to make an new raw material whose strength enables the construction of enormous buildings. Each new language innovation gives the software craftsman a new, more powerful material from which to build both larger and simpler systems.
Tools
A discussion of software as craft isn’t complete without mentioning tools. A software craftsman does deal with the hardware on which his software runs, but the more interesting tool set is the software that the craftsman uses to write code. The text editor or development environment, the unit testing framework, the continuous integration system, and the acceptance test system are the tools of the software craftsman’s trade. Because these tools are built from the same raw materials as the thing being made, software craftsmen have the ability like historical craftsmen to be tool makers.
Learning
The final argument for treating software development as a literal craft is the way in which it is learned. A traditional college education in computer engineering or computer science produces graduates woefully unprepared to develop software. The best way to learn how to make software is to sit down with someone who knows how to do it and learn from them. This is currently being displayed in many shops throughout the world that are embracing an apprenticeship model for training and growth. This model has been used for centuries to pass on crafts from one generation to the next.
Software is Craft
The Software Craftsmanship community is growing and having some fabulous discussions. I think that this is largely a result of people not just using craftsmanship as a way to talk about or explain software, but embracing and practicing software as a literal craft. The historical crafts have begun to inform us in the software craft and have helped us develop our practice. Most metaphors break down when taken too far, but software-as-craft isn’t losing any steam. Perhaps that is because the association is more than metaphor and software really is a craft.
Meta-programming Comes Naturally to Intern
by: doug | June 22nd, 2009 | 4 comments »
We have a couple of interns in the office this summer. They are kind of like Jr. Apprentices - distinguished mostly by the fact that they are in school and will be returning to school in the fall. I've been working with Andrew this summer. He just finished his Sophomore year of High School and is just learning to program. He's been working through a couple of ruby tutorials: Chris Pine's Learn to Program in Ruby and the ever-so-entertaining-especially-for-a-high-schooler Why's Poignant Guide to Ruby.
He was working on the Orange Tree example for Pine's tutorial. He had the class written and want to write a command line interface to it. This was what he tried to do.
- tree = OrangeTree.new
- command = gets
- tree.command
"What are you trying to do Andrew?"
"I want to get a command from the user and call that command on the tree object."
Now I had expected that Andrew would write a big if-else chain comparing strings and calling methods. In my mind that's what a beginning programmer should learn. I learned to program in C++ and that's the way I had to do it! I wasn't even sure that we would even touch meta-programming this summer.
But I had a second thought. "Why not show him some Meta Programming now?" I don't want to be responsible for destroying the future career of an aspiring programmer, but what the heck? How much damage could it possibly do?
So I explained to Andrew how methods in Ruby aren't really methods, they are messages and how you can "send" a message to an object. We modified his program to do what he wanted.
- tree = OrangeTree.new
- command = gets.chomp.to_sym
- tree.send(command) if tree.responds_to?(command)
I'm not sure that he completely understood all that, but there it is. Ruby let Andrew do the thing that he naturally wanted to do.
Embedded Ruby Talks Morse
by: doug | January 8th, 2009 | 7 comments »
I've been working with Ruby on embedded systems for a couple of weeks now. The final pieces have fallen into place and I'd like to share them with you. From the beginning of the project, my goal have been to turn some LEDs on and off from a web page.
Getting down to the metal
Any embedded software application has to eventually control some interesting hardware. My ARM board had two LEDs wired up, so I thought I'd try to control them. The control for the ports that control those LEDs are in memory mapped registers. Ruby really never let's us see the memory that we are working with, and even if it did, we are working in a virtual memory environment, so we wouldn't be able to access the specific memory address where the register is located. So it was time to learn how to write Ruby extensions.
I was surprised how easy this ended up being. Ruby has a great little module 'mkmf' that makes Makefiles for you. The API for defining ruby modules was also pretty straight forward and explained well in Pickaxe. I put the module I wrote up on git hub, so take a look there if you are interested. The extension allows you to just read from or write to any physical address on the device. To set a bit in a register, you might do something like this.
- include MemoryMappedIO
- from_register = read(0x560000010, "w")
- write(0x560000010, "w", from_register | 0x00000001)
Ahh. . 0x, hex numbers, addresses. It's nice to be back.
To get the module into my Ruby environment, I created an 'mmio' directory in the 'ext' directory of the Ruby source and dropped in the source files. I didn't have to change any makefiles, I just created an extconf.rb and the ruby build system took care of the rest. It would certainly be possible to build the module separate from the rest of the Ruby source, but since I already had the source tree configure to cross-compile, the path of least resistance was to just include this extension in the source tree.
I posted my extension to the ruby-core mailing list to see if there was any wider interested in it. It turns out there is a memory mapper extension already written. I took a quick look and it isn't exactly the same thing that I did. My interface is much more basic (and simple), but I think the mmap extension could be made to do the same thing I am doing.
The Promised Land
With a way to control the hardware from Ruby, I had finally arrived where I had wanted to be. The entire thesis behind this little experiment was that Ruby could make embedded application development fast and fun. I found both to be true. This entire application came together in just a couple of hours. I was able to make use of a ruby gem that did a bunch of the work for me. I called the application weblink. You are free to interpret the name however you would like (We Blink, Web Blink, Web link). The source is on git hub.
When test-driving an embedded system, you'll save yourself a bundle of time by doing as much of the development as you can on your host computer. The download, restart, test cycle can really add up when you are working in quick TDD cycles. On my particular system, the files system is still being hosted remotely, and the language is interpreted (no compile) so this overhead is not that bad. Still I wanted my application to run on my development machine, and I didn't think it wise to overwrite some random address in my Mac's memory, so I needed an abstraction.
When developing these kinds of environments in a C++ system, I would traditionally build a pure-virtual interface and implement it twice, once for the target hardware and once for the simulated, or development environment. In C you can do a similar thing with the linker. You write two functions, one for each platform and just link in the correct one when building for that platform. With Ruby's ducktyping, there is no need for a defined interface, but the concept is very similar.
I wrote two Led classes both with 'on', 'off', and 'on?' methods. The MockLed class just saves the on/off state in a YAML file. The real Led class uses the mmio extension to read and write a bit in a memory mapped register. I did not want the real Led class to have the platform specific knowledge about which LEDs were in which register, so I used the Factory Pattern to create the Led objects. The factory method is called 'find.' The MockLed file implements this same method that returns MockLed objects in the development environment.
The tricky part of this is switching between the two Led classes. For this, I chose to use Sinatra's environment configuration scheme. The production environment is used when running the app on the target, and the development environment runs on my Mac.
- configure :production do
- require 'leds_S3C2440A'
- end
- configure :development do
- require 'mock_led'
- end
Dit, Dash
To celebrate the 170th anniversary of the first demonstration of the telegraph, I decided to turn the application into a visual telegraph, beeping out little messages. The ideas is that you enter a message in the web page, and the LED blinks out your morse code. Here is where I saw the great power of not only Ruby, but also the community who uses it. I discovered right away that there is a Morse Code Gem already written. You give it a string and It gives you back a series of dits, dashes, and spaces. Thanks Ben!
Eric Meyer sat down with me and we ping-ponged out the morse blinker in short order. I love how simple this class ended up. It just proves again to me what great code you can write in Ruby.
See it for yourself
Okay, so enough talking, let me show it to you. Enjoy.
A Screenshot of the app:
What's Next
So I know that the response that I will get from embedded developers is "Great, but it's slow and big, it can't be used in a real system." I'm going to do some profiling and optimization on this system to get some hard performance data. Initial results (just looking at 'top') shows that the ruby process with Sinatra, Webrick, the morse gem, and my code loaded up is taking up about 12% of the system memory. That mean about 6 or 7 MB. What nice is that you only pay for what you use. If you don't require it, it won't load into memory.
As far as clock cycles go, the ruby processes peaks out at about 20% of the 400 MHz processor when serving HTTP requests. While blinking the LEDs, only a fraction of a percent of the processor's cycles are being consumed. I'm not happy with the performance of Webrick (no one ever claimed it was fast anyway) and I am going to try to get Sinatra running with 'Thin' instead.
Synchronization: I fork a new ruby process to blink out the messages. If you got both LEDs blinking at the same time, they could step on each other's toes and cause incorrect values to be written to the LED. I need to stick a mutex in to protect that register.
I remember early in my career, Kevin Moore and I had started using Ruby to run our embedded builds. We used the Win32 API to drive the automation interface of Metrowerks and we wrote lots of little tools to do the annoying parts of building a flash image for us. I remember at the time, Kevin and I having a conversation that went something like "Wouldn't it be cool if we could write the entire app in Ruby?" Well Kevin, now we can.
Embedded Ruby Sings Sinatra
by: doug | December 30th, 2008 | 3 comments »
Last Time I got ruby up and running on my Arm based embedded development platform. Here is a quick summary of what Santa and I did over Christmas.Sockets
Getting support for sockets built into Ruby turned out to not be hard at all. All I had to do has uncomment the extensions I wanted in ext/Setup. Here is everything I decided to turn on.- etc
- fcntl
- iconv
- socket
- stringio
- strscan
- syck
- thread
- zlib
After a rebuild and reinstall, I could require and use 'socket.' Welcome, Ruby, to the outside world!
Relocating Ruby
I decided to move ruby to the 'standard' install directory (/usr/local/) instead of the root that I had done in the first iteration. This would avoid having to set the RUBYLIB environment variable and keep any mess I made out out of the main system /bin and /lib directories. First I removed the --prefix from the configure script I had written last time. This will cause Ruby to build assuming the default install location (/usr/local/).- #! /bin/sh
- export ARM_TOOLS=/usr/local/arm/gcc-4.2.3-glibc-2.3.3/arm-unknown-linux-gnu/bin
- export CC=$ARM_TOOLS/arm-unknown-linux-gnu-gcc
- export LD=$ARM_TOOLS/arm-unknown-linux-gnu-gcc
- export AR=$ARM_TOOLS/arm-unknown-linux-gnu-ar
- export RANLIB=$ARM_TOOLS/arm-unknown-linux-gnu-ranlib
- export ac_cv_func_getpgrp_void=yes
- export ac_cv_func_setpgrp_void=yes
- ./configure --host=arm-unknown-linux --enable-wide-getaddrinfo
After Ruby was built, but before installing it (make install), I hacked the DESTDIR in rbconfig.rb
- ...
- TOPDIR = File.dirname(__FILE__).chomp!("/lib/ruby/1.8/arm-linux")
- DESTDIR = "/~/ruby/install"
- CONFIG = {}
- ...
This created the /usr/local tree inside my install directory. I created a /usr/local/ on my file system and copied that tree over. The only problem with this process is that the sh-bang line on the top of all of the ruby scrips (irb, testrb, etc.) had the wrong path in them. They had the install path on the host machine (/~/ruby/install/usr/local/bin/ruby) instead of the actual path on the target (/usr/local/bin/ruby). I changed those by hand.
Sinatra
Ahh, now the good part. Using a gem on an embedded system is an interesting problem. I first had to get rubygems installed on the network files system. I downloaded the source code and temporarily placed in on the target files system. On the target I ran the install command.- ruby setup.rb --no-rdoc --no-ri
I found it more convenient to install the gems from the host system instead of the target. It would be faster and the 'gem' command had some ruby dependencies that I hadn't yet build. I downloaded Sinatra and Rack and then manually installed them into my target's file system on the host machine. Note that /arm/fs/ is the root of my networked file system. I switched off rdoc and ri to help keep the install small.
- sudo gem install sinatra-0.3.2.gem -i /arm/fs/usr/local/lib/ruby/gems/1.8 --no-rdoc --no-ri
- sudo gem install rack-0.4.0.gem -i /arm/fs/usr/local/lib/ruby/gems/1.8 --no-rdoc --no-ri
With Sinatra installed and ready to go, I wrote a quick Sinatra app. Sinatra runs on Mongrel by default, but I wanted to run on the lighter weight Webrick web server which was already in my ruby installation.
- require 'rubygems'
- require 'rack/handler/webrick'
- require 'sinatra'
- Sinatra::Application.default_options.merge!(
- :run => false,
- :env => :production,
- :port => 80
- )
- get '/' do
- "Hello Sinatra!"
- end
- Rack::Handler::WEBrick.run Sinatra.application
Drum roll please ...
Next Steps
I've been plugging away on the linux device and ruby extension side of the project. I'm still on the steep side of the learning curve, but making progress. I'm still after that elusive blinking LED!Embedded Ruby - First Steps
by: doug | December 19th, 2008 | 3 comments »
I spent the beginning of my career working on embedded systems for some audio company. These embedded systems were my first love in programming and to me, no flashy css on a web page can beat the thrill of writing some code that flashes an LED. I've been working lately with Ruby a lot. I love it. I love that the language nearly disappears and I am able to express pure intent. Ok, so there is still syntax and such, but I can create so much more with so much less code.I hate living a fragmented existence, so I've been working the last few days on bridging these two worlds of mine. I figured that it will also give me a chance to get more familiar with linux and the latest in the embedded world.
First up, pick a platform.
I chose this single board computer from Glomation. It has an ARM920T core and an LCD / touch screen interface which may be fun later.Next, Tools.
I was determined that I could get a toolchain up and running on my MAC, but eventually ended up running linux in a virtual machine. Glomation had a set of tools and a pre-patched kernel already to go on their support page and our apprentice had a virtualbox linux image that he let me copy, so I was up and running quickly.I do want to share with you a few of the resources I found in the processes.
- I began with the GNUARM project.
- Tom Walsh on the gnuarm mailing list was helpful and pointed me to his scripts. I came real close to a working toolchain on the Mac with his help.
- I also gave the Crosstools project a try but ended up in the same place I was before.
- Thanks to David Goodlad's RubyConf 2008 presentation I discovered Open Embedded. This seems to be where the momentum is right now. I imagine I will give this project a careful look soon. I wish I would have started here.
Cross-Compiling Ruby
A few folks have had some success cross compiling ruby and Goodlad's presentation claimed that ruby is a part of the open embedded project. I built ruby 1.8.6-p111 because that what was on my linux distribution and it seems to be a well distributed release. Here is the script I used to configure ruby for cross compilation. Thanks to The Zen Machine blog for the skeleton of this script.- #! /bin/sh
- export ARM_TOOLS=/usr/.../arm-unknown-linux-gnu/bin
- export CC=$ARM_TOOLS/arm-unknown-linux-gnu-gcc
- export LD=$ARM_TOOLS/arm-unknown-linux-gnu-gcc
- export AR=$ARM_TOOLS/arm-unknown-linux-gnu-ar
- export RANLIB=$ARM_TOOLS/arm-unknown-linux-gnu-ranlib
- export ac_cv_func_getpgrp_void=yes
- export ac_cv_func_setpgrp_void=yes
- ./configure --host=arm-unknown-linux --prefix=$HOME/ruby/install
ARM_TOOLS is where I installed the cross compiler. The prefix is just the place where 'make install' will drop the results of the build.
The configure script generates a file in the ruby root director called fake.rb that causes some problems when I went to 'make'
- /ruby-1.8.6-p111/fake.rb:12: unterminated string meets end of file (SyntaxError)
I opened it up and it has a very obvious syntax error in it. I added the missing backslash on line 12 and ruby built fine from there.
- 12 ALT_SEPARATOR = "\";
becomes . . .
- 12 ALT_SEPARATOR = "\\";
'make' then 'make install' and I had my cross compiled rubyGetting Ruby onto the Target
The last step to seeing little rubies flying on my ARM core was to get the build onto the target. The Glomation board came preloaded with a kernel and a root file system. The kernel source was provided on the support page but not the root file system. I asked their support guy and he kindly posted it for me. I was dreading having to rebuild a file system from scratch, so I was grateful for his help.I decided that the best option would be to just have the target load of the root file system over the network on boot. I followed these instructions for mounting the image on my linux VM and these instructions for setting up an NFS Server. Mounting the file system over the network is a great option because now I can edit the file system from my Mac or linux VM and have the target see the changes without even rebooting. Perfect! The 2440 board came loaded with UBoot and all I had to do to load the file system over the network was to set the nfsroot in the bootargs from the bootloader's command line.
- set bootargs 'nfsroot=10.0.1.151:/arm/fs rw console=ttySAC0,115200 ip=dhcp init=/linuxrc'
Once booted, I only needed to set the RUBYLIB environment variable so that ruby knows where to find the libraries. I added this to my init script.
- export RUBYLIB=/lib/ruby/1.8
And there you have it. Ruby running on my ARM board:
Next Steps
Here is where I want to go from here.- Sockets. I need to build openssl support for ruby so that I can talk to the world from Ruby. The Zen Machine ought to help me out here.
- Sinatra - I'd like to run Sinatra on the target and start serving up some web pages
- RTC - I want to get that on chip Real Time Clock working so that it's not always 1970
- Drivers and extensions - I want to be able to control some hardware from Ruby. I've got a lot to learn here but I'll have to find or write a linux driver and then build a Ruby extension on top of it. I'm imagining something like led.on and led.flash.
- Submit to ESC. I'm hoping to submit my work to the Embedded Systems Conference. I hope that Ruby can start picking up some momentum in the space and save embedded developers gobs of time like it has done in the web development world.
Own Your Tools
by: doug | September 15th, 2008 | 2 comments »
I spent a lot of time with my grandpa growing up. He has spent much of his retirement ‘fooling around’ in a workshop he built on his slice of Pike County, Illinois farmland. From a very early age I spent a lot of weekends and entire weeks of the summer as Grandpa’s little helper. I’d work on the things he was working on while helping and learning. When I was about 7 years old, I was helping Grandpa refinish a dresser. I had a flat paint scraper in my little hands and was trying to dig into the layers of flaking paint that gripped the dresser. I really didn’t have the strength to get under the paint with that big blade, so I turned the tool on edge and started scratching deeply into the wood. I was making progress now, but tearing the heck out of the surface. Now in Grandpa’s version of this story, he says that when he saw what I was doing he corrected me too harshly and sharply and later found me teared up in a corner of the workshop sorry for what I’d done. I honestly don’t remember being that hurt by his rebuke, but I do know how to use a paint scraper and dozens of other tools properly because of that time I spent ‘helping’ grandpa in his shop.
As software crafts-people our tools are other bits of software. We spend every minute of every day using software. Our editors, compilers, interpreters, source code repositories, IDEs, debuggers, and test frameworks enable every stage of our work. Everything we do to create and add value to a software project requires some other software tool to make it happen.
At many of the places I’ve worked, the developers have a laundry list of complaints about their software tools. Often, teams develop elaborate rituals and incantations to dance around the shortcomings of their tools. “Before you check in, copy this file over there then add a note to that file then spin around in your chair three times and your check-in should succeed.” Now I agree that there are lots of poorly designed tools out there. Some tools do things that just don’t make sense and others crash all the time, but I have a challenge for us as software crafts-people: Own your tools. Tools are software, you are a software crafts-person. You can find or make a tool to do anything you need.
Groups decide to invest in a tool, often at great cost, but very few people end up understanding or even using the tool. The tools usually gets blamed for its shortcomings before anyone has really made the effort to get them to work. They give up on it far to early. Own your tools. Understand everything it can do, and if it isn’t enough, find a way to make it do what you want.
One of the cool things that happens is that investing time in your tools may give you the chance to explore a new language. One of our goals as craftsmen at 8th Light is to learn a new language every year, but often its hard to justify the time spent in a new language when you are heads-down in a project. Using a new language to create a tool for yourself may give you just the excuse you need to spread out a bit and learn something new.
Is it really worth it? Can the time spent writing “non-production” code really be justified? Let’s take a task, say the creation of a new class in C++. Most people when creating a new class, will open up the last class they worked on, copy the entire thing, paste it into a new file, delete all the methods and data, then do a find/replace on the class name. There are probably a few comments that need editing, the revision history needs to be cleaned out and maybe there is a comment header or footer that needs to be updated. This entire process could take maybe 2 minutes. It hardly seems like it’s worth automating. Except … Wait! It won’t compile, because you mistakenly didn’t remove the parameters from the constructor and the compiler can’t resolve the dependencies. This is a manual process, so it’s error prone. So you spend maybe another 3 minutes getting the thing to compile. Then we need a test harness so you do the same copy, paste, delete, find / replace process. 8 minutes later we have a new class and test harness and we are ready to start working. The hour or so investment to build a tool for yourself will surely be worth it now. If you share your work with the rest of your team and suddenly everyone is saving 8 minutes every time a new class is generated, you might have your hour back by the end of the week.
Some IDEs and editors have some class generation utilities for you. This may get you part of the way there, but it probably won’t put your company’s header on the top or put in your source control keywords. It may not make your destructor virtual or create a private copy constructor to start like I like to do. The tool doesn’t do exactly what you want. Own your tool. You are a software craftsmen. You can create software that generates a class for yourself. If you are in an editor that supports macros or bundles, you may be able to implement the tool in the editor’s macro language.
In this spirit, the craftsmen at 8th light have contributed to open source software tool projects for several years. Micah is the author of the widely used Fitnesse acceptance test framework and Eric has taken over the management of Selenium on Rails. Micah’s also been working on a whole new development framework called LimeLight. We love open source tools because they let anyone own the tool.
Grandpa used to make things out of sliced walnuts. He’d glue together little baskets or crosses and fill the walnut cavities with colorful beads. As you can imagine, a walnut is a pretty difficult thing to slice. At the very least it’s awfully dangerous to get your fingers that close to a band saw. Grandpa showed me a while ago the tool that he made to save his lower digits. It’s a pretty simple block of wood with a half-walnut sized divot carved out of it. It was a woodworker using his woodworking skills to create (and own) a tool for woodworking.
If you’d like my class generator, you can have it here. Chances are, it won’t do exactly what you need it to do, so … own your tool.
Maturing the Manifesto
by: doug | August 27th, 2008 | 1 comments »
There has been an interesting discussion happening about adding a 5th value statement to the Agile Manifesto. Uncle Bob Martin proposed this addition earlier this month at Agile 2008. The proposal has centered around the idea of craftsmanship or professionalism. In his keynote, Uncle Bob proposed that we value “Craftsmanship over Crap” and in a later blog post suggested “Craftsmanship over Execution.” I strongly agree with the call for more professionalism and craftsmanship amongst software developers.
The original value statements are comparative. The things on the right still have value, but the things on the left are valued more. “We value working software over comprehensive documentation.” I think what has happened is that we have found something we value MORE than “working software.” We value well-crafted software over working software. It’s very important that the software works, but even more important is that the code is clean, that it is easy to read and therefore easy to change.
I’ve been reading “The Craftsman” by Richard Sennett. I’ve found a great definition of craftsmanship. “They are dedicated to good work for its own sake” (Sennett 20). A craftsman is driven by quality. Quality software is software that both does what is is supposed to (works) and is clean and easy to continue to work with.
This has me wondering about the other 3 value statements in the manifesto. Are there things that we value more than those things on the left hand side? We are learning day by day better ways of doing software, so what have we learned since 2001? We have a good idea about how Craftsmanship shapes the way we think about ‘working software.’ How can the idea of Craftsmanship change how we think about ‘responding to change’, ‘individuals and interactions’, and ‘customer collaboration’?
Sennett, Richard. The Craftsman. Yale University Press. New Haven and London. 2008
How Doug got started programming
by: doug | August 8th, 2008 | 0 comments »
Tagged by Micah Martin
How old were you when you started programming.
When I was about 11 or so I bought a Color Computer III at a garage sale. I started typing in some basic programs that I found in a math text book or something. I had no disk or tape drive, so I had to start over every time I turned the computer on. I don’t remember what the program did. I do remember playing the game with the bouncing ball, paddle and busting up bricks.
How did you get started programming.
I started writing static web pages somewhere around 1995. I was the president of my high school’s computer club and we built the first every website for Jacksonville High School, complete with a presentation to the school board. I’m pretty sure the site had blinking text.
We also started learning C++ in the club. We didn’t have a text book, but our sponsor, Robin Manker, would print out sheets each week for us and we’d bind them into one of those plastic spiral bound things that you needed the machine to open up the binding.
What was your first language?
BASIC
What was the first real program you wrote?
Like others, I’m not sure what makes a program ‘real.’ I remember that my first C++ exercise was a Fahrenheit to Celsius converted.
What languages have you used since you started programming?
BASIC, ADI Sharc assembly and other uber-fun machine languages, C, C++, Java, Ruby
What was your first professional programming gig?
My first job was writting DSP (Digital Signal Processing) algorithms in assembly. The first thing I worked on was the compressor algorithm, I implemented time sharing on the averaging algorithms and reduced the cycle count by 30% or so. The processor was an Analog Devces Sharc. It had two data buses and two ALUs, so you could basically make two read/writes from memory and two arithmetic calculations per clock cycle. We’d write lines of code that looks like this:
r1 = r2+r5; r3=r6-r7; dm(i6) = r2; r5= pm(i3);
Everyline of code would be followed by a line of comments explaining the line. It was painstaking work, but It’s how I learned to be methodical and linear. It was also a whole lot of fun to listen to your code after you finished it.
If there is one thing you learned along the way that you would tell new developers, what would it be?
I still remember one of the first things Robin, the first person to teach me how to code used to say. I still pull it out often. It went something like this.
1) There is a teapot sitting on the counter. How does the programmer solve the problem of making tea? He picks up the teapot and sets it on the stove.
2) There is a teapot sitting on the floor. How does the programmer solve the problem of making tea? He picks up the the teapot and sets it on the counter. The he says “I’ve solved this problem before”
What’s the most fun you’ve ever had programming?
Kevin Moore was one of my first mentors when I started working at Shure fresh out of college. These was a time, when we would stay late every Tuesday night and code together. He was the first one to tell me about XP things like “What’s the simplest thing that could possibly work” and pair programming. Late on Tuesdays we didn’t have any managers telling us to stop wasting time with two people at one computer. We paired together writing the microcontroller code for the DFR22. We had a lot of fun and pulled of a pretty amazing project in something like 8 months.
Up Next
Note sure if they have blogs or not: Kevin Moore, Robin Manker
That's Not Agile! Bibliography
by: doug | August 7th, 2008 | 0 comments »
Mondo Cane. 1962. http://www.youtube.com/watch?v=fSZXe5NjqAw]
McConnell, Steve. Cargo Cult Software Engineering. IEEE Software. March/April 2000. http://www.stevemcconnell.com/ieeesoftware/eic10.htm
Frye, Colleen. Alistair Cockburn on what’s agile, what’s not. 2007. http://searchsoftwarequality.techtarget.com/news/interview/0,289202,sid92_gci1255480,00.html
Beck, Kent. Keynote Address. RailsConf 2008. http://www.viddler.com/explore/gotthingsdone/videos/5/
Vandegriend, Basil. To Be or Not To Be Agile. http://www.basilv.com/psd/blog/2007/to-be-or-not-to-be-agile
Spolsky, Joel. From the “you call this agile?” department. http://www.joelonsoftware.com/items/2006/11/15.html
Webber, Jim, Ph.D. Agile Atheism. http://jim.webber.name/2006/11/30/a7ccc5a7-08a8-4594-a347-5f78e13f04f2.aspx
Martin, Robert. The Founding of the Agile Alliance. http://blog.objectmentor.com/articles/2007/07/10/the-founding-of-the-agile-alliance
Fowler, Martin. Writing The Agile Manifesto. http://martinfowler.com/articles/agileStory.html
Holy Bible. Matthew 15:1-11. http://www.biblegateway.com/passage/?search=matthew%2015:1-11;&version=31;
That's not Agile, Live
by: doug | July 26th, 2008 | 0 comments »
About a year ago, I wrote That’s not Agile. The idea has grown a bit since then and I will be presenting it as a workshop at Agile 2008. If you are coming to Toronto, please consider coming to check out the workshop. It all happens Thursday morning (8/7) at 8:30 am.
In this workshop we’ll be looking at the differences between the practices of Agile and the values/beliefs in Agile. We’ll explore questions like “What makes a practice Agile?” “Is it your practices that make you Agile or you beliefs?”
I’m especially hoping to find some people in the room who have been on a team that has struggled in transitioning to Agile.
See you in Toronto!
Sockets Enable Multi-Lingual Applications
by: doug | November 4th, 2007 |
As we work with our clients to delivery new features to them quickly and with high quality code, we are finding that the fastest way forward is often writing code in Ruby. The problem is that in many cases we are working with an existing application written in a different language. We may need to add a feature to a C++ application or integrate with a Java Library. One of our favorite solutions in this situations is to have multiple applications talking to each other over sockets.
We’ve found that using sockets to communicate between applications is a great way to ‘bolt on’ new functionality. This type of communication has been around for a long time and nearly every language has socket communication in standard libraries or in free open source projects.
Dean Wampler suggested that Applications Should Use Several Languages and socket communication is another way to enable this.
Socket Basics
Most internet communication is built on socket communication, so I won’t try to go into great detail here. I don’t pretend to be an expert. Here is what you need to understand about sockets to use them in your applications.
UDP vs TCP
There are two basic types of IP socket protocols: UDP and TCP. UPD is what I’ll call a ‘send and pray’ protocol. In UDP there is really no difference between server and client. Each node can listen on some port and write on some port. Messages are sent from point to point or broadcast to all nodes. Either way, delivery is not guaranteed. The message will likely make it to the destination, but there are a host of things that could happen that would prevent delivery. Worse, as the sender you can’t know whether of not your message made it unless you implement some kind of response protocol on top.
I’ve used UDP communications for monitoring / metering applications where it isn’t important that every message be delivered, but I’ve also found that I usually end up implementing some kind of delivery guarantee mechanism anyway.
TCP sockets build another layer on top of basic IP communication that does guarantee delivery. Once the connection is established between client and server, both side can communicate knowing that their message will be received. On the Server side, a socket listens on a particular port for new connections. Most libraries call this operation ‘accept.’ A client ‘opens’ a connection to the server. This process involves the client and the server agreeing on a new port for communication. If the server is going to accept multiple connections, then it usually launches a new thread to handle each new connection.
I use TCP Sockets for most inter-application communication. It turns out that in most situations, I want that guaranteed delivery and don’t want to bother with my own acknowledgment protocol. So it’s the TCP Socket that I’ll show you for now.
Over my next few posts, I’ll show you how to communicate via sockets in many languages. We’ll start with Ruby. Ruby has TCP Sockets built in, though there really isn’t much documentation on how to use it. Here is how to do it.
The TCPSocket class can be found in ‘socket’
- require 'socket'
Create a socket server. The first parameter is the address to listen on. If you specify ‘0.0.0.0’ then the server will accept connections from any host. If you specify ‘localhost’ or ‘127.0.0.1’ this the server will only accept connections from sockets on the same computers. The port can be anything you want. Be sure to avoid commonly used ports.
- server = TCPServer.new('localhost', '4138')
Now, when you call accept on the server it will block until a client opens up a connection.
- server_socket = server.accept
Now that the server is waiting for a new connection, let’s open that connection from a client. Note that this needs to be happening in a separate ruby process. The first parameter is the host address or name of the server. The second is the port on which the server is listening.
- require 'socket'
- client_socket = TCPSocket.new('localhost', '4138')
Now that there is as new connection open the client and server can talk back and forth at will. In this example, the server just echos the clients message back to it. So all together, the Server side looks like this:
- require 'socket'
- server = TCPServer.new('localhost', '4138')
- server_socket = server.accept
- message = server_socket.recvfrom(256)[0]
- server_socket.write("You Said: #{message}")
And the Client side:
- require 'socket'
- client_socket = TCPSocket.new('localhost', '4138')
- print "Enter Message: "
- input = gets
- client_socket.write(input)
- response = client_socket.recvfrom(256)[0]
- puts response
So that’s it, you are communicating between two applications with sockets. If we want the server to continue processing messages, we can loop reading from the socket:
- require 'socket'
- server = TCPServer.new('localhost', '4138')
- server_socket = server.accept
- message = ""
- until message.chomp == "quit" do
- message = server_socket.recvfrom(256)[0]
- server_socket.write("You Said: #{message}")
- end
So far our server can only handle one connection at a time. Often times, you’ll want multiple client to be able to open up connections to the server. To do this, we’ll need to launch a new thread each time a client connects. This is a little class that does that. You can implement your own handler object to handle each socket. The handler only needs a ‘serve’ method that takes a socket. The ThreadGroup is a nice little class to keep track of the threads. When a thread finishes, it is automatically removed from the thread group.
- require 'socket'
- class MultiTcpServer
- def initialize(handler, port)
- @group = ThreadGroup.new
- @handler = handler
- @server = TCPServer.new('0.0.0.0', port)
- end
- def connections_open
- return @group.list.size
- end
- def run
- begin
- loop do
- socket = @server.accept
- @group.add(Thread.new {@handler.serve(socket)})
- end
- rescue IOError
- end
- end
- def stop
- @server.close
- end
- end
Hopefully this little tutorial was helpful. Next time I’ll take a look at sockets in C++ or Java.
#