<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Daveblog5000</title>
 <link href="http://www.naildrivin5.com/blog/atom.xml" rel="self"/>
 <link href="http://www.naildrivin5.com/blog/"/>
 <updated>2011-10-25T22:26:10-04:00</updated>
 <id>http://www.naildrivin5.com/blog</id>
 <author>
   <name>Dave Copeland</name>
   <email>davec@naildrivin5.com</email>
 </author>

 
 <entry>
   <title>My Book's in Beta!</title>
   <link href="http://www.naildrivin5.com/blog/2011/10/25/awesome-command-line-apps-in-ruby-in-beta.html"/>
   <updated>2011-10-25T00:00:00-04:00</updated>
   <id>http://www.naildrivin5.com/blog/2011/10/25/awesome-command-line-apps-in-ruby-in-beta</id>
   <content type="html">&lt;a href='http://www.awesomecommandlineapps.com/'&gt;&lt;img src='http://imagery.pragprog.com/products/249/dccar_xlargebeta.jpg?1319573406' /&gt;&lt;/a&gt;
&lt;h3 id='build_awesome_commandline_applications_in_ruby'&gt;Build Awesome Command-Line Applications in Ruby&lt;/h3&gt;

&lt;h4 id='control_your_computer_simplify_your_life'&gt;Control your Computer, Simplify your Life&lt;/h4&gt;

&lt;p&gt;Woot!&lt;/p&gt;

&lt;p&gt;&lt;a href='http://www.awesomecommandlineapps.com/'&gt;My Book&lt;/a&gt; is in Beta! Whoohoo! It&amp;#8217;s all about writing amazing command-line apps in Ruby. This isn&amp;#8217;t about hacking together UNIX commands, or bash scripting…this is about making apps that are easy to learn, easy to use, easy to write, and that will delight their users. Seriously, stop making crappy command-line scripts, read my book, and start kicking ass.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s been a &lt;strong&gt;long&lt;/strong&gt; time coming. Please stop now, and go &lt;a href='http://www.awesomecommandlineapps.com/'&gt;check it out&lt;/a&gt;. I started this almost a year ago during &lt;a href='http://forums.pragprog.com/forums/190'&gt;PragProWriMo&lt;/a&gt;, where I wrote (almost) every single day in November of 2010. When I saw that &lt;a href='http://www.travisswicegood.com/'&gt;Travis Swicegood&lt;/a&gt; (one of the few who made it all the way through) had gotten his manuscript accepted, I cleaned up a chapter and submitted and the &lt;a href='http://www.pragprog.com'&gt;Prags&lt;/a&gt; accepted!&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve spent my time since then writing, re-writing, re-organizing, and working hard to get this thing done. It&amp;#8217;s in beta, meaning that you can buy the e-book and read the work in progress. It&amp;#8217;s &lt;em&gt;almost&lt;/em&gt; complete, just a few chapters to go, and by reading it in beta, you can give me valuable feedback to make the book even better.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://www.awesomecommandlineapps.com/'&gt;Check it out&lt;/a&gt; now!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>DC's New 52 Review</title>
   <link href="http://www.naildrivin5.com/blog/2011/10/21/new-52-review.html"/>
   <updated>2011-10-21T00:00:00-04:00</updated>
   <id>http://www.naildrivin5.com/blog/2011/10/21/new-52-review</id>
   <content type="html">&lt;img src='http://dcu.blog.dccomics.com/files/2011/07/Justice-League-12-150x150.jpg' /&gt;
&lt;p&gt;I&amp;#8217;ve always liked superhero stuff, but was never into comics as a kid. Reading Wikipedia &lt;a href='http://en.wikipedia.org/wiki/Flashpoint_(comics)'&gt;summaries&lt;/a&gt; of the &lt;a href='http://en.wikipedia.org/wiki/Infinite_Crisis'&gt;insanity&lt;/a&gt; that is the DC universe&amp;#8217;s continuity makes me never want to touch the stuff. Now, it seems, they&amp;#8217;ve thrown all of that out and started things fresh. Though it&amp;#8217;s not a reboot. Whatever.&lt;/p&gt;

&lt;p&gt;Having zero desire to locate, much less visit, my local comics store, the awesome &lt;a href='http://www.comixology.com/'&gt;Comixology&lt;/a&gt; app is my gateway to nerdom. I&amp;#8217;ve used it to read a few short-run titles like Kick-Ass and Wanted, and they carry the DC titles. &lt;strong&gt;And&lt;/strong&gt;, the New 52 titles are being released digitally at the same time as they are in print. Awesome. Nothing more annoying than downloading some 5 year old comic that just abruptly ends because they didn&amp;#8217;t feel like digitizing all of it.&lt;/p&gt;

&lt;p&gt;Based on what I know about the characters, and a few recommendations, I got the #1&amp;#8217;s for several of the new titles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Action Comics&lt;/em&gt; - Superman&amp;#8217;s young and pissed, and Lex Luthor is out to get him. Love this one. And, I&amp;#8217;m cool with his costume being jeans and a T-shirt.&lt;/li&gt;

&lt;li&gt;&lt;em&gt;All Star Western&lt;/em&gt; - Jonah Hex is a kick-ass dude in 1800s Gotham City. I like the vibe, but the story seemed a bit formulaic, and I&amp;#8217;m not sure I care about yet another grumpy badass character. I&amp;#8217;ll read #2 and see if it picks up.&lt;/li&gt;

&lt;li&gt;&lt;em&gt;Batman&lt;/em&gt; - YES. So very good. The first two issues deal with some shadowy assasins coming to Gotham and Batman is ready to kick some serious ass.&lt;/li&gt;

&lt;li&gt;&lt;em&gt;Batwoman&lt;/em&gt; - No clue who or what Batwoman is supposed to be. I bought the first two issues based on a recommendation and I probably won&amp;#8217;t continue. Story is kinda boring and the character just doesn&amp;#8217;t interest me. Plus, it seems the bad guys are stupid supernatural demons or something, and I just hate that stuff.&lt;/li&gt;

&lt;li&gt;&lt;em&gt;Catwoman&lt;/em&gt; - Dumb fun. This one&amp;#8217;s been getting flak for it&amp;#8217;s overt sexuality, but I love the idea of a character who&amp;#8217;s in it for herself and not trying to be a hero. The scene in the second issue with Bruce acting like a drunken idiot while watching Selina&amp;#8217;s every move is awesome. Definitely keep reading this one.&lt;/li&gt;

&lt;li&gt;&lt;em&gt;Detective Comics&lt;/em&gt; - I dont even remember what this one&amp;#8217;s about. Batman plus blood-n-guts. I dunno. Wasn&amp;#8217;t really into it, and &lt;em&gt;Batman&lt;/em&gt; is just way better so far.&lt;/li&gt;

&lt;li&gt;&lt;em&gt;Justice League&lt;/em&gt; - Love it. The League hasn&amp;#8217;t formed, no one knows each other &lt;em&gt;or&lt;/em&gt; trusts each other and the government&amp;#8217;s out to get all the heros. And Darkseid is sending bombs and dudes to Earth. Green Lantern: &amp;#8220;You&amp;#8217;re not just some guy in a bat costume are you?&amp;#8221;. Ha!&lt;/li&gt;

&lt;li&gt;&lt;em&gt;Wonder Woman&lt;/em&gt; - REALLY boring. No idea what the story is, but there&amp;#8217;s centaurs and Zeus and other boring shit I can&amp;#8217;t stand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rest of the new 52 titles don&amp;#8217;t look super interesting to me; I think a lot of the Justice League characters are kinda boring on their own, with Superman and Batman being the exception. The other &amp;#8220;Bat family&amp;#8221; titles look OK, but I&amp;#8217;m pretty happy with what I&amp;#8217;ve got for the time being.&lt;/p&gt;

&lt;p&gt;The only thing I don&amp;#8217;t get how all this fits together; Batman&amp;#8217;s in three of the titles I&amp;#8217;m reading, and so is it the same guy at different points, or totally different stories that are timeless or what? Ah well.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Curation FTW and the End of References</title>
   <link href="http://www.naildrivin5.com/blog/2011/08/07/end-of-reference-curation-ftw.html"/>
   <updated>2011-08-07T00:00:00-04:00</updated>
   <id>http://www.naildrivin5.com/blog/2011/08/07/end-of-reference-curation-ftw</id>
   <content type="html">&lt;p&gt;Museums aren&amp;#8217;t the only things curated anymore - now, everything is!&lt;/p&gt;

&lt;p&gt;If there were a &amp;#8220;trending word&amp;#8221; of the decade leading up to this one, it would be &amp;#8220;curated&amp;#8221;. Although I&amp;#8217;d heard the word before its launch, the &lt;a href='http://itunes.apple.com/en/genre/mobile-software-applications/id36?mt=8'&gt;iOS App Store&lt;/a&gt; certainly brought it to the forefront of everyone interested in technology.&lt;/p&gt;

&lt;p&gt;However, it&amp;#8217;s a concept that&amp;#8217;s been around forever. I posted this picture on &lt;a href='http://instagr.am/'&gt;Instagram&lt;/a&gt; a few months ago titled &amp;#8220;A study in usability&amp;#8221;:&lt;/p&gt;
&lt;img src='/images/bar_aid.jpg' /&gt;
&lt;p&gt;This is a device my wife got from her dad that allows you to &amp;#8220;look up&amp;#8221; the recipe for about 80 different cocktails. You find the one you want on the front, and turn a dial, which reveals the recipe in the small window in the center. Old school and retro, it adds some nostalgia to our home bar setup.&lt;/p&gt;

&lt;p&gt;Compare this to a book of cocktail recipes I&amp;#8217;ve had for quite sometime:&lt;/p&gt;
&lt;img src='http://ecx.images-amazon.com/images/I/51cBoKhQN2L._BO2,204,203,35,-76_AA300_SH20_OU01_.jpg' /&gt;
&lt;p&gt;It has hundreds, if not &lt;strong&gt;thousands&lt;/strong&gt; of cocktail recipes. It is, in every way, far superior to the Bar Aid, right? It has more recipes, it has several indeces, and it has plenty of space to describe how to make the cocktail in question.&lt;/p&gt;

&lt;p&gt;The Bar Aid is actualy &lt;em&gt;much&lt;/em&gt; more usable, and gets a lot more use when I&amp;#8217;m at the bar. Why?&lt;/p&gt;

&lt;p&gt;Curation.&lt;/p&gt;

&lt;p&gt;The Bar Aid is, for all intents and purposes, a &lt;em&gt;curated&lt;/em&gt; list of cocktails. It&amp;#8217;s not only a list of 80 popular and common cocktails, but it&amp;#8217;s also a list of 80 cocktails whose recipe fits in a 5&amp;#8221;x1&amp;#8221; window. Common and simple. It has never steered me wrong.&lt;/p&gt;

&lt;p&gt;What if I want a cocktail not on the list, or if I have a strange ingredient and want to see what cocktails I can make with it? Do I reach for the &amp;#8220;Ultimate A-Z Bar Guide&amp;#8221;? Not often. I usually reach for the Internet (yes &lt;a href='/blog/2011/08/01/why-i-wont-work-for-google-twitter-facebook.html'&gt;Google&lt;/a&gt;). The &lt;em&gt;Internet&lt;/em&gt; is my new reference guide. It has &lt;strong&gt;more&lt;/strong&gt; information and choices than any reference I have at home, and is &lt;em&gt;infinitely&lt;/em&gt; searchable.&lt;/p&gt;

&lt;p&gt;In this modern age we live in, references, like the A-Z Guide, are useless when compared to the Internet. They&amp;#8217;re also useless compared to curated material like the Bar Aid. When I want to look up a &amp;#8220;good cocktail&amp;#8221;, I can quickly flip through the Bar Aid and find something easy to make. When I need something more involved, I&amp;#8217;ll hit Google.&lt;/p&gt;

&lt;p&gt;I find this fascinating and I think it&amp;#8217;s a big problem for creators of reference materials of any kind. I don&amp;#8217;t need 100 of Gordon Ramsay&amp;#8217;s best dishes, I need his 20 best starters. I don&amp;#8217;t want to know how Roger Ebert rated every movie of the last century, but I&amp;#8217;d love to know his 10 best straight-to-video releases.&lt;/p&gt;

&lt;p&gt;I think this is a &lt;em&gt;great&lt;/em&gt; way for those knowledgable on something to spread that knowledge and create interest in their field. Focused, curated information is going to continue to be important. It&amp;#8217;s just too hard to search the Internet when you only want &amp;#8220;something good&amp;#8221;, and a reference book is too limiting when you want to hunt down something specific.&lt;/p&gt;

&lt;p&gt;Since I&amp;#8217;m a huge nerd who recently spent a few hours in &lt;a href='http://groundkontrol.com/'&gt;Ground Kontrol&lt;/a&gt;, I&amp;#8217;ll leave you with my curated list of 80s video games that are the easiest and most fun to play:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Centipede&lt;/strong&gt; - fast, great sound FX, lots of shooting&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Frogger&lt;/strong&gt; - great music, colorful, easy to grok, hard to master&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Ms. Pac Man&lt;/strong&gt; - AMAZING sound, nonviolent, rewarding&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Star Wars (the vector one)&lt;/strong&gt; - vector graphics are so great, sound design and music is wonderful, and the controls are natural and fun&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Super Sprint&lt;/strong&gt; - fast-paced car racing that&amp;#8217;s &lt;em&gt;just&lt;/em&gt; realistic enough to be challenging, but not so much that you&amp;#8217;re bored&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Tempest&lt;/strong&gt; - abstract vector graphics and premise; just shoot things with satisfying sound effects&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Tron&lt;/strong&gt; - four awesome games in one; you get to &lt;em&gt;be&lt;/em&gt; the light cycle, fight tanks, and kill that pesky MCP.&lt;/li&gt;
&lt;/ul&gt;</content>
 </entry>
 
 <entry>
   <title>Why I'd never work for Google, Twitter, or Facebook</title>
   <link href="http://www.naildrivin5.com/blog/2011/08/01/why-i-wont-work-for-google-twitter-facebook.html"/>
   <updated>2011-08-01T00:00:00-04:00</updated>
   <id>http://www.naildrivin5.com/blog/2011/08/01/why-i-wont-work-for-google-twitter-facebook</id>
   <content type="html">&lt;p&gt;Just got back from OSCON 2011. There were some really interesting talks, and “the big three” were all over the place: Google, Twitter, and Facebook. I attended the &lt;a href='http://www.oscon.com/oscon2011/public/schedule/detail/20528'&gt;Twitter talk&lt;/a&gt; on how they moved from Ruby to the JVM, as well a talk by Rob Pike (of Google) on &lt;a href='http://www.oscon.com/oscon2011/public/schedule/detail/18653'&gt;Go&lt;/a&gt;. I use Twitter and Google a &lt;em&gt;lot&lt;/em&gt;, and enjoyed hearing about how they work (Facebook, on the other hand, I use begrudgingly).&lt;/p&gt;

&lt;p&gt;My first reaction to these talks was “Wow, it sure sounds like a lot of fun to work at these places!” From inventing programming languages to using Scala to scale a massive architecture, it sounds like developer shangri-la. Until recently, I was slinging &lt;a href='/blog/2010/01/09/Top-5-Omissions-From-Spring-MVC.html'&gt;Spring MVC&lt;/a&gt; code in vanilla Java. Sucks for me, right?&lt;/p&gt;

&lt;p&gt;This is lazy thinking, and I haven&amp;#8217;t fallen victim to it in quite a while. Ask yourself: “Why would Google spend the time and money to get Rob Pike to work for them and invent an entirely new programming language?” Ask: “Why would Twitter spend the time and money to design and deploy an elegant, scalable architecture using the JVM and Scala?”&lt;/p&gt;

&lt;p&gt;An awesome new programming language, or an impressive, scalable architecture is not an end to itself. These are tools that serve some other purpose.&lt;/p&gt;

&lt;p&gt;In the case of Google, Twitter, and Facebook, that purpose is to serve ads.&lt;/p&gt;

&lt;p&gt;Although &lt;a href='http://www.youtube.com/watch?v=vKmQW_Nkfk8'&gt;Steve Yegge&amp;#8217;s&lt;/a&gt; keynote features him “quitting” his project at Google (which he describes as “sharing cat pictures”) to work on some higher calling (still within Google), he&amp;#8217;s just trading one ad-serving system for another.&lt;/p&gt;

&lt;p&gt;Google+ isn&amp;#8217;t about sharing cat pictures, it&amp;#8217;s about serving ads. Twitter&amp;#8217;s massive network of 140-character bits of information isn&amp;#8217;t about connecting people across the globe or to view current trends in worldwide thinking, it&amp;#8217;s about serving ads. Facebook isn&amp;#8217;t about entertaining yourself with games or sharing interesting links, it&amp;#8217;s about serving ads.&lt;/p&gt;

&lt;p&gt;So, why are the best and brightest in the industry busting their asses to work at these places? If all you care about is watching performance metrics increase, or playing with something new, or just watching lots of tests pass, I guess it&amp;#8217;s nice to get paid well. But, how can this be truly fulfilling? For me, it wouldn&amp;#8217;t be. I need the tools I&amp;#8217;m building, the products I work on, and the architecture I&amp;#8217;m helping to create to all serve something I&amp;#8217;m interested in.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m not saying that my code needs to save the world or support humanitarian causes, but it should at least be something that &lt;em&gt;I&lt;/em&gt; like, or &lt;em&gt;I&lt;/em&gt; would use, or that &lt;em&gt;I&lt;/em&gt; care about.&lt;/p&gt;

&lt;p&gt;And I can&amp;#8217;t fucking abide advertisements. Honestly, I don&amp;#8217;t know anyone who does. Except, apparently, a lot of really smart software engineers.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>I spent a dollar on something that's free</title>
   <link href="http://www.naildrivin5.com/blog/2011/04/28/I-spent-a-dollar.html"/>
   <updated>2011-04-28T00:00:00-04:00</updated>
   <id>http://www.naildrivin5.com/blog/2011/04/28/I-spent-a-dollar</id>
   <content type="html">&lt;p&gt;Co-worker sent out an email today, letting everyone know about a handy Mac app called &lt;a href='http://code.google.com/p/cdto/'&gt;cdto&lt;/a&gt;. You drag it to Finder and, if you click it, it will open a Terminal window where the current working directory is the folder you&amp;#8217;re viewing in Finder. Pretty handy.&lt;/p&gt;

&lt;p&gt;I click the link and get to a Google Code page, with a link to a zip. Then, I thought, maybe the developer is being nice and has put it in the App Store; that way, I can install it here with one click, and install it at home with one click.&lt;/p&gt;

&lt;p&gt;Nope.&lt;/p&gt;

&lt;p&gt;But, &lt;em&gt;another&lt;/em&gt; developer has created a similar app called &lt;a href='http://inscopeapps.com/#shellto'&gt;ShellTo&lt;/a&gt;. The icon is similar, and it does exactly the same thing. However, it&amp;#8217;s 99 cents.&lt;/p&gt;

&lt;p&gt;Now, I have a bit of a dilemma. Do I download cdto, find the expanded folder (called “cdto dist”) in my Downloads folder, search that for the executable (there were several directories, only one having the app), drag it to the Applications folder and then repeat the process (which I can make &lt;em&gt;slightly&lt;/em&gt; faster via Dropbox) at home?&lt;/p&gt;

&lt;p&gt;Or, do I pay a buck to have this done instantly and painlessly?&lt;/p&gt;

&lt;p&gt;I paid the buck.&lt;/p&gt;

&lt;p&gt;If you could pay a dollar for 5 minutes of your time back, would you?&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Hyperscheduling - How I find time to do things I hate</title>
   <link href="http://www.naildrivin5.com/blog/2011/04/06/hyperscheduling.html"/>
   <updated>2011-04-06T00:00:00-04:00</updated>
   <id>http://www.naildrivin5.com/blog/2011/04/06/hyperscheduling</id>
   <content type="html">&lt;blockquote&gt;
&lt;p&gt;You don&amp;#8217;t need schedule time to play video games - Merlin Mann&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href='http://www.kungfugrippe.com/'&gt;Merlin Mann&lt;/a&gt; has said this more than a few times on his great &lt;a href='http://5by5.tv/b2w'&gt;podcast&lt;/a&gt; with &lt;a href='http://twitter.com/danbenjamin'&gt;Dan Benjamin&lt;/a&gt;, and it really strikes a chord with me. Not that I play video games (I don&amp;#8217;t), but the underyling message really speaks to me: “you don&amp;#8217;t need to schedule time to do things you &lt;em&gt;really&lt;/em&gt; want to do.”&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s true; I don&amp;#8217;t have any problem finding time throughout the week to work on my book, or hack on &lt;a href='http://github.com/davetron5000/gli'&gt;open source&lt;/a&gt; stuff, or have a great meal with my lovely &lt;a href='http://twitter.com/amymaura'&gt;fiancé&lt;/a&gt;. What I &lt;em&gt;do&lt;/em&gt; have a problem finding time for are the things I hate doing, but that I feel, intellecutally, that I &lt;em&gt;should&lt;/em&gt; be doing.&lt;/p&gt;

&lt;p&gt;Given that, in less than two months, I&amp;#8217;ll be on a beach in Puerto Rico, getting married, and having my picture taken, I started to get worried. I&amp;#8217;m not obese, but I&amp;#8217;m far from a healthy weight, and I lead a mostly sedentary lifestyle. I also rarely eat breakfast, leading me to just devour massive amounts of food at lunchtime.&lt;/p&gt;

&lt;p&gt;About once a month, I&amp;#8217;ll “buckle down” and make breakfast about twice, and make it to the gym a few times, and the back to normal.&lt;/p&gt;

&lt;p&gt;Not this time. Other than a life-long partner, the &lt;em&gt;other&lt;/em&gt; thing from a wedding that lasts are the pictures. And, if I can&amp;#8217;t get myself in some semblance of shape for &lt;em&gt;that&lt;/em&gt;, well…I just can&amp;#8217;t do it. And I hate not being able to do things.&lt;/p&gt;

&lt;h2 id='doing_the_things_i_hate'&gt;Doing the things I hate&lt;/h2&gt;

&lt;p&gt;My problem was this constant feeling of “not enough time in the day.” We seem to have solved this problem &lt;a href='http://www.heyitsopower.com'&gt;at work&lt;/a&gt;, and that&amp;#8217;s &lt;em&gt;way&lt;/em&gt; more complex than my life.&lt;/p&gt;

&lt;p&gt;So, I started with a completely empty day, and started to carve things out, one by one.&lt;/p&gt;

&lt;p&gt;I wanted to leave work at 6pm every day. That means getting there by 9:30am. And if I want to go to the gym, I&amp;#8217;d need to be &lt;em&gt;done&lt;/em&gt; working out by 9:00am. I worked all the way through everything I&amp;#8217;d need to do, including making breakfast and packing my bag the night before.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/hyperschedule.png' alt='My Hyperschedule' /&gt;&lt;/p&gt;

&lt;p&gt;As you can see, I&amp;#8217;ve scheduled things down to the minute: I get up at 6:50, start making breakfast by 7, and clean it all up in time to leave for the gym by 7:35. I set each of these to loudly alarm on my iPhone, so I keep the right pace.&lt;/p&gt;

&lt;p&gt;And yes, I also planned when to eat lunch and what to have (I eat at one of the same three restaurants every day anyway, why bother having to make the decision?).&lt;/p&gt;

&lt;h2 id='does_it_work'&gt;Does it work?&lt;/h2&gt;

&lt;p&gt;So far, it has &lt;em&gt;totally&lt;/em&gt; worked. I&amp;#8217;ve &lt;em&gt;never, ever&lt;/em&gt; in my life made it to the gym more than twice in one week. EVER. The first three weeks, I made it 4 times each week, and did 30 minutes of cardio, plus stretches, weights, etc. I was also in bed by 11:00 each night, with my bag packed and ready to go.&lt;/p&gt;

&lt;p&gt;And then I got food poisoning, forcing an entire week of &lt;em&gt;not&lt;/em&gt; following this schedule.&lt;/p&gt;

&lt;p&gt;I was really worried I&amp;#8217;d lost all my momentum, that maybe the “newness” of this technique would wear off.&lt;/p&gt;

&lt;h3 id='i_started_right_back_up'&gt;I started right back up&lt;/h3&gt;

&lt;p&gt;Not a problem; started back into my routine with no problems at all. Now, I&amp;#8217;m not tracking calories, weight, or anything (this can&amp;#8217;t be about manipulating metrics, it has to be about establishing a healthy routine), but so far, I think this has the highest chance of working its way into my life.&lt;/p&gt;

&lt;h2 id='why_does_this_work'&gt;Why does this work?&lt;/h2&gt;

&lt;p&gt;When I&amp;#8217;d make it to the gym, I&amp;#8217;d feel rushed. “Shit, I have to hurry, so I can get to work in time to put in the right hours so I can get home and then do fun stuff!” “I won&amp;#8217;t go to the gym, because I overslept and I won&amp;#8217;t get a proper workout, so why bother?” The excuses went on and on.&lt;/p&gt;

&lt;p&gt;Now that everything&amp;#8217;s scheduled, I&amp;#8217;m not rushed. I never worry that I&amp;#8217;ll miss out on anything, because all of my “chores” are accounted for: getting up in time to make a proper breakfast, getting to the gym in time to get a proper work out, getting to work in time to put in my hours &lt;em&gt;and&lt;/em&gt; leave at a reasonable hour, etc.&lt;/p&gt;

&lt;p&gt;Getting ready the night before is also crucial: it reduces friction for the next day, and also represents a commitment to myself. If I&amp;#8217;ve already gone to the trouble of packing up my clothes and stuff for the gym, when I&amp;#8217;m groggy the next morning, trying to convince myself to sleep more, I think about that bag: “Well, I&amp;#8217;m actually all ready, so I might as well actually go.”&lt;/p&gt;

&lt;h3 id='what_about_scheduling_free_time'&gt;What about scheduling “free time?”&lt;/h3&gt;

&lt;p&gt;I decided to explicitly &lt;em&gt;not&lt;/em&gt; schedule “free” activities. There&amp;#8217;s nothing on my calendar that says “work on book” or “make dinner” or “watch TV with fiancé.” As Merlin says, these don&amp;#8217;t &lt;em&gt;need&lt;/em&gt; to be scheduled, and, honestly, free time doesn&amp;#8217;t feel free when the iPhone alarams are going off.&lt;/p&gt;

&lt;h2 id='whats_next'&gt;What&amp;#8217;s next?&lt;/h2&gt;

&lt;p&gt;Keep doing it and hope my wedding pictures turn out great! I&amp;#8217;ll report back after the honeymoon with the results!&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Why not use bash?</title>
   <link href="http://www.naildrivin5.com/blog/2011/04/02/why-not-use-bash.html"/>
   <updated>2011-04-02T00:00:00-04:00</updated>
   <id>http://www.naildrivin5.com/blog/2011/04/02/why-not-use-bash</id>
   <content type="html">&lt;p&gt;At &lt;a href='http://www.rubynation.org'&gt;RubyNation&lt;/a&gt;, I gave a talk on &lt;a href='http://awesome-cli-ruby.heroku.com'&gt;Making Awesome Command Line Applications in Ruby&lt;/a&gt;, which I&amp;#8217;ve done a few times, and is what led to my currently-in-progress book on the subject.&lt;/p&gt;

&lt;p&gt;One of the assertions I added to the talk, based on my work on the book is the specific advice to not start off in bash…use Ruby. This was questioned by a member of the audience (who I realized later was &lt;a href='http://twitter.com/bmizerany'&gt;Blake Mizerany&lt;/a&gt; of Heroku/Sinatra fame, i.e. someone far more knowledgable than me about CLI apps, Ruby, and shell programming).&lt;/p&gt;

&lt;p&gt;My answer was about as eloquent as a middle-school debate team closing argument and amounted to “Me hate bash.”&lt;/p&gt;

&lt;p&gt;Although I &lt;em&gt;do&lt;/em&gt; dislike shell programming, it&amp;#8217;s not exactly fair of me to transfer my personal preferences into solid “advice,” nor is it fair to imply that shell programming is a lame or worthless skill; it&amp;#8217;s certainly not.&lt;/p&gt;

&lt;p&gt;So, I thought about it a bit more and I have a &lt;em&gt;real&lt;/em&gt; answer to the question “Why use Ruby instead of shell?”&lt;/p&gt;

&lt;p&gt;Blake made the point that one of my examples (in Ruby) would&amp;#8217;ve been very trivial in shell, and further that issues I was discussing could be easily avoided by simply better-wielding the shell. His preference was to convert to Ruby only when things got complicated.&lt;/p&gt;

&lt;p&gt;I would generally agree, for some definition of “when things get complicated.”&lt;/p&gt;

&lt;p&gt;For me, things get complicated in shell &lt;em&gt;very&lt;/em&gt; quickly…I&amp;#8217;m just not a shell expert and likely won&amp;#8217;t ever be. A lot of developers aren&amp;#8217;t shell experts, and are not going to be able to use the shell programming language &lt;em&gt;nearly&lt;/em&gt; as effectively as they could Ruby.&lt;/p&gt;

&lt;p&gt;So, rather than write &lt;em&gt;bad&lt;/em&gt; shell code and then port to Ruby later (once you&amp;#8217;ve made a mess), my advice, assuming you aren&amp;#8217;t a shell expert and aren&amp;#8217;t looking to become one, is to just start off with Ruby.&lt;/p&gt;

&lt;p&gt;I say this because the average developer is much more likely to be able to write clean &amp;amp; idiomatic Ruby code than to write similarly idiomatic shell code.&lt;/p&gt;

&lt;p&gt;That said, I probably should become &lt;em&gt;more&lt;/em&gt; of an expert on shell programming and would love some resources if anyone has any.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>One Week of using my iPad for personal stuff at work</title>
   <link href="http://www.naildrivin5.com/blog/2011/01/10/2010-one-weed-of-ipad.html"/>
   <updated>2011-01-10T00:00:00-05:00</updated>
   <id>http://www.naildrivin5.com/blog/2011/01/10/2010-one-weed-of-ipad</id>
   <content type="html">&lt;p&gt;On Jan 3, I &lt;a href='http://twitter.com/#!/davetron5000/status/21943399506509824'&gt;tweeted&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;All personal stuff only on iPad; no twitter, email, or RSS on work computer. Will it keep me more focused?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Essentially, what I decided to try doing was to bring my iPad to work every day, and use it for Twitter, RSS, and personal emails. The only &amp;#8220;personal&amp;#8221; stuff I would be doing on my work machine would be IM, simply because the IM experience on iPad is not very good, and the immediacy of it would be lost on a computer that&amp;#8217;s not right in front of me. I don&amp;#8217;t do a lot of personal IM&amp;#8217;ing anyway, so this seemed like a good compromise.&lt;/p&gt;

&lt;h2 id='why'&gt;Why?&lt;/h2&gt;

&lt;p&gt;Normally, I get all kinds of notifications on my machine: new emails, new stories in RSS, new tweets, etc. This divides my focus. I&amp;#8217;ll spend upwards of five minutes reading mail or blogs while waiting for a &lt;em&gt;two&lt;/em&gt; minute test run to complete. Not good. It&amp;#8217;s hard enough to focus where I work as it is, so I thought this would help. Further, when I &lt;em&gt;do&lt;/em&gt; take a break and focus on RSS or personal email, I&amp;#8217;m bombarded with work-related things&amp;#8230;the very things I&amp;#8217;m trying to take a break from!&lt;/p&gt;

&lt;h2 id='how_did_it_go'&gt;How did it go?&lt;/h2&gt;

&lt;p&gt;In a word: &amp;#8220;smashing.&amp;#8221;&lt;/p&gt;

&lt;p&gt;I tended to keep Twitter for iPad running, as that&amp;#8217;s pretty easy to duck in and out of. &lt;em&gt;Any&lt;/em&gt; interesting link, I sent right to &lt;a href='http://www.instapaper.com/'&gt;Instapaper&lt;/a&gt; for reading on the train home. I only read RSS feeds a couple times a day, usually during lunch, and during the dreaded 3pm doldrums where I just start fading and need a break.&lt;/p&gt;

&lt;p&gt;I got to most personal emails I would normally deal with, however, because of the iPad&amp;#8217;s virtual keyboard, I pushed off dealing with emails that required a bit more writing. This turns out to be a good thing, because most of the time these sorts of emails can just wait until I get home.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m going to keep it going as long as I can; I think it&amp;#8217;s going to be a great way to maintain focus without just ditching the handy notification systems that are useful throughout the day. When I&amp;#8217;m working, I&amp;#8217;m not thinking about personal email or what&amp;#8217;s been posted to Daring Fireball. When I&amp;#8217;m taking a break, I&amp;#8217;m just dealing with email, taking in blog entries and &lt;em&gt;actually&lt;/em&gt; recharging for the next block of work.&lt;/p&gt;

&lt;p&gt;I &lt;em&gt;don&amp;#8217;t&lt;/em&gt; think this would be possible on just a phone; the iPad provides a near-to-a-real-computer enough experience that I can do just about everything I need to on it.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>2010 in review; what's next for me in 2011</title>
   <link href="http://www.naildrivin5.com/blog/2011/01/01/2010-whats-next.html"/>
   <updated>2011-01-01T00:00:00-05:00</updated>
   <id>http://www.naildrivin5.com/blog/2011/01/01/2010-whats-next</id>
   <content type="html">&lt;p&gt;Yesterday, while waiting for guests to arrive at my mostly-annual New Year&amp;#8217;s Eve party, I found a txt file I created called &lt;code&gt;2010_goals.txt&lt;/code&gt;. It&amp;#8217;s contents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;speak at at least one more user&amp;#8217;s group&lt;/li&gt;

&lt;li&gt;speak at some sort of conference&lt;/li&gt;

&lt;li&gt;deploy an App to the iPhone App Store&lt;/li&gt;

&lt;li&gt;Deploy a Rails 2 app to Heroku&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I had totally forgotten about this, although I accomplished almost everything on that list. This year, I spoke at &lt;a href='http://www.meetup.com/dcruby/'&gt;DCRUG&lt;/a&gt; twice, &lt;a href='http://www.novajug.org/'&gt;NOVAJUG&lt;/a&gt; once, and &lt;a href='http://naildrivin5.com/blog/2010/04/30/my-talk-at-scala-days.html'&gt;spoke at ScalaDays&lt;/a&gt; 2010 in Switzerland (and was subsequently trapped by that &lt;a href='http://en.wikipedia.org/wiki/Eyjafjallaj%C3%B6kull'&gt;stupid volcano&lt;/a&gt;) as well as &lt;a href='http://www.lonestarrubyconf.com/'&gt;Lone Star Ruby Conf&lt;/a&gt; in Austin. While I still haven&amp;#8217;t quite submitted &lt;a href='http://naildrivin5.com/blog/2010/07/18/iphone-app-part-5.html'&gt;my iPhone app&lt;/a&gt; to the app store, I &lt;em&gt;did&lt;/em&gt; deploy a Rails &lt;em&gt;three&lt;/em&gt; app to heroku, namely my Rails Rumble &amp;#8216;10 entry &lt;a href='http://carltherobot.heroku.com'&gt;Carl The Robot&lt;/a&gt;. On top of all that, I successfully completed &lt;a href='http://forums.pragprog.com/forums/190'&gt;PragProWriMo&lt;/a&gt;, writing a 170+ page book on command-line applications in Ruby in just one month. &lt;em&gt;And&lt;/em&gt; had &lt;a href='http://lampsvn.epfl.ch/trac/scala/ticket/3737'&gt;more&lt;/a&gt; &lt;a href='http://lampsvn.epfl.ch/trac/scala/ticket/3750'&gt;than&lt;/a&gt; &lt;a href='http://lampsvn.epfl.ch/trac/scala/ticket/3751'&gt;a few&lt;/a&gt; &lt;a href='http://lampsvn.epfl.ch/trac/scala/ticket/3793'&gt;patches&lt;/a&gt; &lt;a href='http://lampsvn.epfl.ch/trac/scala/ticket/4021'&gt;accepted&lt;/a&gt; &lt;a href='https://github.com/schacon/showoff/commit/b43fab03cd618335ad8d7c1774ff607d433d4321'&gt;to some&lt;/a&gt; &lt;a href='http://scala-lang.org'&gt;open source&lt;/a&gt; &lt;a href='https://github.com/schacon/showoff'&gt;projects&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, I created &lt;code&gt;2011_goals.txt&lt;/code&gt; to continue the tradition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy my iPhone app to App Store&lt;/li&gt;

&lt;li&gt;Speak at at least 2 conferences&lt;/li&gt;

&lt;li&gt;Publish my command-line application book&lt;/li&gt;

&lt;li&gt;Develop and deploy an iPad app&lt;/li&gt;

&lt;li&gt;Blog twice a month&lt;/li&gt;

&lt;li&gt;Learn JavaScript more betterer&lt;/li&gt;

&lt;li&gt;Get my rudimentary &lt;a href='http://lampsvn.epfl.ch/trac/scala/ticket/4102'&gt;scaladoc doclet&lt;/a&gt; accepted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I think it&amp;#8217;s doable, but I&amp;#8217;ve got a busy year planned in the non-geek-related parts of my life, so who knows? What are &lt;em&gt;your&lt;/em&gt; goals for 2011?&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Static vs. Dynamic Typing: A matter of keystrokes?</title>
   <link href="http://www.naildrivin5.com/blog/2010/08/24/static-vs-dynamic-typing-is-typing.html"/>
   <updated>2010-08-24T00:00:00-04:00</updated>
   <id>http://www.naildrivin5.com/blog/2010/08/24/static-vs-dynamic-typing-is-typing</id>
   <content type="html">&lt;p&gt;In Java, I almost &lt;em&gt;never&lt;/em&gt; make type errors. The type errors that are possible in Java fall roughly into two categories:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using an object of the wrong type (this is caught by the compiler)&lt;/li&gt;

&lt;li&gt;Casting an object to a more specific type at runtime (this can only be caught by tests or users :)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I&amp;#8217;d make error #1 on occasion, but the compiler catches it. As to #2, before generics, I can count on my hands the number of times I got a bona-fide &lt;code&gt;ClassCastException&lt;/code&gt; at runtime. After generics? Never.&lt;/p&gt;

&lt;p&gt;I don&amp;#8217;t mean just that I didn&amp;#8217;t experience these runtime type errors, but that they &lt;em&gt;didn&amp;#8217;t even make it to the compiler&lt;/em&gt;. If you think about how Java syntax works, it&amp;#8217;s no wonder:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='java'&gt;&lt;span class='n'&gt;List&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt;&lt;span class='n'&gt;String&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;someList&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;ArrayList&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt;&lt;span class='n'&gt;String&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;();&lt;/span&gt;
&lt;span class='n'&gt;someList&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;add&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;Foo&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt;
&lt;span class='n'&gt;someList&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;add&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;Bar&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I had to type almost the exact same thing twice. After about 2 days of using generics, my muscle memory literally &lt;em&gt;prevents&lt;/em&gt; me from making type errors. To even simulate one requires a pre-generics library call, or some herculean efforts. An arguable win for static typing, if at the price of verbosity.&lt;/p&gt;

&lt;p&gt;Of course, in Ruby, I make type errors all the time, especially when using new libraries I&amp;#8217;m not familiar with. Ruby libraries rarely document the types of things (though they are frequently liberal with what they will accept). The solution here is just better unit tests. And that&amp;#8217;s a pretty good thing. So, a slight negative for dynamic typing that leads us to a better tested system, reduced verbosity, and better productivity once the learning curve is dealth with.&lt;/p&gt;

&lt;p&gt;This pretty well illustrates the tradeoffs between dynamic and static typing. Case closed, right?&lt;/p&gt;

&lt;p&gt;Enter Scala. With Scala, I make type errors just as much as I do with Ruby. The only difference is that the compiler catches them. Here&amp;#8217;s the Scala equivalent to the Java code above&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;var&lt;/span&gt; &lt;span class='n'&gt;list&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Notce how I haven&amp;#8217;t specified a &lt;em&gt;single&lt;/em&gt; type? It&amp;#8217;s nearly identical to the Ruby version:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;list&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;These examples are obviously simplistic, but in a more complex system, Scala&amp;#8217;s type inferencer tends to be one step ahead of me. While it&amp;#8217;s handy that I have a compiler to catch these type errors, the fact remains that, despite Scala being a statically typed language, &lt;em&gt;I&amp;#8217;m making far more type errors than I would in Java&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This seems kindof odd, but I think it&amp;#8217;s ultimately a win: I get the brevity and productivity of a dynamically typed language, but the safety of the compiler catching my type errors for me.&lt;/p&gt;

&lt;p&gt;Scala puts a subtle spin on the &amp;#8220;static vs. dynamic&amp;#8221; debate, because you aren&amp;#8217;t annotating your types &lt;em&gt;nearly&lt;/em&gt; as much as with Java, but you still get all the benefits. I&amp;#8217;ve certainly heard many criticisims of static typing, but having the compiler check types for you wasn&amp;#8217;t one of them.&lt;/p&gt;

&lt;p&gt;Of course, sometimes you &lt;em&gt;do&lt;/em&gt; need to tell Scala what your types are, but, they seem to be exactly where you&amp;#8217;d want them anyway:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='cm'&gt;/** get users with the given name and age */&lt;/span&gt;
&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;getUsers&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;name&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;String&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='n'&gt;age&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;User&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This says that we take a requires &lt;code&gt;String&lt;/code&gt; and an optional &lt;code&gt;Int&lt;/code&gt; and will return a list of &lt;code&gt;User&lt;/code&gt; objects. To give the same information in Ruby, you&amp;#8217;d need to:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='c1'&gt;# Gets the users with the given name and age&lt;/span&gt;
&lt;span class='c1'&gt;#&lt;/span&gt;
&lt;span class='c1'&gt;# name - a String&lt;/span&gt;
&lt;span class='c1'&gt;# age - an Int or nil if not searching by age&lt;/span&gt;
&lt;span class='c1'&gt;#&lt;/span&gt;
&lt;span class='c1'&gt;# Returns an array of User objects&lt;/span&gt;
&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;get_users&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;name&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;&lt;span class='n'&gt;age&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='kp'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;.&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;(Sure, you could leave off the comment, but do you really hate your fellow developers (&lt;em&gt;and&lt;/em&gt; future you) that much?)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Now&lt;/em&gt; which language is more verbose? Perhaps the static/dynamic typing debate is really just about entering text?&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>In "Offense" of Scala's Option class; a guarded defense of Cédric's rant</title>
   <link href="http://www.naildrivin5.com/blog/2010/07/30/in-offense-of-scala-option.html"/>
   <updated>2010-07-30T00:00:00-04:00</updated>
   <id>http://www.naildrivin5.com/blog/2010/07/30/in-offense-of-scala-option</id>
   <content type="html">&lt;p&gt;In a &lt;a href='http://beust.com/weblog/2010/07/28/why-scalas-option-and-haskells-maybe-types-wont-save-you-from-null/'&gt;recent blog entry&lt;/a&gt;, Cédric Beust calls out scala&amp;#8217;s &lt;code&gt;Option&lt;/code&gt; class as nothing more significant than null checks. Commenters rightly set him straight that the thesis of his blog post was marred by an ignorance of idiomatic use of the class.&lt;/p&gt;

&lt;p&gt;But, it&amp;#8217;s hard to really blame Cédric, when you look at what he had to go on. Odersky&amp;#8217;s book states that one should use pattern matching with &lt;code&gt;Option&lt;/code&gt;, and the scaladoc for Option is just abysmal:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This class represents optional values. Instances of Option are either instances of case class Some or it is case object None.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is the &lt;em&gt;entire&lt;/em&gt; description of the class, no examples, nothing. Worse, the method that commenters called out as idiomatic, &lt;code&gt;flatMap&lt;/code&gt;, has the following description:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the option is nonempty, return a function applied to its value. Otherwise return None.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is &lt;em&gt;not&lt;/em&gt; what &lt;code&gt;Option#flatMap&lt;/code&gt; actually appears to do (nor is documented to do; it&amp;#8217;s documented to return an &lt;code&gt;Option[B]&lt;/code&gt;!):&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;String&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;String&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt;
&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;String&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt;
&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;flatMap&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;foobar&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;flatMap&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='nc'&gt;None&lt;/span&gt;
&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;result&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;flatMap&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='n'&gt;r&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;java.lang.String&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;foobar&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;r&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;getClass&lt;/span&gt;
&lt;span class='n'&gt;res6&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;java.lang.Class&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='k'&gt;_&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;Some&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It certainly doesn&amp;#8217;t call itself out as &amp;#8220;the way&amp;#8221; to use Option. A simple example in the scaladoc could have gone a long way.&lt;/p&gt;

&lt;p&gt;So, angry post + helpful commenters == problem solved, right?&lt;/p&gt;

&lt;p&gt;Wrong.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Option&lt;/code&gt; class is, really, an implementation of the &lt;a href='http://en.wikipedia.org/wiki/Null_Object_pattern'&gt;NullObject&lt;/a&gt; pattern, and a more elegant way to handle optional values. In scala, we might have this method signature:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='cm'&gt;/**&lt;/span&gt;
&lt;span class='cm'&gt; * Updates the full name&lt;/span&gt;
&lt;span class='cm'&gt; * @param lastName the last name&lt;/span&gt;
&lt;span class='cm'&gt; * @param firstName the first name&lt;/span&gt;
&lt;span class='cm'&gt; */&lt;/span&gt;
&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;updateName&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lastName&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;String&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;firstName&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;String&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This means &amp;#8220;update my name; lastName is required and firstName is optional&amp;#8221;. In java, this method might look like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='java'&gt;&lt;span class='cm'&gt;/**&lt;/span&gt;
&lt;span class='cm'&gt; * Updates the full name&lt;/span&gt;
&lt;span class='cm'&gt; * @param lastName the last name, may not be null&lt;/span&gt;
&lt;span class='cm'&gt; * @param firstName the first name, may be null&lt;/span&gt;
&lt;span class='cm'&gt; */&lt;/span&gt;
&lt;span class='kd'&gt;public&lt;/span&gt; &lt;span class='kt'&gt;void&lt;/span&gt; &lt;span class='nf'&gt;updateName&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;String&lt;/span&gt; &lt;span class='n'&gt;lastName&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;String&lt;/span&gt; &lt;span class='n'&gt;firstName&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lastName&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;throw&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nf'&gt;IllegalArgumentException&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;lastName required&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt;
    &lt;span class='o'&gt;}&lt;/span&gt;
    &lt;span class='n'&gt;StringBuffer&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;StringBuffer&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lastName&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;firstName&lt;/span&gt; &lt;span class='o'&gt;!=&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
        &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;append&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;, &amp;quot;&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt;
        &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;append&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;firstName&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt;
    &lt;span class='o'&gt;}&lt;/span&gt;
    &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;fullName&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;toString&lt;/span&gt;&lt;span class='o'&gt;();&lt;/span&gt;
&lt;span class='o'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So, what&amp;#8217;s the right way to do it in Scala? According to the commentors:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;updateName&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lastName&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;String&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;firstName&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;String&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;Unit&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nc'&gt;StringBuffer&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lastName&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
  &lt;span class='n'&gt;firstName&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;foreach&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;name&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;append&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;, &amp;quot;&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;append&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;firstName&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='o'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Yech. Does anyone else think that calling a method called &amp;#8220;foreach&amp;#8221; on our &amp;#8220;optional value&amp;#8221; is just nonsensical? Or that the &lt;em&gt;idiomatic way&lt;/em&gt; to treat an optional value is &lt;em&gt;as a collection&lt;/em&gt;, e.g. by using the &lt;code&gt;for&lt;/code&gt; comprehension? This just feels hacky. Naming is one of the most important (and challenging) things in software engineering, and &lt;code&gt;Option&lt;/code&gt;&amp;#8217;s API is an utter failure (even its name is wrong; when one has &lt;em&gt;an option&lt;/em&gt;, one typicaly has many choices, not just one or nothing. &lt;em&gt;Optional&lt;/em&gt; is really what is meant here, so why are we afraid of adding a few more letters? Especially given how &amp;#8220;precise&amp;#8221; some of the documentation is, mathematically speaking, why are we not being precise with English?). If &lt;code&gt;Option&lt;/code&gt; is just shorthand for a &amp;#8220;list of zero or one elements&amp;#8221;, and we get no better methods than what comes with &lt;code&gt;List&lt;/code&gt;, then what&amp;#8217;s even the point of the class?&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m not saying we remove all the collection methods from &lt;code&gt;Option&lt;/code&gt;, but how about a throwing us a bone to make our code readable and learnable without running to the scaladoc (or REPL) to see what&amp;#8217;s going on? I mean, there&amp;#8217;s a method on &lt;code&gt;Option&lt;/code&gt; called &lt;code&gt;withFilter&lt;/code&gt; whose documented purpose (I&amp;#8217;m not making this up) is: &amp;#8220;Necessary to keep Option from being implicitly converted to Iterable in for comprehensions&amp;#8221;. Am I expected to believe that it&amp;#8217;s ok to have &lt;em&gt;this&lt;/em&gt; hacky pile of cruft, but we can&amp;#8217;t get a readable method for &amp;#8220;do something to the contents if they are there&amp;#8221;?&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;ifValue&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;U&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;U&lt;/span&gt; &lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;Unit&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;foreach&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;unlessValue&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;U&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;U&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;Unit&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;self&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;isEmpty&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;
&lt;span class='o'&gt;}&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;updateName&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lastName&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;String&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;firstName&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;String&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;Unit&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nc'&gt;StringBuffer&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lastName&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
  &lt;span class='n'&gt;firstName&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;ifValue&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;name&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;append&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;, &amp;quot;&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;append&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;firstName&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;)&lt;/span&gt;
&lt;span class='o'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Which would be less surprising? Couple this with some better scaladoc:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='cm'&gt;/** This class represents an optional value.  &lt;/span&gt;
&lt;span class='cm'&gt; *&lt;/span&gt;
&lt;span class='cm'&gt; * To use as a null object:&lt;/span&gt;
&lt;span class='cm'&gt; * val optional = getSomePossiblyOptionalValue&lt;/span&gt;
&lt;span class='cm'&gt; * &amp;lt;pre&amp;gt;&lt;/span&gt;
&lt;span class='cm'&gt; * option.ifValue { (actualValue) =&amp;gt; &lt;/span&gt;
&lt;span class='cm'&gt; *   // do things with the value, if it was there&lt;/span&gt;
&lt;span class='cm'&gt; * }&lt;/span&gt;
&lt;span class='cm'&gt; * &amp;lt;/pre&amp;gt;&lt;/span&gt;
&lt;span class='cm'&gt; * or&lt;/span&gt;
&lt;span class='cm'&gt; * &amp;lt;pre&amp;gt;&lt;/span&gt;
&lt;span class='cm'&gt; * optional.unlessValue { log.debug(&amp;quot;missing optional value&amp;quot;) }&lt;/span&gt;
&lt;span class='cm'&gt; * &amp;lt;/pre&amp;gt;&lt;/span&gt;
&lt;span class='cm'&gt; * &lt;/span&gt;
&lt;span class='cm'&gt; * To use as a Monad or collection:&lt;/span&gt;
&lt;span class='cm'&gt; * &amp;lt;pre&amp;gt;&lt;/span&gt;
&lt;span class='cm'&gt; * val first8upper = option.flatMap( (y) =&amp;gt; Some(y.toUpperCase) ).&lt;/span&gt;
&lt;span class='cm'&gt; *                          flatMap( (y) =&amp;gt; Some(y.substring(0,8)) )&lt;/span&gt;
&lt;span class='cm'&gt; * &amp;lt;/pre&amp;gt;&lt;/span&gt;
&lt;span class='cm'&gt; */&lt;/span&gt;
&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
  &lt;span class='c1'&gt;// etc.&lt;/span&gt;
&lt;span class='o'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;With these examples, you cover the two main uses of this class, show newcomers how to use it, and demonstrate its superiority over null checks.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s frustrating to see this, because Scala has so much potential to be a lucid, accessible, readable language, but API usability and learnability are just not prioties. Scala needs to take some lessons from Ruby in terms of API design (and Java in terms of API documentation).&lt;/p&gt;

&lt;p&gt;Of course, none of this &lt;em&gt;does&lt;/em&gt; save you from null, because Scala is perfectly happy to assign null to anything. It kinda makes the whole thing seem a bit pointless.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>My first iPhone App - Part 5</title>
   <link href="http://www.naildrivin5.com/blog/2010/07/18/iphone-app-part-5.html"/>
   <updated>2010-07-18T00:00:00-04:00</updated>
   <id>http://www.naildrivin5.com/blog/2010/07/18/iphone-app-part-5</id>
   <content type="html">&lt;p&gt;&lt;em&gt;See &lt;a href='/blog/2010/06/23/iphone-app-part-1.html'&gt;Part 1&lt;/a&gt;, &lt;a href='/blog/2010/06/27/iphone-app-part-2.html'&gt;Part 2&lt;/a&gt;, &lt;a href='/blog/2010/06/29/iphone-app-part-3.html'&gt;Part 3&lt;/a&gt;, and &lt;a href='/blog/2010/07/08/iphone-app-part-4.html'&gt;Part 4&lt;/a&gt; first&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve been working on the app more than my recent lack of blog entries indicates. At this point, I have what could roughly be called a beta version; almost all the features are there, and things seem to be generally working pretty well.&lt;/p&gt;

&lt;h2 id='user_experience'&gt;User Experience&lt;/h2&gt;

&lt;p&gt;The biggest change in the UX is the ability to add tasting notes, date tasted, and location tasted. This is a new screen accessible from the main entry screen. The most obvious way to do this in my mind, was a big button at the bottom:&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/wine_brain_new_wine_5.jpg' alt='New Add Screen' /&gt;&lt;/p&gt;

&lt;p&gt;In designing the new screen, the &amp;#8220;where tasted&amp;#8221; and &amp;#8220;when tasted&amp;#8221; were straightforward; I used stock controls. For the tasting notes, I needed a &lt;code&gt;UITextView&lt;/code&gt;, which is akin to an HTML &lt;code&gt;TEXTAREA&lt;/code&gt;. The visual appearance of this control is pretty lacking compared to the &lt;code&gt;UITextField&lt;/code&gt;; there is no nice beveled edge, no rounded corners, and no placeholder text. I really just wanted a multi-line field much like the &lt;code&gt;UITextField&lt;/code&gt;, but there is nothing available to create that.&lt;/p&gt;

&lt;p&gt;So, I hacked something together.&lt;/p&gt;

&lt;p&gt;An option for the &lt;code&gt;UITextField&lt;/code&gt;&amp;#8217;s appearance is to have a beveled edge with square corners. In this configuration, you can adjust the height of the text field. So, I placed such a field on the screen and sized it about the size of my tasting notes field and made the background color white. I then put the tasting notes field on top of it, with a clear background color, and, well, it looked pretty good:&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/wine_brain_new_wine_details.jpg' alt='Details Screen' /&gt;&lt;/p&gt;

&lt;p&gt;I then implemented some &lt;code&gt;UITextViewDelegate&lt;/code&gt; methods to give the apperance of placeholder text:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objc'&gt;&lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;BOOL&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='nl'&gt;textViewShouldBeginEditing:&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;UITextView&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='n'&gt;textView&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='n'&gt;textView&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;text&lt;/span&gt; &lt;span class='nl'&gt;isEqualToString:&lt;/span&gt;&lt;span class='n'&gt;DEFAULT_TASTING_NOTES_TEXT&lt;/span&gt;&lt;span class='p'&gt;])&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='n'&gt;textView&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;text&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s'&gt;@&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='n'&gt;YES&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;

&lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;void&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='nl'&gt;textViewDidEndEditing:&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;UITextView&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;&lt;span class='n'&gt;textView&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='n'&gt;textView&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;text&lt;/span&gt; &lt;span class='n'&gt;length&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='n'&gt;textView&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;text&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;DEFAULT_TASTING_NOTES_TEXT&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I considered using some third-party controls that mimic this behavior, but didn&amp;#8217;t want to get side-tracked adding new frameworks to my app at this point.&lt;/p&gt;

&lt;h2 id='user_testing'&gt;User Testing&lt;/h2&gt;

&lt;p&gt;Once I had this, I handed my phone to Amy for some more user testing; She brought up a few obvious things that I had completely internalized and begun ignoring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clicking &amp;#8220;Save&amp;#8221; on the details screen brought you back to the &amp;#8220;new wine&amp;#8221; screen, instead of just saving and bringing you back to the top. A minor but obvious annoyance.&lt;/li&gt;

&lt;li&gt;She kept tapping on the &amp;#8220;Choose Varietal&amp;#8221; text field, thinking that would bring up the varietal chooser, instead of clicking the much smaller blue &amp;#8220;disclosure&amp;#8221; button&lt;/li&gt;

&lt;li&gt;She was a bit sad that the wines we had entered in the app would not be available on our shared Google Spreadsheet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To smooth the navigation after saving, I used a stock feature of the &lt;code&gt;UINavigationController&lt;/code&gt; to &amp;#8220;pop&amp;#8221; more than once up the chain. Since my design of the details screen used Apple&amp;#8217;s delegate pattern (essentially, the &amp;#8220;add new wine&amp;#8221; view controller was the delegate to the details view&amp;#8217;s lifecycle; when you click &amp;#8220;Save&amp;#8221; on the detail view, it triggers a callback in the &amp;#8220;add new wine&amp;#8221; view controller; the perfect place to save before the detail view controller popped back two screens).&lt;/p&gt;

&lt;p&gt;The problem with the &amp;#8220;Choose Varietal&amp;#8221; control had bugged me, too, but I got used to it and didn&amp;#8217;t think about it. The solution was very simple, though hacky. I placed a clear button on top of the field the exact size of the field and had it trigger the same action as the blue disclosure button. Problem solved.&lt;/p&gt;

&lt;p&gt;As to maintaining the list up on Google Docs, I think I may need to implement this sooner rather than later; I think it&amp;#8217;s important to be able to get your data out of an application, and Google Docs is a reasonably user-friendly way to do it (as opposed to emailing some CSV file).&lt;/p&gt;

&lt;h2 id='other_random_bits'&gt;Other Random Bits&lt;/h2&gt;

&lt;p&gt;I still didn&amp;#8217;t get around to setting up iCuke for testing; I really should because I don&amp;#8217;t know what missing &lt;code&gt;retain&lt;/code&gt; calls might be lurking. I also finally created an icon, using a picture I took in Napa. Not sure I like it, but it beats the white blob:&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/wine_brain_icon.png' alt='Icon' /&gt;&lt;/p&gt;

&lt;p&gt;(Taken from &lt;a href='http://www.flickr.com/photos/davetron5000/3805675435/'&gt;my original&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Finally, the app no longer starts up on the actual device. A seemingly serious problem that I assume would be remedied by a re-install from scratch, however I have a few wines that I&amp;#8217;ve added and don&amp;#8217;t particularly wanted to lose them. Not sure how I could gain access to the SQL database to get them out, but I&amp;#8217;m currently downloading the 4.0.1 update for my phone and the 2+ GB SDK update (!).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;As a followup, I had to re-install the application from scratch, though I was able to access the SQLite database from an iTunes backup. I &lt;em&gt;really&lt;/em&gt; need to implement a quicker backup/export mechanism&amp;#8230;&lt;/em&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>My first iPhone App - Part 4</title>
   <link href="http://www.naildrivin5.com/blog/2010/07/08/iphone-app-part-4.html"/>
   <updated>2010-07-08T00:00:00-04:00</updated>
   <id>http://www.naildrivin5.com/blog/2010/07/08/iphone-app-part-4</id>
   <content type="html">&lt;p&gt;&lt;em&gt;See &lt;a href='/blog/2010/06/23/iphone-app-part-1.html'&gt;Part 1&lt;/a&gt;, &lt;a href='/blog/2010/06/27/iphone-app-part-2.html'&gt;Part 2&lt;/a&gt;, and &lt;a href='/blog/2010/06/29/iphone-app-part-3.html'&gt;Part 3&lt;/a&gt; first&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The past week was spent trying to understand the best way to expand my application&amp;#8217;s features without have a ton of duplicated code or UI. It was also a learning experience on Core Data. Thankfully, &lt;a href='http://www.stackoverflow.com'&gt;Stackoverflow&lt;/a&gt; and its amazing contributers were very helpful.&lt;/p&gt;

&lt;h2 id='core_data_blunders'&gt;Core Data Blunders&lt;/h2&gt;

&lt;p&gt;It started as I made my first foray into implementing the search screen (i.e. the home screen of my app):&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/wine_brain_homescreen.jpg' alt='Home Screen' /&gt;&lt;/p&gt;

&lt;p&gt;Three of the searches (most recent wines, wines by rating, and all wines) end up doing the same thing more or less: Query for some data, sort it a certain way, and show it in a &lt;code&gt;UITableView&lt;/code&gt;. I ended up creating a custom table cell view and I wanted all three to use it:&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/wine_brain_custom_cell.jpg' alt='Custom Cell' /&gt;&lt;/p&gt;

&lt;p&gt;Access to Core Data-provided entities is done through objects of the class &lt;code&gt;NSFetchedResultsController&lt;/code&gt;, which takes what amounts to a database query and provides many ways of accessing the results, including caching, callbacks, and iteration. When using a table view, you typically have your view controller handle callbacks for this class, which allows the table to update itself when items are added, removes, or changed. All of this boilerplate is given to you at the start of the project. So far so good.&lt;/p&gt;

&lt;p&gt;My plan was to create additional &lt;code&gt;NSFetchedResultsController&lt;/code&gt; instances inside my table view controller class and then switch between them. A fine idea that lead that numerous random difficult-to-reproduce crashes.&lt;/p&gt;

&lt;p&gt;It turns out the basic idea of what I was doing was good, but my implementation exposed a sore lack of understanding of how all this stuff fit together. I&amp;#8217;m still not sure I fully grasp it (and wish the book I bought had a bit of a deeper dive into Core Data), but after some more reasoning, I got around it. Essentially, leaving the unused &lt;code&gt;NSFetchedResultsController&lt;/code&gt; instances connected to my table view &lt;em&gt;and&lt;/em&gt; having caching turned on &lt;em&gt;and&lt;/em&gt; not properly reloading data when switching searches created a situation where they were all pretty confused about the underlying state of the database.&lt;/p&gt;

&lt;p&gt;With some judicious management of these instances, as well as disabling caching, I now have a fully-functional &amp;#8220;Recent Wines&amp;#8221;, &amp;#8220;Wines By Rating&amp;#8221; and fancy indexed &amp;#8220;All Wines&amp;#8221; view (index meaning I can jump to wines by letter, a la the Contacts application).&lt;/p&gt;

&lt;p&gt;Unfortunately, the result of turning off caching is that it takes a noticable blip of time to summon any of these views. I may just come full circle and end up with three different &lt;code&gt;UITableViewController&lt;/code&gt; instances and NIBs just so I can leave Caching on.&lt;/p&gt;

&lt;h2 id='user_experience'&gt;User Experience&lt;/h2&gt;

&lt;p&gt;Once I had gotten back to a stable app, I loaded it up on my phone and headed into the field. A few nights ago, Amy and I ended up at one of our favorite restaurants/wine bars in DC, &lt;a href='http://www.proofdc.com'&gt;Proof&lt;/a&gt;. We&amp;#8217;ve been there several times, and many of their wines-by-the-glass are in the Wine Brain. While they rotate their selections, I was curious as to what I&amp;#8217;d had there previously. Unfortunately, I had yet to implement the search-by-location feature :) Combing through the &amp;#8220;All Wines&amp;#8221; view was a bit frustrating. This made obvious several features that are now on the top of my list (some planned previously, some not):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Find wines by location&lt;/li&gt;

&lt;li&gt;Actually &lt;em&gt;entering&lt;/em&gt; the location at which I had a wine&lt;/li&gt;

&lt;li&gt;Location-aware assistance of location (e.g. &amp;#8220;Are you at Proof? Here&amp;#8217;s what you&amp;#8217;ve had there&amp;#8230;&amp;#8221;)&lt;/li&gt;

&lt;li&gt;Ability to text-search the &amp;#8220;all wines&amp;#8221; list&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The good news is that my cursory reading of my book and the API docs indicates that these things are going to be &lt;em&gt;very&lt;/em&gt; easy to implement.&lt;/p&gt;

&lt;h2 id='objectivec'&gt;Objective-C&lt;/h2&gt;

&lt;p&gt;There&amp;#8217;s a lot to like about Objective-C, and a lot to dislike. Even though the handling of multiple arguments is a bit strange, I find it actually results in fairly readable code. It feels very Apple; different, but usable. Even though it&amp;#8217;s a lot to type out something like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;NSString *stripped = [canonicalName stringByTrimmingCharactersInSet:
                       [NSCharacterSet whitespaceAndNewlineCharacterSet]];&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It &lt;em&gt;is&lt;/em&gt; pretty readable, regardless of what programming language you are coming from. That being said, stack traces and error messages on crashes are nigh-useless, and the overall testability of iPhone apps is pretty behind the times. This months &lt;a href='http://pragprog.com/magazines'&gt;issue of Prag Prog&amp;#8217;s magazine&lt;/a&gt; has an interesting article on &lt;a href='http://github.com/unboxed/icuke'&gt;iCuke&lt;/a&gt;, which I look forward to trying out. I&amp;#8217;ve resulted to keeping a text file of test cases that I have to manually run through to make sure I haven&amp;#8217;t broken anything, and it feels, well, 1997. The rumours of a Apple&amp;#8217;s switch to Ruby are too good to be true, but one can always dream.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Continued in &lt;a href='/blog/2010/07/18/iphone-app-part-5.html'&gt;Part 5&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>My first iPhone App - Part 3</title>
   <link href="http://www.naildrivin5.com/blog/2010/06/29/iphone-app-part-3.html"/>
   <updated>2010-06-29T00:00:00-04:00</updated>
   <id>http://www.naildrivin5.com/blog/2010/06/29/iphone-app-part-3</id>
   <content type="html">&lt;p&gt;&lt;em&gt;See &lt;a href='/blog/2010/06/27/iphone-app-part-2.html'&gt;Part 1&lt;/a&gt; and &lt;a href='/blog/2010/06/27/iphone-app-part-2.html'&gt;Part 2&lt;/a&gt; first&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Just a quick update for tonight. I&amp;#8217;m starting to get the hang of how the user interface elements I create in Interface Builder get hooked up and become available in code. It&amp;#8217;s a bit odd and not terribly intuitive, but it&amp;#8217;s starting to make a &lt;em&gt;bit&lt;/em&gt; more sense. Under the covers there&amp;#8217;s some sort of dependency injection going on (even if Apple doesn&amp;#8217;t call it that) that smells of Spring-style magic; objects get created for me and populated if I do the right thing.&lt;/p&gt;

&lt;p&gt;At any rate, I decided that, before making any more changes, I needed to get a reasonable data set into the app. I spent two painful hours exporting my Google Doc Wine Brain into CSV and parsing it with Objective-C, mapping it to my Core Data model objects. In the end, I was successful, but, WOW, what a pain compared to Ruby or Perl.&lt;/p&gt;

&lt;p&gt;Seeing this large set of data on the home screen was very motivational to start working on a drill-down/search interface, as you can see here:&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/wine_brain_all_wines.jpg' alt='All Wines List' /&gt;&lt;/p&gt;

&lt;p&gt;Before delving into my new homescreen, I decided to work up a better color scheme that was more &amp;#8220;wine-like&amp;#8221;. I&amp;#8217;m not a big fan of apps that have fancy graphics and obscure the idiomatic iPhone UI, but a bit of a color splash would go a long way (and, not to mention, be well within my graphic design skill level). In addition, more user testing (via Amy once again) revealed that the rating control needed a much starker contrast between the selected and unselected choices. There isn&amp;#8217;t much I have control over via the API for this, so I chose an alternate style of &lt;code&gt;UISegmentedControl&lt;/code&gt; that used the &amp;#8220;iPhone blue&amp;#8221; for the selected state. I think it works OK with the color scheme, though I&amp;#8217;d prefer the &amp;#8220;merlot red&amp;#8221; that I chose for the nav bar and wine type:&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/wine_brain_new_wine_4.jpg' alt='Colorrific New Wine Screen' /&gt;&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m starting to think that my desire to have wine entry confined to one screen might not pan out. The &amp;#8220;slot-machine&amp;#8221; control will become more and more unusable as more varietals are added, and there&amp;#8217;s really no way to even &lt;em&gt;add&lt;/em&gt; a new varietal here. I think I may have to go with the drill-down method where by I push another table view onto the stack to select (and possibly add) a varietal. For another day.&lt;/p&gt;

&lt;p&gt;Lastly, I took a stab at a better home screen:&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/wine_brain_homescreen.jpg' alt='Home Screen' /&gt;&lt;/p&gt;

&lt;p&gt;This pretty-well represents the ways I &lt;em&gt;think&lt;/em&gt; I&amp;#8217;d want to navigate the data. Time will tell once I implement these searches, but this seems like a reasonable start.&lt;/p&gt;

&lt;p&gt;I also have to say that, despite Objective-C&amp;#8217;s overall wackiness, it was pretty easy to put this together and have the &amp;#8220;Add New Wine&amp;#8221; button bring up the &amp;#8220;Add Wine&amp;#8221; screen and to have the &amp;#8220;All Wines&amp;#8221; button navigate to the old home screen. Apple has done a reasonable job of making it easy to make an idiomatic, normal-looking iPhone app.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Continued in &lt;a href='/blog/2010/07/08/iphone-app-part-4.html'&gt;Part 4&lt;/a&gt;, and &lt;a href='/blog/2010/07/18/iphone-app-part-5.html'&gt;Part 5&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>My first iPhone App - Part 2</title>
   <link href="http://www.naildrivin5.com/blog/2010/06/27/iphone-app-part-2.html"/>
   <updated>2010-06-27T00:00:00-04:00</updated>
   <id>http://www.naildrivin5.com/blog/2010/06/27/iphone-app-part-2</id>
   <content type="html">&lt;p&gt;&lt;em&gt;See &lt;a href='/blog/2010/06/23/iphone-app-part-1.html'&gt;Part 1&lt;/a&gt; first&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For the past several days I&amp;#8217;ve had the app on my phone and used it to enter in wines to see how the UI was working. Yesterday, I integrated Core Data (Apple&amp;#8217;s Object/Relational Mapper (ORM), for lack of a better description) so that I could actually &lt;em&gt;save&lt;/em&gt; some data. I discovered some nuances to using Core Data, as well as a refinement in the UI.&lt;/p&gt;

&lt;h2 id='ui'&gt;UI&lt;/h2&gt;

&lt;p&gt;Last night, I had both my girlfriend Amy and my good friend Clay (who is also reasonably into wine) play around with the &amp;#8220;new wine&amp;#8221; screen. Neither have an iPhone, and there were a few obvious problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They were very unaccustomed to the &amp;#8220;Done&amp;#8221; button being in the upper-right corner, as well as the &amp;#8220;slot-machine&amp;#8221; control&lt;/li&gt;

&lt;li&gt;Both had trouble with the &amp;#8220;Wine Name&amp;#8221; concept&lt;/li&gt;

&lt;li&gt;Both had trouble dismissing the keyboard&lt;/li&gt;

&lt;li&gt;Clay thought he was entering search terms and not a new Wine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Later that evening, I had a glass of wine at a bar and entered it into my app. Up until this point, I was just typing in wines I knew about, so this was the first &amp;#8220;real use&amp;#8221; of the app in the field. I quickly realized that the &amp;#8220;Wine Name&amp;#8221; concept, while important, was too vague and confusing to be the first field you enter. Most wines are known by the vineyard and some don&amp;#8217;t even have proper names or appellations. So, I swapped the fields and added some examples in the placeholder text:&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/wine_brain_new_wine_comparison.jpg' alt='Comparison' /&gt;&lt;/p&gt;

&lt;p&gt;I also added a title to indicate that this screen is for adding a new wine. Finally, I used the &lt;a href='http://stackoverflow.com/questions/804563/how-to-hide-the-keyboard-when-empty-area-is-touched-on-iphone'&gt;background button trick&lt;/a&gt; along with some events on the rating and type controls to dismiss the keyboard if you tap anywhere outside of a text field.&lt;/p&gt;

&lt;p&gt;This feels much cleaner and flows a bit better. While varietal is probably the third most important thing (at least for New World wines), the slot-machine control would be awkwardly placed right below the vineyard/vintage text fields, so I left it where it was.&lt;/p&gt;

&lt;p&gt;As to Clay and Amy&amp;#8217;s confusion over some idiomatic iPhone design choices, I&amp;#8217;m not worrying about them a whole lot; a typical iPhone user will understand what&amp;#8217;s going on (I hope :).&lt;/p&gt;

&lt;h2 id='core_data'&gt;Core Data&lt;/h2&gt;

&lt;p&gt;Backing all this is Apple&amp;#8217;s Core Data, which grew out of the &lt;a href='http://en.wikipedia.org/wiki/Enterprise_Objects_Framework'&gt;Enterprise Objects Framework&lt;/a&gt; (and was, incidentally, my first exposure to an ORM way back in 1998), is the simplest and most idiomatic way to store and manage data on the iPhone. As with Interface Builder, you create the model visually, using a simplistic data modelling tool. I set up the bare bones of my data model and generated the classes.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/wine_brain_data_model.jpg' alt='Data Model' /&gt;&lt;/p&gt;

&lt;p&gt;The first problem I ran into was in changing the model after the database had been created on the device. Core Data doesn&amp;#8217;t migrate your model for you by default. I ended up starting over with a &amp;#8220;versioned&amp;#8221; model and implementing their default migration. This will probably work for simple changes, but for more complex changes, it looks like it&amp;#8217;s somewhat difficult to migrate the model. An unfortunate reason to do some Big Design Up Front.&lt;/p&gt;

&lt;p&gt;My next problem was initializing reference data. In my case, I wanted the list of varietals as well as the list of wine types (e.g. &amp;#8220;red&amp;#8221;, &amp;#8220;white&amp;#8221;) to be in the database and managed by Core Data. I ended up creating an array of the values inside the app and then checking the database for their existence, adding them if they were missing. It&amp;#8217;s a bit cheesy, but I can extract the lists to plist files later. It &lt;em&gt;did&lt;/em&gt; give me a chance to play with Objective-C&amp;#8217;s blocks feature. I needed to map my list of &lt;code&gt;Varietal&lt;/code&gt; objects to a list of strings, so I could compare that list against my default list. While &lt;code&gt;NSArray&lt;/code&gt; doesn&amp;#8217;t provide a map function, it does provide the equivalent of Ruby&amp;#8217;s &lt;code&gt;each&lt;/code&gt; or Scala&amp;#8217;s &lt;code&gt;foreach&lt;/code&gt;. In true Apple/Objective-C style, it&amp;#8217;s called &lt;code&gt;enumerateObjectsUsingBlock&lt;/code&gt; :)&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objc'&gt;&lt;span class='n'&gt;NSMutableArray&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;strings&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;NSMutableArray&lt;/span&gt; &lt;span class='nl'&gt;arrayWithCapacity:&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;array&lt;/span&gt; &lt;span class='n'&gt;count&lt;/span&gt;&lt;span class='p'&gt;]];&lt;/span&gt;
&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;array&lt;/span&gt; &lt;span class='nl'&gt;enumerateObjectsUsingBlock:&lt;/span&gt;&lt;span class='o'&gt;^&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;id&lt;/span&gt; &lt;span class='n'&gt;obj&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;NSUInteger&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kt'&gt;BOOL&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;stop&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;strings&lt;/span&gt; &lt;span class='nl'&gt;addObject:&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;obj&lt;/span&gt; &lt;span class='nl'&gt;valueForKey:&lt;/span&gt;&lt;span class='s'&gt;@&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;]];&lt;/span&gt;
&lt;span class='p'&gt;}];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;stop&lt;/code&gt; pointer is an out-only variable that you set to YES to allow for an early exit from the loop. I&amp;#8217;m glad they&amp;#8217;ve adopted this functional style; I forsee explicit loops becoming just as quaint as GOTOs in the near future.&lt;/p&gt;

&lt;p&gt;One thing bugged me about this process, however. I had these generated classes and it wasn&amp;#8217;t clear how to add my own methods to them without losing the code every time I re-generated my model. Enter &lt;a href='http://github.com/rentzsch/mogenerator'&gt;mogenerator&lt;/a&gt;. This provides a more sophisticated bit of code generation, givng you two classes for each model: one for machines (i.e. for Core Data to manage) and a subclass for people (to which I can add custom methods). Perfect! I wasn&amp;#8217;t able to incorporate it into XCode, but I&amp;#8217;m happy running in on the command line as needed for now.&lt;/p&gt;

&lt;h2 id='random_bits'&gt;Random Bits&lt;/h2&gt;

&lt;p&gt;I spent more time than I would&amp;#8217;ve liked tracking down a nasty bug where every attempt to convert a string to a number (for the wine vintage year) resulted in a &lt;code&gt;nil&lt;/code&gt; number. It turns out I was confused about when some object lifecycle methods were being called and my pointer to an &lt;code&gt;NSNumberFormatter&lt;/code&gt; was, in fact, pointing to &lt;code&gt;nil&lt;/code&gt;. Unlike Java, where you&amp;#8217;d get a &lt;code&gt;NullPointerException&lt;/code&gt;, or C, where you&amp;#8217;d get a core dump, it seems Objective-C just returns &lt;code&gt;nil&lt;/code&gt; and doesn&amp;#8217;t even issue a warning. Very strange. Once I realized that, the solution was obvious.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m still not 100% sure I&amp;#8217;m structuring my code properly, but Stack Overflow&amp;#8217;s stalwart iPhone SDK answerers have been &lt;em&gt;incredibly&lt;/em&gt; helpful in pointing me in the right direction.&lt;/p&gt;

&lt;h2 id='next_steps'&gt;Next Steps&lt;/h2&gt;

&lt;p&gt;Now that I&amp;#8217;ve got the ability to save and retrieve data, the next step is to start looking to browsing, viewing, and editing the database. I think the domain is restricted enough that I can use the iPhone&amp;#8217;s idiomatic drill-down table navigation to filter the database.&lt;/p&gt;

&lt;p&gt;Continued in &lt;a href='/blog/2010/06/29/iphone-app-part-3.html'&gt;Part 3&lt;/a&gt;, &lt;a href='/blog/2010/07/08/iphone-app-part-4.html'&gt;Part 4&lt;/a&gt;, and &lt;a href='/blog/2010/07/18/iphone-app-part-5.html'&gt;Part 5&lt;/a&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>My first iPhone App - Part 1</title>
   <link href="http://www.naildrivin5.com/blog/2010/06/23/iphone-app-part-1.html"/>
   <updated>2010-06-23T00:00:00-04:00</updated>
   <id>http://www.naildrivin5.com/blog/2010/06/23/iphone-app-part-1</id>
   <content type="html">&lt;h2 id='background'&gt;Background&lt;/h2&gt;

&lt;p&gt;Last year, I spent most of my free time becoming familiar with Ruby, Rails, and Scala. I&amp;#8217;m by no means an expert, but I&amp;#8217;m trying to follow the advice of the &lt;a href='http://www.pragprog.com'&gt;Pragmatic Programmers&lt;/a&gt; and learn a new language/system every year. This year, it&amp;#8217;s going to be the iPhone API and Objective-C. I coded some WebObjects applications in Objective-C many years ago, so the language isn&amp;#8217;t totally unfamiliar, but the iPhone SDK, obviously, is. After working my way through the first several chapters of the &lt;a href='http://pragprog.com/titles/amiphd/iphone-sdk-development'&gt;Dudney and Adamson&amp;#8217;s &amp;#8220;iPhone SDK Development&amp;#8221;&lt;/a&gt; book, I decided I was ready to try my first real app.&lt;/p&gt;

&lt;h2 id='first_app'&gt;First App&lt;/h2&gt;

&lt;p&gt;My girlfriend and I enjoy wine, but are largely novices. On a trip to Napa we started writing down the wines we&amp;#8217;d tried and keeping personal ratings of them. The idea being twofold: try to remember good wines/avoid bad ones, and try to hone in on what our tastes are. There are so many wines and so many flavors and smells, it&amp;#8217;s just impossible to keep in your head. So, I created a Google Spreadsheet and a form to allow us to enter wines on the go, via our smart phones. The Goolge Docs form is less than usable, and this seems like the perfect job for a native iPhone app.&lt;/p&gt;

&lt;h3 id='user_experience'&gt;User Experience&lt;/h3&gt;

&lt;p&gt;Aside from learning the ins and outs of the SDK, another main goal is focus on making a highly-usable application (at least for myself and my girlfriend). So, before diving into Core Data and modelling the domain, my first version of the applicaton simply presents the &amp;#8220;add a new wine&amp;#8221; screen. This will be the screen I spend the most time in, and it&amp;#8217;s important to make it fast and easy.&lt;/p&gt;

&lt;p&gt;The Google Spreadsheet currently collects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wine Name&lt;/li&gt;

&lt;li&gt;Vineyard&lt;/li&gt;

&lt;li&gt;Vintage (year)&lt;/li&gt;

&lt;li&gt;Varietal&lt;/li&gt;

&lt;li&gt;Type (e.g. red/white)&lt;/li&gt;

&lt;li&gt;Where we had&lt;/li&gt;

&lt;li&gt;When we had&lt;/li&gt;

&lt;li&gt;My rating&lt;/li&gt;

&lt;li&gt;Her rating&lt;/li&gt;

&lt;li&gt;Tasting Notes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That&amp;#8217;s obviously too much for one iphone screen, and, if I&amp;#8217;m entering something in a hurry, I might not have time to go through all that. Further, I think adding multiple ratings makes things a bit confusing, so I focussed my screen on the identifying characteristics (name/vineyard/vintage), the rating, and the type:&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/wine_brain_new_wine_1.jpg' alt='First Attempt' /&gt;&lt;/p&gt;

&lt;p&gt;As you can see, I tried to fit the &amp;#8220;where&amp;#8221; on the bottom, as well as a &amp;#8220;enter more information&amp;#8221; button. After loading this on the phone, it was just not working out, plus I was missing the varietal, which is fairly important (at least to me).&lt;/p&gt;

&lt;p&gt;My next attempt simply ignores the &amp;#8220;add more&amp;#8221; concept, and, by using the segmented control, I was able to fit the type into a more compact area, while including the varietal as a &amp;#8220;slot-machine&amp;#8221;/picker.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/wine_brain_new_wine_2.jpg' alt='Second Attempt' /&gt;&lt;/p&gt;

&lt;p&gt;My plan is to load this onto the phone and try using it the next few times I&amp;#8217;m out. I figure I can do without the tasting notes or location if it keeps the UI simple&lt;/p&gt;

&lt;h3 id='the_code'&gt;The Code&lt;/h3&gt;

&lt;p&gt;Objective-C and XCode are a whole different world from Java or Ruby. First thing that bit me is the memory management. I was familiar with the rules (or so I thought). Basically, if you call a method like &amp;#8220;copyXXX&amp;#8221; or &amp;#8220;initXXX&amp;#8221; to create a new object, you must &lt;code&gt;release&lt;/code&gt; it when you are done with it. If you get access to an object through any other means, you should &lt;em&gt;not&lt;/em&gt; release it.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objc'&gt;&lt;span class='c1'&gt;// my class has an NSArray called varietals that I&amp;#39;m initializing here&lt;/span&gt;
&lt;span class='n'&gt;varietals&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;NSArray&lt;/span&gt; &lt;span class='nl'&gt;arrayWithObjects:&lt;/span&gt;
                  &lt;span class='s'&gt;@&amp;quot;Barbera&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
                  &lt;span class='s'&gt;@&amp;quot;Cabernet Franc&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
                  &lt;span class='c1'&gt;// snip&lt;/span&gt;
                  &lt;span class='s'&gt;@&amp;quot;Zinfandel&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
                  &lt;span class='s'&gt;@&amp;quot;Other&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
                  &lt;span class='nb'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Since I&amp;#8217;m &lt;em&gt;not&lt;/em&gt; calling an &amp;#8220;init&amp;#8221; style method, I figured I didn&amp;#8217;t need to release it in &lt;code&gt;dealloc&lt;/code&gt;. For some reason, this made me decide that I didn&amp;#8217;t need to &lt;code&gt;retain&lt;/code&gt; it. This caused my first crash and trip through the debugger to figure out what in the heck is going on.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='objc'&gt;&lt;span class='c1'&gt;// my class has an NSArray called varietals that I&amp;#39;m initializing here&lt;/span&gt;
&lt;span class='n'&gt;varietals&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[[&lt;/span&gt;&lt;span class='n'&gt;NSArray&lt;/span&gt; &lt;span class='nl'&gt;arrayWithObjects:&lt;/span&gt;
                  &lt;span class='s'&gt;@&amp;quot;Barbera&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
                  &lt;span class='s'&gt;@&amp;quot;Cabernet Franc&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
                  &lt;span class='c1'&gt;// snip&lt;/span&gt;
                  &lt;span class='s'&gt;@&amp;quot;Zinfandel&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
                  &lt;span class='s'&gt;@&amp;quot;Other&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
                  &lt;span class='nb'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='n'&gt;retain&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Since I needed &lt;code&gt;varietals&lt;/code&gt; to survive the method where I was initializing it, I had to &lt;code&gt;retain&lt;/code&gt; it.&lt;/p&gt;

&lt;h3 id='other_struggles'&gt;Other struggles&lt;/h3&gt;

&lt;p&gt;Interestingly, laying out the UI and getting that hooked up isn&amp;#8217;t too bad; the thing I&amp;#8217;m having the most trouble with is figuring out what is the &amp;#8220;unsurprising&amp;#8221; way of doing things; tutorial code from books is rarely very well written; it&amp;#8217;s usually done in a certain way to make concepts clear, but I haven&amp;#8217;t yet found a definitive &amp;#8220;here&amp;#8217;s how you organize your code&amp;#8221; or &amp;#8220;iPhone best practices&amp;#8221; that seems relatively comprehensive.&lt;/p&gt;

&lt;p&gt;At any rate, I figure if I can get the UX to be reasonably good, the rest should sort itself out.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ll continue posting about my progress here on my blog. If I can get the app polished and working, my girlfriend might demand and Android version. Would be interesting to compare the two paradigms (especially since Android is all Java, which has been my bread-and-butter for many years).&lt;/p&gt;

&lt;p&gt;&lt;a href='/blog/2010/06/27/iphone-app-part-2.html'&gt;Continued in Part 2&lt;/a&gt;, &lt;a href='/blog/2010/06/29/iphone-app-part-3.html'&gt;Part 3&lt;/a&gt;, &lt;a href='/blog/2010/07/08/iphone-app-part-4.html'&gt;Part 4&lt;/a&gt;, and &lt;a href='/blog/2010/07/18/iphone-app-part-5.html'&gt;Part 5&lt;/a&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>In defense of vi</title>
   <link href="http://www.naildrivin5.com/blog/2010/06/14/in-defense-of-vi.html"/>
   <updated>2010-06-14T00:00:00-04:00</updated>
   <id>http://www.naildrivin5.com/blog/2010/06/14/in-defense-of-vi</id>
   <content type="html">&lt;p&gt;Sadly, I was unable to attend &lt;a href='http://www.railsconf.org'&gt;RailsConf&lt;/a&gt; this year. It was in Baltimore, and it would&amp;#8217;ve been a lot of fun, but it just wasn&amp;#8217;t in the cards. One of the great things about RailsConf is that the videos are posted online very quickly and are always of high quality. While I always like hearing &lt;a href='http://www.youtube.com/watch?v=b0iKYRKtAsA'&gt;DHH&lt;/a&gt; speak, I try to never miss one of &lt;a href='http://www.twitter.com/unclebobmartin'&gt;Uncle Bob Martin&lt;/a&gt;, author of the must-go-read-this-right-now &lt;a href='http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1276567370&amp;amp;sr=8-1'&gt;Clean Code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This year, he gave an &lt;a href='http://www.youtube.com/watch?v=mslMLp5bQD0'&gt;awesome talk&lt;/a&gt; on the (lack of) innovation in software development. He pointed out that we were still writing the same type of code now as we were 40 years ago. In one part, he asks the crowd what editor they use (knowing full well most will say &lt;a href='http://www.vim.org'&gt;vim&lt;/a&gt;). He then proceeds to make light of the audience for using a 19-year-old editor based on a 34-year-old editor. While his criticism is brief, I think it speaks more to the sorry state of text editing than to the developers (like me) who are &amp;#8220;still&amp;#8221; using vim.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m sure that unclebob is one of the more advanced IDE users, but it just &lt;em&gt;pains&lt;/em&gt; me watching my co-workers meander through their code, selecting things with the mouse, and deleting long swaths of text by just hitting the delete key a lot.&lt;/p&gt;

&lt;p&gt;While an IDE is great for learning a new environment (especially one as pedantic and verbose as Java or Objective-C), the editing capabilities are counter-intuitive and degenerate. vim may be hard on the newbie, but it&amp;#8217;s intuitive and logical. When you understand the &amp;#8220;zen&amp;#8221; of vim, you can fly through your code, playing it like a musical instrument. It &lt;em&gt;affords&lt;/em&gt; muscle memory and allows sophisticated chaining of movement, intent, and action. You can &lt;em&gt;see&lt;/em&gt; what you want to accomplish and your hands make it so, all without reaching for a mouse, cursoring, using the delete key, or contorting your hand with some awful combination of key modifiers.&lt;/p&gt;

&lt;p&gt;Think of it as a piano; it&amp;#8217;s a very simple base of simple sounds and actions that, when chained together, can be used to make beautiful music. An IDE is more like a fancy Casio keyboard with built-in songs and beats. Shiny, but hollow.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Are private methods code smells?</title>
   <link href="http://www.naildrivin5.com/blog/2010/05/26/is-private-a-code-smell.html"/>
   <updated>2010-05-26T00:00:00-04:00</updated>
   <id>http://www.naildrivin5.com/blog/2010/05/26/is-private-a-code-smell</id>
   <content type="html">&lt;p&gt;Having had discussions with co-workers on the utility of private methods and &lt;a href='http://scala-programming-language.1934581.n4.nabble.com/Just-curious-why-public-as-default-visibility-td2228941.html'&gt;recently on the scala mailing list&lt;/a&gt;, there&amp;#8217;s been the notion that private methods (or even protected methods) are code smells &amp;#8211; indicators that there is something wrong with the design of your code. I believe in many cases they can be, but that private (and protected) methods still have their uses, especially in maintaining a clean design under constraints of getting things done. First, we need to know what we are talking about.&lt;/p&gt;

&lt;h2 id='definitions'&gt;Definitions&lt;/h2&gt;

&lt;p&gt;While the technical meaning of access modifiers varies with the language, the &lt;em&gt;intent&lt;/em&gt; these concepts communicate is what we&amp;#8217;re talking about here. I assert that the &lt;em&gt;intent&lt;/em&gt; of public/protected/private is (and/or should be) as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;public&lt;/em&gt; - this method is part of the published API and will not change within major versions of the class&lt;/li&gt;

&lt;li&gt;&lt;em&gt;protected&lt;/em&gt; - this method is a hook for modifying the behavior of this class using subclasses. It, too, will not change within major versions of the class (of course, it also might exist for code-reuse internal to the class hierarchy).&lt;/li&gt;

&lt;li&gt;&lt;em&gt;private&lt;/em&gt; - this method was &lt;em&gt;refactored out of a well tested public or protected method&lt;/em&gt; for reasons of clarity or internal re-use. This method may absolutely change, even in patch releases, and should not be relied upon to even exist&lt;/li&gt;

&lt;li&gt;&lt;em&gt;package private&lt;/em&gt; (bonus for Java) - this method was written by someone lazy or ingorant, &lt;em&gt;or&lt;/em&gt; by someone who acknowledges that this code should be pulled out into its own class, but hasn&amp;#8217;t done so, yet still wants to test it seperately, thus breaking encapsulation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='why_would_private_methods_be_code_smells'&gt;Why would private methods be code smells?&lt;/h2&gt;

&lt;p&gt;The most concise argument is that private methods could indicate that the class that contains them is doing too many things. Consider this code from shorty, my URL shortener:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;override&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;contextInitialized&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;event&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;ServletContextEvent&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
  &lt;span class='n'&gt;event&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;getServletContext&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;log&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;Initializing our hasher/DB&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;dirName&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;event&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;getServletContext&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;getInitParameter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;
    &lt;span class='nc'&gt;ShortyServlet&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;DB_DIR_PARAM&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
  &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dirName&lt;/span&gt; &lt;span class='o'&gt;!=&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;dir&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nc'&gt;File&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dirName&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dir&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;exists&lt;/span&gt;&lt;span class='o'&gt;())&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
      &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dir&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;isDirectory&lt;/span&gt;&lt;span class='o'&gt;())&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;hasher&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;URIHasher&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;DB&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dir&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt;
        &lt;span class='n'&gt;hasher&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;start&lt;/span&gt;
        &lt;span class='n'&gt;uriHasher&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;hasher&lt;/span&gt;
        &lt;span class='n'&gt;event&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;getServletContext&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;setAttribute&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;
          &lt;span class='nc'&gt;ShortyServlet&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;URI_HASHER_ATTRIBUTE&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='n'&gt;uriHasher&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
      &lt;span class='o'&gt;}&lt;/span&gt;
      &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;throw&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nc'&gt;ServletException&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dir&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;getAbsolutePath&lt;/span&gt; 
          &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s'&gt;&amp;quot; is not a directory&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
      &lt;span class='o'&gt;}&lt;/span&gt;
    &lt;span class='o'&gt;}&lt;/span&gt;
    &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
      &lt;span class='k'&gt;throw&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nc'&gt;ServletException&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dir&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;getAbsolutePath&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s'&gt;&amp;quot; doesn&amp;#39;t exist&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
    &lt;span class='o'&gt;}&lt;/span&gt;
  &lt;span class='o'&gt;}&lt;/span&gt;
  &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;throw&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nc'&gt;ServletException&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;You must supply a value for &amp;quot;&lt;/span&gt; 
      &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='nc'&gt;ShortyServlet&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;DB_DIR_PARAM&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
  &lt;span class='o'&gt;}&lt;/span&gt;
&lt;span class='o'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Is it totally clear what this method does? If not, it basically checks that the directory configured for our database exists and is a directory, giving us a specific error message if not. It&amp;#8217;s a bit long and full of error checking, so the meat where it creates our URI hasher and gives it to the servlet is somewhat obscured. Here&amp;#8217;s a cleaned up version:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;override&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;contextInitialized&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;event&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;ServletContextEvent&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
  &lt;span class='n'&gt;event&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;getServletContext&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;log&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;Initializing our hasher/DB&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
  &lt;span class='n'&gt;getDBDir&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;event&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Right&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dir&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
      &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;hasher&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;URIHasher&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;DB&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dir&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt;
      &lt;span class='n'&gt;hasher&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;start&lt;/span&gt;
      &lt;span class='n'&gt;uriHasher&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;hasher&lt;/span&gt;
      &lt;span class='n'&gt;event&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;getServletContext&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;setAttribute&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;
        &lt;span class='nc'&gt;ShortyServlet&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;URI_HASHER_ATTRIBUTE&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='n'&gt;uriHasher&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
    &lt;span class='o'&gt;}&lt;/span&gt;
    &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Left&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;errorMessage&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
      &lt;span class='k'&gt;throw&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nc'&gt;ServletException&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;errorMessage&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
  &lt;span class='o'&gt;}&lt;/span&gt;
&lt;span class='o'&gt;}&lt;/span&gt;

&lt;span class='k'&gt;private&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;getDBDir&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;event&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;ServletContextEvent&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;dirName&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;event&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;getServletContext&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;getInitParameter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;
    &lt;span class='nc'&gt;ShortyServlet&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;DB_DIR_PARAM&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
  &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dirName&lt;/span&gt; &lt;span class='o'&gt;!=&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;dir&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nc'&gt;File&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dirName&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dir&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;exists&lt;/span&gt;&lt;span class='o'&gt;())&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
      &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dir&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;isDirectory&lt;/span&gt;&lt;span class='o'&gt;())&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
        &lt;span class='nc'&gt;Right&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dir&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
      &lt;span class='o'&gt;}&lt;/span&gt;
      &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
        &lt;span class='nc'&gt;Left&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dir&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;getAbsolutePath&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s'&gt;&amp;quot; is not a directory&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
      &lt;span class='o'&gt;}&lt;/span&gt;
    &lt;span class='o'&gt;}&lt;/span&gt;
    &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
      &lt;span class='nc'&gt;Left&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dir&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;getAbsolutePath&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s'&gt;&amp;quot; doesn&amp;#39;t exist&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
    &lt;span class='o'&gt;}&lt;/span&gt;
  &lt;span class='o'&gt;}&lt;/span&gt;
  &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
    &lt;span class='nc'&gt;Left&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;You must supply a value for &amp;quot;&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='nc'&gt;ShortyServlet&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;DB_DIR_PARAM&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;
  &lt;span class='o'&gt;}&lt;/span&gt;
&lt;span class='o'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;We&amp;#8217;ve added lines of code, but our public method is a lot clearer: we get the dir for our DB; if we get a &amp;#8220;right&amp;#8221;, we have a usable dir, and if we get a &amp;#8220;left&amp;#8221; (the Scala convention for an error), we have the error message to use for our exception.&lt;/p&gt;

&lt;p&gt;So, is &lt;code&gt;getDBDir&lt;/code&gt; now a code smell? This is a private method and, this means that &lt;code&gt;contextInitialized&lt;/code&gt; was tested and we extracted the private method as step three of the TDD &amp;#8220;Test/Fix/Refactor&amp;#8221; cycle.&lt;/p&gt;

&lt;p&gt;Of course, &lt;code&gt;getDBDir&lt;/code&gt; has nothing to do with the &lt;code&gt;ServletContextListener&lt;/code&gt; and is really all about checking for a valid path. So, we should extract it to a new class, right?&lt;/p&gt;

&lt;p&gt;Well, if we &lt;em&gt;did&lt;/em&gt; do that, we&amp;#8217;ve now actually added a public API to our codebase. Unless we make the new class completely private to the enclosing class, we&amp;#8217;ve now introduced a new public class that must be tested and managed as part of our system&amp;#8217;s public API.&lt;/p&gt;

&lt;p&gt;I don&amp;#8217;t see the benefit to doing that. I don&amp;#8217;t particularly &lt;em&gt;want&lt;/em&gt; this method to be in the public API (at least not &lt;em&gt;now&lt;/em&gt;). So, what about making it a private inner class? That doesn&amp;#8217;t seem to be much different than what we have now, though it might save a few minutes on a future extraction.&lt;/p&gt;

&lt;h2 id='when_is_this_a_code_smell'&gt;When IS this a code smell?&lt;/h2&gt;

&lt;p&gt;This was a simple example. Consider a class like &lt;a href='http://github.com/davetron5000/gliffy/blob/master/lib/gliffy/url.rb'&gt;&lt;code&gt;SignedUrl&lt;/code&gt; in my Gliffy Ruby client&lt;/a&gt;. This class has a fair number of private methods and, overall, is pretty large. The private methods are vague things like &lt;code&gt;handle_params&lt;/code&gt; and &lt;code&gt;get_signing_key&lt;/code&gt;. The private methods aren&amp;#8217;t really the problem, however; They are a symptom of the fact that this class is just doing too many things. A better design would be to split this class up into something like a &lt;code&gt;UrlParams&lt;/code&gt;, &lt;code&gt;UrlSigner&lt;/code&gt; and &lt;code&gt;UrlAssembler&lt;/code&gt; (just off the top of my head). The result would be more smaller classes, each with fewer public &lt;em&gt;and&lt;/em&gt; private methods.&lt;/p&gt;

&lt;h2 id='what_about_protected_methods'&gt;What about protected methods?&lt;/h2&gt;

&lt;p&gt;In Ruby, you don&amp;#8217;t see a lot of protected methods. In well-designed Java frameworks (such as &lt;a href='http://www.springframework.org'&gt;Spring&lt;/a&gt;), you&amp;#8217;ll see them as I&amp;#8217;ve described above: hooks into a helper class that allow you to customize how that class behaves via subclassing. In non-library code, protected methods tend to get used for code-reuse in narrowly-focused class hierarchies. For example, the project I&amp;#8217;m working on has a &lt;code&gt;BaseController&lt;/code&gt; that provides common methods to the actual web controllers. Having used protected methods for both of these purposes, I think that, honestly, both &lt;em&gt;can&lt;/em&gt; be code smells.&lt;/p&gt;

&lt;h3 id='protected_methods_as_hooks'&gt;Protected methods as hooks&lt;/h3&gt;

&lt;p&gt;In the case of providing &amp;#8220;hooks&amp;#8221;, I think it&amp;#8217;s clear that by providing them at all, you are acknowledging that your class &lt;em&gt;might&lt;/em&gt; be poorly designed (or that your language lacks the expressiveness to better design it). Consider the venerable (and now deprecated) &lt;a href='http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/web/servlet/mvc/SimpleFormController.html'&gt;&lt;code&gt;SimpleFormController&lt;/code&gt;&lt;/a&gt;, a Spring MVC class that provides &lt;em&gt;many&lt;/em&gt; protected-method hooks, one of which is &lt;code&gt;protected Map referenceData(HttpServletRequest request)&lt;/code&gt;. This is called during the lifecycle of the controller to get any data needed by the form that should be available to the view (for example, a list of U.S. states from the database). Your subclass of &lt;code&gt;SimpleFormController&lt;/code&gt; overrides this to provide the data as a map.&lt;/p&gt;

&lt;p&gt;Why not create an interface called &lt;code&gt;ServletRequestToReferenceData&lt;/code&gt; that contains this method, and inject an instance into &lt;code&gt;SimpleFormController&lt;/code&gt;? This would be very Spring-like. My guess as to why this &lt;em&gt;isn&amp;#8217;t&lt;/em&gt; the case is that there is simply too much overhead in making yet another one-method interface and the designer of &lt;code&gt;SimpleFormController&lt;/code&gt; just felt this was a reasonable tradeoff.&lt;/p&gt;

&lt;p&gt;In Scala, however, this could simply take a function:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;referenceData&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]((&lt;/span&gt;&lt;span class='nc'&gt;HttpServletRequest&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Map&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;String&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]);&lt;/span&gt;

  &lt;span class='c1'&gt;// ...&lt;/span&gt;


  &lt;span class='n'&gt;controller&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;referenceData&lt;/span&gt;&lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;request&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
    &lt;span class='c1'&gt;// create our map based on the request&lt;/span&gt;
  &lt;span class='o'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In Ruby, the overhead of creating a new class isn&amp;#8217;t nearly as onerous, and we could still inject a block as we do in Scala.&lt;/p&gt;

&lt;p&gt;Ultimately, I would say that you have to make a tradeoff here, and it &lt;em&gt;has&lt;/em&gt; to take the language and frameworks into account; a class with many, many hooks might be a code smell, but using it as a means to avoid language ceremony in the name of OO purity is probably a reasonable design tradeoff.&lt;/p&gt;

&lt;h3 id='protected_methods_as_code_sharing'&gt;Protected methods as code sharing&lt;/h3&gt;

&lt;p&gt;This use of protected methods is harder to justify, but incredibly handy. Still, this could be another case of Java (e.g.) not providing the necessary language features to make class extraction more straightforward. As mentioned, in my current application, I have a &lt;code&gt;BaseController&lt;/code&gt;. It has a helper method as follows:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='java'&gt;&lt;span class='kd'&gt;protected&lt;/span&gt; &lt;span class='n'&gt;Person&lt;/span&gt; &lt;span class='nf'&gt;getAndValidateLoggedInPerson&lt;/span&gt;&lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
  &lt;span class='n'&gt;Person&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;personService&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;getPerson&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;
    &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;authenticationService&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;loggedInUserId&lt;/span&gt;&lt;span class='o'&gt;());&lt;/span&gt;
  &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;throw&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;NotFoundException&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt;
  &lt;span class='o'&gt;}&lt;/span&gt;
  &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt;
&lt;span class='o'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Because of Spring MVC, we have specialized exceptions for HTTP errors, such as &amp;#8220;NOT_FOUND&amp;#8221;. Here we contain the logic to identify the id of the logged-in person as well as the check for existence. Having this available to all controllers in the entire system is very handy.&lt;/p&gt;

&lt;p&gt;But, is this a code smell?&lt;/p&gt;

&lt;p&gt;We could make a class that does this, turning this code:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='java'&gt;&lt;span class='n'&gt;Person&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;getAndValidateLoggedInPerson&lt;/span&gt;&lt;span class='o'&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;into this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='java'&gt;&lt;span class='n'&gt;Person&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;personValidatorAndGetter&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='na'&gt;getPerson&lt;/span&gt;&lt;span class='o'&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;creating a one method class that has many lines of injected dependeicies and other boilerpalte with a few actual lines of code.&lt;/p&gt;

&lt;p&gt;I think this is yet another case of pragmatically dealing with language ceremony. In Scala or Ruby, the overhead of creating re-usable bits of code like this is far lower than for Java; In Scala one could envision a simple function, possibly with some implicit parameters. Ultimateley, &amp;#8220;too much&amp;#8221; of this sort of thing &lt;em&gt;should&lt;/em&gt; be a code smell, but small bits of this, in the name of simplicity, clarity, and simply keeping the codebase smaller isn&amp;#8217;t an automatic red flag.&lt;/p&gt;

&lt;h2 id='conclusions'&gt;Conclusions&lt;/h2&gt;

&lt;p&gt;So, are non-public methods code smells? If we take the &lt;a href='http://en.wikipedia.org/wiki/Code_smell'&gt;wikipedia definition&lt;/a&gt;, which is clear that a code smell indicates merely the &lt;em&gt;possibility&lt;/em&gt; of deeper problems in your code, then, yes, private and protected methods &lt;em&gt;are&lt;/em&gt; code smells.&lt;/p&gt;

&lt;p&gt;But, should they be avoided at all costs? Absolutely not. There&amp;#8217;s many valid reasons to use them, and they do not deserve the blame for an ill-concieved class. Coding in the real world is about tradeoffs; we have to do the best thing we can with the time, resources, and tools at our disposal. These tradeoffs may not result in an &lt;a href='http://en.wikipedia.org/wiki/Edmond_Hoyle'&gt;According-to-Hoyle&lt;/a&gt; OO (or functional) design, but we&amp;#8217;re not writing code to provide examples of programming paradigms or design patterns; we&amp;#8217;re writing it to accomplish something and provide value. And, as professionals, we need to do it at a predictable rate that doesn&amp;#8217;t incur too much technical debt.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Video of My Talk at ScalaDays 2010</title>
   <link href="http://www.naildrivin5.com/blog/2010/04/30/my-talk-at-scala-days.html"/>
   <updated>2010-04-30T00:00:00-04:00</updated>
   <id>http://www.naildrivin5.com/blog/2010/04/30/my-talk-at-scala-days</id>
   <content type="html">&lt;p&gt;
&lt;a href=&quot;http://days2010.scala-lang.org/node/138/169&quot;&gt;Video of my talk at ScalaDays is online&lt;/a&gt;.  Check it out.  Feedback very much appreciated!
&lt;/p&gt;
&lt;p&gt;
&lt;a href=&quot;http://days2010.scala-lang.org/node/138/169&quot;&gt;&lt;img src=&quot;/images/scaladays_talk.jpg&quot; width=&quot;400&quot; border=&quot;0&quot;/&gt;&lt;/a&gt;
&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Scala Days Impressions</title>
   <link href="http://www.naildrivin5.com/blog/2010/04/22/scala-days-recap.html"/>
   <updated>2010-04-22T00:00:00-04:00</updated>
   <id>http://www.naildrivin5.com/blog/2010/04/22/scala-days-recap</id>
   <content type="html">&lt;p&gt;
I had the good fortune to not only attend &lt;a href=&quot;http://days2010.scala-lang.org/&quot;&gt;ScalaDays 2010&lt;/a&gt;, but also to speak (generously supported by &lt;a href=&quot;http://www.opower.com&quot;&gt;my employer&lt;/a&gt;).  The experience overall was great.
I talked to some really enthusiastic and interesting people (including two high school kids from Austria who were using Lift because, after three years of Java, they were tired of it already!)
&lt;/p&gt;
&lt;h1&gt;Overall Impressions&lt;/h1&gt;
&lt;ul&gt;
    &lt;li&gt;Scala 2.8 has some &lt;b&gt;really&lt;/b&gt; powerful new features; I'm almost &lt;b&gt;glad&lt;/b&gt; I don't have a significant codebase
    using 2.7, because I would hate to &lt;b&gt;not&lt;/b&gt; be able to use 2.8&lt;/li&gt;
    &lt;li&gt;The conference had a wide variety of talks, at varying skill levels; this was not a &quot;beginners-only&quot; conference, though
    there were plenty of introductory talks (e.g. the &lt;a href=&quot;http://akkasource.org/&quot;&gt;Akka&lt;/a&gt; talk).&lt;/li&gt;
    &lt;li&gt;The Scala team seems very interested in moving Scala into industry and changing the perception of it as an &quot;academic&quot;
    language (though I'm not convinced they know what to do, nor should this be their responsibility).&lt;/li&gt;
    &lt;li&gt;Most people I talked to who weren't using Scala at their jobs were looking at the strategy &lt;a href=&quot;http://sneaking-scala.heroku.com/&quot;&gt;I had employed&lt;/a&gt;
    (using it for better testing), or were just frustrated with not being able to take advantage of Scala's productivity.&lt;/li&gt;
    &lt;li&gt;Scala's flexible syntax and powerful constructs are being used for a very wide variety of things; there were talks
    on using it for &lt;a href=&quot;http://processing.org/&quot;&gt;Processing&lt;/a&gt;, parallel collections, and cross-compilation to
    non-standard architectures (i.e. chips with no JVM available).&lt;/li&gt;
    &lt;li&gt;The term &quot;monad&quot; was mentioned during exactly one talk and not at all for the rest of the conference.  This made
    me feel very good, because the impression I get on the Scala mailing list sometimes is that if you don't understand
    mathematical type theory, you are a moron who can never understand Scala.  This impression has been proved false.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Talks I Attended&lt;/h2&gt;
&lt;p&gt;
It was very interesting to compare this conference to a &lt;a href=&quot;http://www.nofluffjuststuff.com/home/main&quot;&gt;No Fluff Just Stuff&lt;/a&gt; conference.  At those, the speakers
are professional, both in that they are getting paid and that they are just, really, really good at speaking and presenting.  Their talks, however, tend to be introductory and not terribly advanced.  I think that's fine, these are the type of speakers you want to have when you need to &quot;get the message out&quot; on some new and interesting technologies.
&lt;/p&gt;
&lt;p&gt;
The speakers at ScalaDays, however, were just regular people using Scala and wanting to talk about it.  As such, things like presentation style and slides were highly varied in terms of quality.  That being said, even the speakers who had the most trouble, still had some interesting things to talk about.  Following are my quick thoughts on each of the talks I attended:
&lt;/p&gt;
&lt;h3&gt;Opening Keynote&lt;/h3&gt;
&lt;h4&gt;by Martin Odersky&lt;/h4&gt;
&lt;p&gt;
His talk was on the new features of Scala 2.8 which, as I said above, are quite exciting.  Package objects, new collections library, and default/named arguments are just some of the highlights.  All-in-all, some very exciting features.
&lt;/p&gt;
&lt;h3&gt;Runing Scala in the Browser&lt;/h3&gt;
&lt;h4&gt;by Wolfgang Kuehn&lt;/h4&gt;
&lt;p&gt;
He had created a way to write Scala code and turn it into JavaScript, much like how GWT does this with Java.  His approach wasn't geared around UI widgets, however, but in creating AJAX applications using WebSockets.  I've always felt JavaScript was assembly language (which is why I think &lt;a href=&quot;http://jashkenas.github.com/coffee-script/&quot;&gt;coffeescript&lt;/a&gt; is so interesting), and this was another way to leverage JavaScript without having to deal with it.
&lt;/p&gt;
&lt;h3&gt;Scala Parallel Collections&lt;/h3&gt;
&lt;h4&gt;by Aleksander Prokopec&lt;/h4&gt;
&lt;p&gt;
This was a preview of a Scala 2.8.1 (or later) feature, where a subpackage of the new 2.8 collections library was created that could perform the collection operations in parallel.  Consider a &lt;tt&gt;filter&lt;/tt&gt; on a collection; this is highly parallelizable.  This library is being created to basically implement that in a transparent fashion.  Really interesting stuff.  They had even considered load balancing, via some interesting work-stealing mechanisms.  In only 30 minutes, there wasn't a &lt;b&gt;huge&lt;/b&gt; amount of detail, but this seems to be another way in which parallel computation could be done very easily.
&lt;/p&gt;
&lt;h3&gt;Developing the Scala Bindings to the Fly Object Space&lt;/h3&gt;
&lt;h4&gt;by Channing Walton, Nigel Warren, Simon Kent&lt;/h4&gt;
&lt;p&gt;
The concept of &quot;object spaces&quot; never really sunk in with me, but it wasn't actually that relevant to the talk.  This was basically a comparison of a Java library and it's straight-port to Scala.  As expected, the Scala implementations were all much more succinct and (to me) clear.  The speakers hadn't used a lot of Crazy Scala Magic&amp;#8482; to achieve the real code reduction that was shown.  This talk made it very clear that even if you write &quot;Java in Scala&quot;, you still get a lot of productivity gains.
&lt;/p&gt;
&lt;h3&gt;CCSTM: Library-based STM for Scala&lt;/h3&gt;
&lt;h4&gt;by Nathan Bronson, Hassan Chafi, Kunle Olukotun&lt;/h4&gt;
&lt;p&gt;
&lt;a href=&quot;http://en.wikipedia.org/wiki/Software_transactional_memory&quot;&gt;Software Transactional Memory&lt;/a&gt; is one of the go-to features of Clojure.  Clojure supports it natively, while Scala does not.  This talk was on an implementation of STM as a library for Scala.  It seemed relatively simple to use and understand.  While it's not as &quot;clean&quot; as the Clojure way of doing things, the speaker made a solid case for a library implementation being a better tradeoff, given the difficulty in adding it to the language at this point in Scala's life (it's easy to forget how mature the Scala language and compiler are, despite how &quot;new&quot; it seems).
&lt;/p&gt;
&lt;h3&gt;Lightweight language support for type-based, concurrent event processing&lt;/h3&gt;
&lt;h4&gt;by Philipp Haller&lt;/h4&gt;
&lt;p&gt;
This talk proposed a function type called &quot;Translucent Functions&quot; that were better-suited to concurrency than the partial functions used in the actor library.  Honestly, it was a bit over my head, and I wasn't able to catch up with the speaker.  Perhaps the paper would be more elucidating for me.
&lt;/p&gt;
&lt;h3&gt;Data Parallel Programming in Scala&lt;/h3&gt;
&lt;h4&gt;by Bruce Lester&lt;/h4&gt;
&lt;p&gt;
This talk was very similar to the one on Scala Parallel Collections.  Here, the speaker had created a collection library separate from the Scala one, designed specifically to allow parallel processing.  He had a very different approach, using control structures to indicate areas where parallelism could occure.  It was pretty interesting, but the Scala 2.8 Collections Library implementation seemed a lot cleaner to me than this.
&lt;/p&gt;
&lt;h3&gt;Type Specialization in Scala&lt;/h3&gt;
&lt;h4&gt;by Iulian Drago&amp;#x219;&lt;/h4&gt;
&lt;p&gt;
One of the new features of 2.8 is the ability to &quot;specialize&quot; your code to work with primitive types and avoid boxing/unboxing.  This is something Java cannot really do.  This talk was an overview of how that worked and what specializations were done to the Scala library.  I guess it's nice that this kind of optimization if available, but I think it would have negligible gains for most real-world applications that weren't doing constant number crunching.  Even in that case, you don't necessarily need this.
&lt;/p&gt;
&lt;h3&gt;Leaky Monads&lt;/h3&gt;
&lt;h4&gt;by Josh Suereth&lt;/h4&gt;
&lt;p&gt;
How could I not attend the only session (and mention!) of Monads?  The speaker gave a good overview of using Monads to
implement automatic resource management (e.g. &lt;code&gt;File.open { |file| file.readlines.whatever }&lt;/code&gt;).  The idea was that since Monads are designed to hold onto the objects they manage, it's a bit inconvienient when dealing with the results of operating on managed resources.  Thus, his monads &quot;leaked&quot; their contents to create more concise code.
&lt;/p&gt;
&lt;h3&gt;Type-safe SQL embedded in Scala&lt;/h3&gt;
&lt;h4&gt;by Christoph Wulf&lt;/h4&gt;
&lt;p&gt;
Akin to &lt;a href=&quot;http://en.wikipedia.org/wiki/LINQ&quot;&gt;LINQ&lt;/a&gt;, this talk showed how to write SQL directly inside Scala code, but maintain type safety.  It uses
a compiler plugin to achieve this, and he talked a lot about how to tell the difference between embedded SQL and regular Scala code.  I guess the plugin introspects your database to get the types and generates a bunch of code using some Scala classes that get substituted in during compilation.  Pretty interesting.  I'm not sure I'm really &lt;i&gt;missing&lt;/i&gt; SQL right in my code, but it is certainly cleaner than JDBC.
&lt;/p&gt;
&lt;h3&gt;Scala at LinkedIn: Distribute Computing with Norbert&lt;/h3&gt;
&lt;h4&gt;by Chris Conrad&lt;/h4&gt;
&lt;p&gt;
This was a talk about how LinkedIn is using Scala to glue together some enabling technologies to create their social network graph.  It seemed really clean and simple, especially since the underlying technologies are all Java-based.  This was mostly an overview of the API and some usage examples.  It's &lt;a href=&quot;http://sna-projects.com/norbert/&quot;&gt;open source&lt;/a&gt;, and looks pretty interesting.  I'm not sure it would be useful for me at my job, but definitely seems like a cool project.
&lt;/p&gt;
&lt;h3&gt;Akka&lt;/h3&gt;
&lt;h4&gt;by Jonas Boner&lt;/h4&gt;
&lt;p&gt;
I was looking forward to this one quite a bit, as akka gets a lot of hype on Twitter.  I think 30 minutes was just too short, as it was pretty light on details.  There was a lot of assertions about Akka that the speakers just didn't have time to elucidate or substantiate.  I would love to see a comparison of Scala Actor vs. Akka Actor code and discuss why the Akka way is better.  Similarly, I'd love to see the basis for all the assertions on Akka's performance; it certainly gets a lot of hype.  Jonas is currently working on publicizing the production deployments of Akka (which would go a long way) as well as establishing commercial support for it (which &lt;b&gt;also&lt;/b&gt; goes a long way :).
&lt;/p&gt;
&lt;h3&gt;Scala IDE for Eclipse&lt;/h3&gt;
&lt;h4&gt;by Miles Sabin&lt;/h4&gt;
&lt;p&gt;
I went to this purely for my co-workers.  I hate IDEs in general, and Eclipse does some pretty evil things to my co-workers, yet many of them still swear by it.  At any rate, Miles was almost impossible for me to understand (despite being English!) and most of what I got out of the presentation was that Eclipse was very much designed to work with only Java, requiring some nasty hacks to get Scala working with it.  It seems Miles' Herculean efforts have been used to get around this and there now seems to be a nice development environment for extending and enhancing the Scala plugin.
&lt;/p&gt;
&lt;h3&gt;sbt Design and Implementation&lt;/h3&gt;
&lt;h4&gt;by Mark Harrah&lt;/h4&gt;
&lt;p&gt;
While sbt isn't my ideal build tool, but it's a billion times better than Maven and Mark's talk actually made me appreciate it a lot more.  He is unabashedly in favor of terse symbols over long method names, and he spent some time explaining the rational behind them (thus making things make a bit more sense). His assertion is that you will eventually internalize the symbols and achieve productivity gains at a cost of a slight bump at the start.  I tend to disagree with this, because how often is one modifying their build?  This is why learning and retaining Ant and Maven is so difficult (I can't write a &lt;tt&gt;copy&lt;/tt&gt; in Ant without a trip to the docs).  At any rate, this was a good talk and great overview of sbt, and, despite me not being into the crazy symbols, I will take it over Maven or Ant any day.  At least it's based in a real programming language and not some XML nonsense.
&lt;h3&gt;Processing with Spde&lt;/h3&gt;
&lt;h4&gt;by Nathan Hamblen&lt;/h4&gt;
&lt;p&gt;
This was a brief over of Processing, for those unfamiliar with this (horribly&amp;#8208;named) visualization tool and then a review of the Scala bindingns the presenter had created.  Interestingly, he created &lt;a href=&quot;http://technically.us/spde/About&quot;&gt;SPDE&lt;/a&gt; as an SBT plugin so that users could gain the benefit of SBT's automatic re-compilation and running features.  His plugin + a text editor is a makeshift IDE for Processing, which is pretty cool.  It was very high-level and didn't get into too much detail, but the Scala code was, as expected, much more concise than the Java code.
&lt;/p&gt;
&lt;h3&gt;Sneaking Scala Into your Organization&lt;/h3&gt;
&lt;h4&gt;by Me!&lt;/h4&gt;
&lt;p&gt;
I was pretty nervous, as the many of the previous speakers' topics were all quite heady, but I had practiced my ass off, and delivered the talk as well as I could.  I think it was pretty well received and got some good questions.  I had talked with a few people previously in the conference who were using testing as a way to get Scala into their jobs and a few other people who were interested in what I had to say.  Several people were curious as to how the other developers at OPOWER liked Scala.  I felt pretty good about it.
&lt;/p&gt;
&lt;h3&gt;Future of Scala&lt;/h3&gt;
&lt;h4&gt;by The Scala Team&lt;/h4&gt;
&lt;p&gt;
For this, we broke into small groups and basically unloaded on a poor member of the Scala team as to how anything related to Scala could be better.  Then, the Scala team assembled all of this info while Martin gave a very long term roadmap for Scala.  I do worry that the universe will never catch up to Martin and Scala team as they add more and more advanced and innovative features.
&lt;/p&gt;
&lt;p&gt;
After this, a member of the Scala team did a very fast tour of the feedback.  I wish the entire list could be posted; there was a lot of very heartening complaints in there that would not be obvious from the Scala mailing list (e.g.  hate on the underscore, desire to be less academic in terminology)  This fed my (arguably self-biased) impressions that people want to get Scala into industry and that there is a large hole in this part of the Scala universe.
&lt;/p&gt;
&lt;p&gt;
There were also some updates on IntelliJ's support for Scala.  They sound way ahead of the curve compared to Eclipse and NetBeans, but I was a bit frightened by IDEA's  guy saying that they way people learn languages is to ask for auto-completion and see what's available.  I see this trend all to often and I think it's harmful.  More on that later.
&lt;/p&gt;
&lt;h3&gt;Overall&lt;/h3&gt;
&lt;p&gt;
Despite still being stuck in Geneva, I'm glad I went.  Giving my talk was fun, but it was also great to hear about all the many ways in which people are using Scala.  I went in expecting massive academia overload, with a lot of theoretical type system and functional programming talk and got, instead, a wide variety of topics and just the right amount of academia (i.e. not that much).  Really encouraging.  Also encouraging is that ScalaDays 2011 will likely be in the Bay Area, which is a much nicer place to get stuck that stupid Geneva.
&lt;/p&gt;
</content>
 </entry>
 
 
</feed>

