electric-monk

Thursday, May 19, 2011

Memorable moments in code reading

Reading through other people's code can be tedious. But sometimes you come across a comment that makes it all worthwhile. Thanks to the httplib2 contributor who added this gem.

Monday, April 25, 2011

Creating HTML5 Cache manifests for GWT Apps

I've been working recently on making Springpad work offline using some of HTML5's new features and want to share a solution to a problem I ran into generating the cache manifest file. The cache manifest is a text file containing the version number of your manifest file and the paths of the files on your site that you wish to cache. For more specifics on how to set up an offline application with this file check out Mark Pilgrim's excellent Dive Into HTML5.

That's pretty simple. Generally, when you make a web application you know all of the resource names and locations and can add those to the manifest. Unfortunately, when you are using GWT, the situation is slightly more complicated. GWT compiles javascript files from your Java source code, one per browser platform you are targeting. It names these files by generating a checksum based on the contents of the file. Then it creates a simple javascript file that loads the correct javascript file based on the browser's useragent. So this means that everytime you make a change to your application and recompile, you will need to specify a different javascript file in your cache manifest.

You could do this by hand, but that's tedious and likely to be forgotten at some point. Alternatively, you could do some regex'ing of the bootstrapping file and figure out from that what javascript file to put into the manifest. This is better than doing it by hand, but seems hacky and painful since that javascript will be obfuscated in production.

The solution that we settled on was to implement a custom GWT linker to generate the manifest file. GWT allows you to create your own linkers to either override their linker or to supplement it. Here's the code for the linker which will find the compiled name for the javascript file that we want in our cache manifest and then output a cache manifest will that file in it. For right now, all we care about is the Safari user agent, so that's all that I'm handling. Other browsers also handle offline, so in that case you would want to modify this create a different manifest file for each user agent and then have your server serve the appropriate one based on the user agent in the GET request. I've added comments inline to explain how our version works. Hope this helps.




Tuesday, March 29, 2011

Test Driven Development

At this point, I guess Test Driven Development (TDD) is old news but while I've always liked the idea and have even made preachy statements about unit tests in the past, I've found it difficult in practice to actually write in a test driven way. I don't mean that I don't always test first, but that frequently when I'm in a rush, I test-never. This has come back to bite me enough that I've gradually started writing more tests when it was easy to do.

I recently came across this screencast of Gary Bernhardt using TDD to create a simple string calculator. Gary's velocity is super impressive, but more importantly the video shows how fast TDD can be, especially with a good key mappings to run tests and a split screen.

I watched this at a good time because at Springpad we've recently started a new project all in python. After reading some more about TDD, I've been trying to make a habit of this style of development. So far it's been great. I think the big advantages for me so far have been:

  • Better than a compiler: especially in a dynamic language these are key to make sure you don't have any spelling mistakes or stupid problems. But they're so much better too obviously. Why check that the method exists, when you could check that it behaves as expected before runtime.
  • Staying out of the debugger is fast: Since starting this, I've tried to write enough tests at the right level such that I don't need to debug the program ever. And I've been mostly successful which for me has really sped things up.
  • Deeper understanding of the codebase: Since you spend more time thinking about behavior not only of your code but also of libraries that you use so that you can test it right, you end up knowing the code a lot better. Seems obvious in retrospect, but I didn't start TDD for that reason.

  • I think there's still a lot to figure out with this. Should you use mocks versus stubs? Does a test belong in a separate integration suite versus the unit tests? Etc. So far I haven't created any strong opinions on this, but I'd love to hear anyone's thoughts on how it should be done.

    Friday, October 16, 2009

    Faster Development with JRebel

    Update: In response to the request that I post the problem to forum at Zero Turnaround I was debugging the problem that I had using the intellij run/debug with JRebel buttons some more and found that it was caused by a problem with our code and hibernate. The short version is that there was a String property with getX/setX methods but someone had also added an isX method that returned false if it was null. This usually worked fine, but for some reason when running with JRebel hibernate would get confused and try to set the string value with the boolean from isX() which caused a buried IllegalArgumentException. With that fixed, JRebel works perfectly out of the box. I've changed the post to remove my workaround as it's not necessary any longer.

    Why JRebel?
    I'm going to walk through the steps I took to get JRebel working with maven and Intellij 8 since I ran into a few snags along the way. But first, I should explain why bother install it all. JRebel is a great tool that promises to increase your productivity in Java by enabling all sorts of HotSwaps not normally allowed by the JVM. While you are running your software in debug mode, you can add or remove methods or classes and JRebel will swap these changes into the JVM. No more restarts when you decide to add a new method. JRebel even support making Spring or SpringMVC configuration changes without a restart and it supports plugins so that similar functionality can be added for most tools in the java eco-system. Beyond the obvious time-savings you get from not having to wait for your server to restart, I find it also helps me because I don't have breaks in concentration while I'm waiting for the server to restart. Check out the video from ZeroTurnAround's website for a quick demonstration of how it works.



    My Setup

    I get the feeling that the sticking point for JRebel in terms of adoption is that it can be tricky to configure. They actually provide a really good series of how-tos for different setups but it's hard to cover all of the bases. Most developers at my company use this setup:


    • The build is defined in a Maven build file

    • We debug the application in jetty running it with the maven run-jetty goal

    • We write code in IntelliJ 8 using the maven plugin to generate and update the project file

    • Debugging is done by running the app from IntelliJ using the maven Run configuration



    I tried a few different ways to make this work, and the following setup is what ended up working and being the easiest in terms of development. Much of IntelliJ setup and tips came from here.

    Step 1: Install JRebel

    Download JRebel from their website and install it where ever your prefer. I put mine in /usr/local/java/jrebel

    Step 2: Install the IntelliJ Plugin



    In IntelliJ go to Setting->Plugins, click on the Available tab and right click on the JRebel Plugin and install it. You'll have to restart IntelliJ after this is complete.

    Step 3: Configure JRebel Plugin

    Go to Settings->JRebel in IntelliJ and set JRebel location to where you installed JRebel (e.g., /usr/local/java/jrebel)

    Step 4: Make sure IntelliJ and Maven's output directories are the same



    You need to ensure that IntelliJ and Maven are using the same build directories, otherwise when IntelliJ compiles a changed class it may put into a different directory from where JRebel expects to find it. Go to Project Structure->Modules->Paths and ensure that the output path is the same as what Maven uses when it builds.

    Step 5: Make sure that IntelliJ does not build a WAR

    There's no need for IntelliJ to build a WAR file since jetty-run uses an exploded WAR directory. So building one each time that you compile will just slow things down. Go to Project Structure->Modules click on the Web facet and then and under Java EE Build Settings make sure that "Create Web facet war file" is not checked.

    Step 6: Turn off IntelliJ's hotswapping



    If you don't do this, then everytime that you make a change that the normal JVM cannot hotswap, you will be informed that you've made unsupported changes. It's also a waste of time for it to try and hotswap it. That's why you're installing JRebel. Go to Settings and search for "hotswap". Click "never" for "Reload Classes After Compiliation".

    Step 8 (optional): Remap the Compile command

    I found it helpful to remap the save key (Command-S) to the compile command. So now whenever I make changes all I have to do is hit Command-S and the changes I've made are compiled into the running instance.


    So that's it. Now you can start your application in debug mode. You will see a JRebel startup message in the console immediately. And then you can start adding classes, deleting methods, and when you compile, JRebel will swap it all into the JVM for you... no wait required. It gets you a lot closer to the experience of developing in a dynamic language. Now, if we could only do something about that boilerplate...

    Monday, March 9, 2009

    Better than chicken soup for the soul

    This is the kind of fable that confuses good atheists such as me. A story where it almost seems like the plot is directed by a divine and most assuredly benevolent hand. Switching relious paradigms, it's more likely it was karmic payback for sending me to Iraq... the pat on the back after the kick in the balls. Then again, it was probably just good luck.

    So let me paint the picture for you. I'm in the Q-West dining hall. There are many food options, from main line (comfort food) to fast food to healthy choice or stir fry. I've been eating here since in November and the selection has become rather uninspiring of late. It's likely that I've just eaten there too many times, but it really seems like stopped trying and don't use any spices anymore. Maybe they hired a new executive chef? I'm not sure. But I'm not excited as I walk through the serving area and consider the options.

    And then a moment that might have caused a religious man to say that the lord helps those who help themselves. The Good Lord may not give you a 24 oz. sirloin steak but he may just provide you with what's necessary and with a little good old fashioned Christian elbow grease and ingenuity you could have a feast.

    It happened like this. I approached the healthy food line and saw rice (no surprise there), some shrimp with noodles (sea food in the desert?), stewed tomatos (don't see that often), and asparagus (wait... stewed tomatos?!?!). And then inspiration, the good KBR has provided me with sumptuous rice and stewed tomatos and the fast food line always has hot dogs so.... DAMN RIGHT! I ate hot dog stew for lunch today!

    Now that's what I call chicken soup for the soul.

    Tuesday, December 23, 2008

    Revisited from a previous blog: Letting Go

    My buddy gcole shot me an email pointing to an old blog that I had posted to once and forgotten about. It was funny to read it now almost four years later. It's not embarrassing except for maybe the comparison to an A&F model that I'd probably leave out were I to do it again. More than any of that, it's just really interesting to read it now, a marathon and many assorted miles later. I still have a similar feeling about running now as I did then... I can't be totally away from it for too long for fear of getting too out of shape. But two years of running with Aimee has really matured that impulse and I'm not so in love with the notion of hard core running training or with "great" performance. That said, I run a lot further now then I did back then and it has become a lot more enjoyable. The other thing that I find striking as I read this is the blatant void waiting for climbing to fill it.

    Thursday, April 14, 2005
    Letting Go
    I was a college athelete. For my four years of college, every season was spent in some way preparing for or recovering from track season. At the beginning of the school year was fall track or pre-season. Mostly we ran around the track for various amounts of time and at various speeds. Some of those days I would also lift weights. Then it would snow in Maine and get really cold. Being a sprinter, I would wave good bye to the distance runners as they left for long, cold, snot rocket-filled runs along the roads around Waterville. Meanwhile, we would run around a shorter track for various amounts of time and at various speeds. Occasionally we lifted. Oh and we often would do elaborate warm up drills that involved skipping, hopping, and lunging. These motions were often accompanied by elaborate hand motions. This was indoor track. On saturdays, we ran around the track less then normal, but much faster. Then spring came to Maine and even though there was still snow on the ground, we moved back outside because spring is the time for outdoor track. During this season, we ran around the track, lifted, and accomplished the jumping and hopping warm ups somewhat more gracefully than when we were indoors. On Saturdays, we ran around the track faster than we had on Saturdays during the winter.

    So what's my point?

    My point is that all of this running around in circles has a weird way of becoming habit forming. It's not something that's easy to explain and if you had spoken to me at the end of my senior year, you might not have predicted it at all. At that time I was declaring to anyone who would listen that after graduation I was not going to run farther than the bathroom -- and then only in cases of dire emergencies. It took all of about two weeks for me to break that promise. And it probably would have taken less if I hadn't been so desperately sick after the rampant binge drinking of the week before graduation.

    So why was I addicted? I've had plenty of time to think about it in the five years since. Part of it was probably the look. Sprinting and lifting has a great way of cutting your body fat down to a minimum and since I was already lean it cut me down even more. I was as cut as Abercrombie models -- just not as big or cute, but still its the abs that count, right? That was certainly part of it. Deny it to myself and others as I might, I liked the way I looked.

    Then there's the arrogance angle. I certainly hadn't peaked by the time I graduated. Sprinters don't peak until their late twenties or even early thirties. Of course, most sprinters don't continue to train through their late twenties to early thirties. But nevertheless, I knew that I could only get better and now that I was freed of the ridiculous restrictions of my coaches, the sky was the limit. No more worrying about overtraining or any of that crap. Overtraining is for sissy pansies.

    So left to my own devices, what happened? It wasn't exactly the mechanical 200 meter workouts run at ever increasing speed. Instead, it was surges of motivation when I would run a lot and lift. Lifting was never a huge problem. I just did it. I never got huge, but I stayed in good shape. Running, on the other hand, presented a more difficult problem.

    I was easily caught up in waves of enthusiasm. I would be a fast miler. To be a fast miler, I would run ridiculous amounts of mileage as quickly as possible. I wanted results and I wanted them yesterday. I could easily run ten miles. So I did it. Addicted to the riteous feeling of being an athelete in training, I would run six or seven miles the next day. If it was hard, that was only proof that the training was good. Within a week or two, I would be injured. The giddiness of the images of greatness would be replaced by frustration and impatience. If it wasn't for my knee, I could be running so much faster. Impatience usually led to an early attempt at a comeback - if you can 'comeback' to something that you've only been doing for two weeks consistently.

    You might think that a smart person would recognize the pattern after the first or second time that it happened. In fact, a smart person probably would. I've cycled through that pattern at least six or seven times in the last five years. In the midst of all of this, I became an avid reader of workout books and magazines. From Men's Health to Runner's World; Daniel's Running Formula to The Book of Muscle, I read them all. Imagining the effects that each carefully laid out program would have and debating whether it made sense to get too big from lifting if I really wanted to be running a fast 5K and perhaps even throw in a marathon just for show.

    I demanded of myself that I be on a workout program. If I was going to be spending time working out, I needed to make sure that I was maximizing it. I needed to get the best possible workout effect, build the most muscle possible, and gain as much speed and endurance as I could so that...

    Now let me backtrack for a second. Maybe it makes sense. I wanted to get bigger and faster so that I could compete in races. That's fun, right? There are very few track meets that I ever enjoyed. The races might be fine. But the time leading up the a race was pure torture. It usually began on Friday night, when friends went out and drank themselves into an unthinking stupor like good citizens. During this period, members of the track team usually congregated. It was fun to be with the guys, but sometimes you could feel nerves beginning to show. And by the time, you tried to go to sleep they were in full effect. By Junior year, I was so impatient with the routine that I took Tylenol PM the night before every meet. At breakfast, the food was unappealling and often hard to eat at all. Swallowing almost triggered the gag reflex on a routine basis. And once we had arrived at the meet, being surrounded by the whirl-wind of activity that is a track meet made it much worse. I feared the start of my race and every event that indicated that my event would indeed run and that it was getting closer only intesified those feelings. I was afraid that I would not run well. I was afraid that I would chicken out and not run hard enough. I was afraid that I wouldn't be able to run, because my legs felt completely weakened. All of this introspection led to one thing: self loathing. I hated that I was so nervous. Too inexperienced to realize that everyone gets nervous before major events and there's no way around it, I assumed that it was a character flaw. For a really great explanation of how it feels to waiting for a race read John L. Parker's Once a Runner. Parker's description is amazingly accurate. I get butterflies just reading it.

    So I guess the point of that whole digression was to make the point: no, racing is not particularly fun. Or at least, it wasn't for me in college. So what was I getting ready for? Well, I liked the idea of racing and have done it occassionally, but not regularly. Beyond that I think that I have simply been addicted to the idea of being in shape and of being the athelete.

    Along the way I have ignored so many things. I tried Tae Kwon Doe for several months and enjoyed it. I was even beginning to get good at being a White Belt with a Yellow Stripe. It was fine until I realized that all of this time spent punching and kicking was really taking away from my running. I hadn't been running in forever. I was getting out of shape. I wouldn't be able to...

    I tried yoga once. It was a little new-age for me, but I did enjoy it in spite of myself. I think that it could be a great way to reduce stress, increase flexibility, and just generally feel better. Unfortunately, it couldn't contribute to the bottom line. Would I run faster? Would I be able to lift more? It was cut before it even made the team.

    Worst of all, during these years of working out, I even ignored sports. A lot of people join soccer or basketball leagues to hang out with friends, have a good time, and hey-what-the-heck get a little exercise too. I didn't have the need for extra exercise and couldn't see fitting a workout plus a game into my schedule. So I haven't played too many sports in a while.

    Most recently I have been following the Core Performance program with a co-worker. It's a great program and really addresses a lot of aspects of fitness. If you need to get in good competetive shape or have the time and just feel like getting in great shape, I would definitely recommend it. For me, it's just another in a long string of paper coaches who I have substituted for the living coaches that I followed in college. Ironically, I left school thinking myself free of the tyranny of organized workouts and then quickly sought them out in books and magazines as soon as I was left to my own devices.

    Core performance workouts have left me tired and sore. I feel the same satisfaction that I got five years ago when my hamstring would cramp up after an intense workout. But is all of the time and energy worth it? Exercise is cited as a huge stress reliever, and I believe that it is. But does it really workout that way, when working out is just another stress in my day? Should I rearrange my life to accomodate a demanding workout program?

    Today, I decided no. This week I haven't had a chance to workout. And it felt crappy. At the same time I was thinking a lot about how much working out should impact my life. Tonight around 8:30, I knew that I just needed to go for a run. I opted for a short 2.5 mile run around a pond. I didn't time it. And I didn't concentrate on my pace. I enjoyed the feeling of going fast but didn't feel like I needed to press it further. When I was in sight of my car, I stopped running and walked to it.

    During that run, I resolved to stop being a slave to working out. Exercise is important. But only because it makes you feel good and live better. It's not an end unto itself. I resolved not to be a slave to programs. Just like eating the same food every night for dinner gets boring, so following a single workout program. The only reason to follow such a program is to 'Maximize your Results.' Who cares? I resolve to run when I feel like it, get into pick up basketball games where I can, and learn to surf for the hell of it.

    But most importantly I resolve to ignore those resolutions whenever I feel like it and do what I damn well please.

    Friday, July 11, 2008

    Is Google Making Us Stoopid?: A proof of concept?

    I was in Starbucks today reading about the 1936 Iraqi coup d'etat when an older guy stopped on his way to a nearby table where his daughter was waiting and stared at, I thought, my feet. After a moment's pause, he continued. Then he stopped again and looked back. After a few more beats, he continued to the table. I was self-conciously checking my shoes for unnoticed dog crap or anti-american graffiti or something that would explain a member of the greatest generation's attention. I was drawing a blank and was heading towards an undignified smell-check when he started to say something to his daughter but was interupted by the barista calling him back for his drink. Uncharacterstically patient, I decided to wait for him to come back, hoping he would explain what was wrong with my feet.

    When he did come back, he pointed back towards my table and then asked his daughter if she had seen it. As I shifted my feet underneath my chair to avoid further scrutiny, he told her that it was article about whether google was making us stupid. I had the Atlantic on my table and the cover article this month is Nicholas Carr's Is Google Making Us Stoopid? which is followed in smaller print by What the Internet is doing to our brains. It's a well-written and interesting article that voices the author's concerns about the effects of internet usage on the way that we think, particularly in terms of our ability to focus on topics for long periods of time and think deeply about ideas. Mr. Carr worries that the pre-dominance of quick one to two paragraph articles and blog entries have made us incapable of reading longer form work, preferring instead to scan a few paragraphs for information. He means not only that we are no longer able to read books like Gravity's Rainbow (which is a problem I can attest to) but are also incapable of reading longer form articles, ironic, I thought, to deliver such a message in an article weighing in at just over five pages. While I thought the argument was mostly alarmist and even Mr. Carr, himself, admits that he could just be a modern version of those who decried the printing press, I think there is some basis for his concern that is for me best illustrated by the state of cable news and the decline of the newspaper.

    I had to wonder though, as the man after explaining the title of an article of which he probably had never even noticed the subtext, went on to argue that the article was baseless. "Does the encyclopedia make me stupid?", he countered.