2010 in review; what's next for me in 2011

January 01, 2011

Yesterday, while waiting for guests to arrive at my mostly-annual New Year’s Eve party, I found a txt file I created called 2010_goals.txt. It’s contents:

  • speak at at least one more user’s group
  • speak at some sort of conference
  • deploy an App to the iPhone App Store
  • Deploy a Rails 2 app to Heroku

Static vs. Dynamic Typing: A matter of keystrokes?

August 24, 2010

In Java, I almost never make type errors. The type errors that are possible in Java fall roughly into two categories:

  1. Using an object of the wrong type (this is caught by the compiler)
  2. Casting an object to a more specific type at runtime (this can only be caught by tests or users :)

I’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 ClassCastException at runtime. After generics? Never.

I don’t mean just that I didn’t experience these runtime type errors, but that they didn’t even make it to the compiler. If you think about how Java syntax works, it’s no wonder:

List<String> someList = new ArrayList<String>();
someList.add("Foo");
someList.add("Bar");

I had to type almost the exact same thing twice. After about 2 days of using generics, my muscle memory literally prevents 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.

Of course, in Ruby, I make type errors all the time, especially when using new libraries I’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’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.

This pretty well illustrates the tradeoffs between dynamic and static typing. Case closed, right?

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’s the Scala equivalent to the Java code above

var list = List("foo","bar")

Notce how I haven’t specified a single type? It’s nearly identical to the Ruby version:

list = ["foo","bar"]

These examples are obviously simplistic, but in a more complex system, Scala’s type inferencer tends to be one step ahead of me. While it’s handy that I have a compiler to catch these type errors, the fact remains that, despite Scala being a statically typed language, I’m making far more type errors than I would in Java.

This seems kindof odd, but I think it’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.

Scala puts a subtle spin on the “static vs. dynamic” debate, because you aren’t annotating your types nearly as much as with Java, but you still get all the benefits. I’ve certainly heard many criticisims of static typing, but having the compiler check types for you wasn’t one of them.

Of course, sometimes you do need to tell Scala what your types are, but, they seem to be exactly where you’d want them anyway:

/** get users with the given name and age */
def getUsers(name:String,age:Option[Int]):List[User]

This says that we take a requires String and an optional Int and will return a list of User objects. To give the same information in Ruby, you’d need to:

# Gets the users with the given name and age
#
# name - a String
# age - an Int or nil if not searching by age
#
# Returns an array of User objects
def get_users(name,age=nil)
    ...
end

(Sure, you could leave off the comment, but do you really hate your fellow developers (*and* future you) that much?)

Now which language is more verbose? Perhaps the static/dynamic typing debate is really just about entering text?

In "Offense" of Scala's Option class; a guarded defense of Cédric's rant

July 30, 2010

In a recent blog entry, Cédric Beust calls out scala’s Option 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.

But, it’s hard to really blame Cédric, when you look at what he had to go on. Odersky’s book states that one should use pattern matching with Option, and the scaladoc for Option is just abysmal:

This class represents optional values. Instances of Option are either instances of case class Some or it is case object None.

That is the entire description of the class, no examples, nothing. Worse, the method that commenters called out as idiomatic, flatMap, has the following description:

If the option is nonempty, return a function applied to its value. Otherwise return None.

This is not what Option#flatMap actually appears to do (nor is documented to do; it’s documented to return an Option[B]!):

scala> val s:Option[String] = Some("foo")
scala> val n:Option[String] = None
scala> val f = { (x:String) => Some(x + "bar") }
scala> s.flatMap(f)
Some(foobar)
scala> n.flatMap(f)
None
scala> val result = s.flatMap(f)
r: Option[java.lang.String] = Some(foobar)
scala> r.getClass
res6: java.lang.Class[_] = class scala.Some

It certainly doesn’t call itself out as “the way” to use Option. A simple example in the scaladoc could have gone a long way.

So, angry post + helpful commenters == problem solved, right?

Wrong.

The Option class is, really, an implementation of the NullObject pattern, and a more elegant way to handle optional values. In scala, we might have this method signature:

/**
 * Updates the full name
 * @param lastName the last name
 * @param firstName the first name
 */
def updateName(lastName:String, firstName:Option[String])

This means “update my name; lastName is required and firstName is optional”. In java, this method might look like this:

/**
 * Updates the full name
 * @param lastName the last name, may not be null
 * @param firstName the first name, may be null
 */
public void updateName(String lastName, String firstName) {
    if (lastName == null) {
        throw new IllegalArgumentException("lastName required");
    }
    StringBuffer b = new StringBuffer(lastName);
    if (firstName != null) {
        b.append(", ");
        b.append(firstName);
    }
    this.fullName = b.toString();
}

So, what’s the right way to do it in Scala? According to the commentors:

def updateName(lastName:String, firstName:Option[String]):Unit = {
  val b = new StringBuffer(lastName)
  firstName.foreach( (name) => b.append(", "); b.append(firstName) )
}

Yech. Does anyone else think that calling a method called “foreach” on our “optional value” is just nonsensical? Or that the idiomatic way to treat an optional value is as a collection, e.g. by using the for comprehension? This just feels hacky. Naming is one of the most important (and challenging) things in software engineering, and Option’s API is an utter failure (even its name is wrong; when one has an option, one typicaly has many choices, not just one or nothing. Optional is really what is meant here, so why are we afraid of adding a few more letters? Especially given how “precise” some of the documentation is, mathematically speaking, why are we not being precise with English?). If Option is just shorthand for a “list of zero or one elements”, and we get no better methods than what comes with List, then what’s even the point of the class?

I’m not saying we remove all the collection methods from Option, 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’s going on? I mean, there’s a method on Option called withFilter whose documented purpose (I’m not making this up) is: “Necessary to keep Option from being implicitly converted to Iterable in for comprehensions”. Am I expected to believe that it’s ok to have this hacky pile of cruft, but we can’t get a readable method for “do something to the contents if they are there”?

class Option[A] { 
  def ifValue[U]( f: (A) => U ):Unit = foreach(f)
  def unlessValue[U]( f: () => U):Unit = if (self.isEmpty) f
}

def updateName(lastName:String, firstName:Option[String]):Unit = {
  val b = new StringBuffer(lastName)
  firstName.ifValue( (name) => b.append(", "); b.append(firstName) )
}

Which would be less surprising? Couple this with some better scaladoc:

/** This class represents an optional value.  
 *
 * To use as a null object:
 * val optional = getSomePossiblyOptionalValue
 * <pre>
 * option.ifValue { (actualValue) => 
 *   // do things with the value, if it was there
 * }
 * </pre>
 * or
 * <pre>
 * optional.unlessValue { log.debug("missing optional value") }
 * </pre>
 * 
 * To use as a Monad or collection:
 * <pre>
 * val first8upper = option.flatMap( (y) => Some(y.toUpperCase) ).
 *                          flatMap( (y) => Some(y.substring(0,8)) )
 * </pre>
 */
class Option[T] {
  // etc.
}

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.

It’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).

Of course, none of this does save you from null, because Scala is perfectly happy to assign null to anything. It kinda makes the whole thing seem a bit pointless.

My first iPhone App - Part 5

July 18, 2010

See Part 1, Part 2, Part 3, and Part 4 first

I’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.

User Experience

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:

New Add Screen

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

So, I hacked something together.

An option for the UITextField’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:

Details Screen

I then implemented some UITextViewDelegate methods to give the apperance of placeholder text:

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
    if ([textView.text isEqualToString:DEFAULT_TASTING_NOTES_TEXT]) {
        textView.text = @"";
    }
    return YES;
}

- (void)textViewDidEndEditing:(UITextView *)textView {
    if ([textView.text length] == 0) {
        textView.text = DEFAULT_TASTING_NOTES_TEXT;
    }
}

I considered using some third-party controls that mimic this behavior, but didn’t want to get side-tracked adding new frameworks to my app at this point.

User Testing

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:

  • Clicking “Save” on the details screen brought you back to the “new wine” screen, instead of just saving and bringing you back to the top. A minor but obvious annoyance.
  • She kept tapping on the “Choose Varietal” text field, thinking that would bring up the varietal chooser, instead of clicking the much smaller blue “disclosure” button
  • She was a bit sad that the wines we had entered in the app would not be available on our shared Google Spreadsheet

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

The problem with the “Choose Varietal” control had bugged me, too, but I got used to it and didn’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.

As to maintaining the list up on Google Docs, I think I may need to implement this sooner rather than later; I think it’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).

Other Random Bits

I still didn’t get around to setting up iCuke for testing; I really should because I don’t know what missing retain 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:

Icon

(Taken from my original).

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’ve added and don’t particularly wanted to lose them. Not sure how I could gain access to the SQL database to get them out, but I’m currently downloading the 4.0.1 update for my phone and the 2+ GB SDK update (!).

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 *really* need to implement a quicker backup/export mechanism…

My first iPhone App - Part 4

July 08, 2010

See Part 1, Part 2, and Part 3 first

The past week was spent trying to understand the best way to expand my application’s features without have a ton of duplicated code or UI. It was also a learning experience on Core Data. Thankfully, Stackoverflow and its amazing contributers were very helpful.

Core Data Blunders

It started as I made my first foray into implementing the search screen (i.e. the home screen of my app):

Home Screen

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 UITableView. I ended up creating a custom table cell view and I wanted all three to use it:

Custom Cell

Access to Core Data-provided entities is done through objects of the class NSFetchedResultsController, 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.

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

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’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 NSFetchedResultsController instances connected to my table view and having caching turned on and not properly reloading data when switching searches created a situation where they were all pretty confused about the underlying state of the database.

With some judicious management of these instances, as well as disabling caching, I now have a fully-functional “Recent Wines”, “Wines By Rating” and fancy indexed “All Wines” view (index meaning I can jump to wines by letter, a la the Contacts application).

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 UITableViewController instances and NIBs just so I can leave Caching on.

User Experience

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, Proof. We’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’d had there previously. Unfortunately, I had yet to implement the search-by-location feature :) Combing through the “All Wines” view was a bit frustrating. This made obvious several features that are now on the top of my list (some planned previously, some not):

  • Find wines by location
  • Actually entering the location at which I had a wine
  • Location-aware assistance of location (e.g. “Are you at Proof? Here’s what you’ve had there…”)
  • Ability to text-search the “all wines” list

The good news is that my cursory reading of my book and the API docs indicates that these things are going to be very easy to implement.

Objective-C

There’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’s a lot to type out something like:

NSString *stripped = [canonicalName stringByTrimmingCharactersInSet:
                       [NSCharacterSet whitespaceAndNewlineCharacterSet]];

It is 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 issue of Prag Prog’s magazine has an interesting article on iCuke, which I look forward to trying out. I’ve resulted to keeping a text file of test cases that I have to manually run through to make sure I haven’t broken anything, and it feels, well, 1997. The rumours of a Apple’s switch to Ruby are too good to be true, but one can always dream.

Continued in Part 5

My first iPhone App - Part 3

June 29, 2010

See Part 1 and Part 2 first

Just a quick update for tonight. I’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’s a bit odd and not terribly intuitive, but it’s starting to make a bit more sense. Under the covers there’s some sort of dependency injection going on (even if Apple doesn’t call it that) that smells of Spring-style magic; objects get created for me and populated if I do the right thing.

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.

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:

All Wines List

Before delving into my new homescreen, I decided to work up a better color scheme that was more “wine-like”. I’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’t much I have control over via the API for this, so I chose an alternate style of UISegmentedControl that used the “iPhone blue” for the selected state. I think it works OK with the color scheme, though I’d prefer the “merlot red” that I chose for the nav bar and wine type:

Colorrific New Wine Screen

I’m starting to think that my desire to have wine entry confined to one screen might not pan out. The “slot-machine” control will become more and more unusable as more varietals are added, and there’s really no way to even add 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.

Lastly, I took a stab at a better home screen:

Home Screen

This pretty-well represents the ways I think I’d want to navigate the data. Time will tell once I implement these searches, but this seems like a reasonable start.

I also have to say that, despite Objective-C’s overall wackiness, it was pretty easy to put this together and have the “Add New Wine” button bring up the “Add Wine” screen and to have the “All Wines” 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.

Continued in Part 4, and Part 5

My first iPhone App - Part 2

June 27, 2010

See Part 1 first

For the past several days I’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’s Object/Relational Mapper (ORM), for lack of a better description) so that I could actually save some data. I discovered some nuances to using Core Data, as well as a refinement in the UI.

UI

Last night, I had both my girlfriend Amy and my good friend Clay (who is also reasonably into wine) play around with the “new wine” screen. Neither have an iPhone, and there were a few obvious problems:

  • They were very unaccustomed to the “Done” button being in the upper-right corner, as well as the “slot-machine” control
  • Both had trouble with the “Wine Name” concept
  • Both had trouble dismissing the keyboard
  • Clay thought he was entering search terms and not a new Wine

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 “real use” of the app in the field. I quickly realized that the “Wine Name” 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’t even have proper names or appellations. So, I swapped the fields and added some examples in the placeholder text:

Comparison

I also added a title to indicate that this screen is for adding a new wine. Finally, I used the background button trick along with some events on the rating and type controls to dismiss the keyboard if you tap anywhere outside of a text field.

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.

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

Core Data

Backing all this is Apple’s Core Data, which grew out of the Enterprise Objects Framework (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.

Data Model

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

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. “red”, “white”) 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’s a bit cheesy, but I can extract the lists to plist files later. It did give me a chance to play with Objective-C’s blocks feature. I needed to map my list of Varietal objects to a list of strings, so I could compare that list against my default list. While NSArray doesn’t provide a map function, it does provide the equivalent of Ruby’s each or Scala’s foreach. In true Apple/Objective-C style, it’s called enumerateObjectsUsingBlock :)

NSMutableArray *strings = [NSMutableArray arrayWithCapacity:[array count]];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger i, BOOL *stop) {
    [strings addObject:[obj valueForKey:@"name"]];
}];

The stop pointer is an out-only variable that you set to YES to allow for an early exit from the loop. I’m glad they’ve adopted this functional style; I forsee explicit loops becoming just as quaint as GOTOs in the near future.

One thing bugged me about this process, however. I had these generated classes and it wasn’t clear how to add my own methods to them without losing the code every time I re-generated my model. Enter mogenerator. 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’t able to incorporate it into XCode, but I’m happy running in on the command line as needed for now.

Random Bits

I spent more time than I would’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 nil number. It turns out I was confused about when some object lifecycle methods were being called and my pointer to an NSNumberFormatter was, in fact, pointing to nil. Unlike Java, where you’d get a NullPointerException, or C, where you’d get a core dump, it seems Objective-C just returns nil and doesn’t even issue a warning. Very strange. Once I realized that, the solution was obvious.

I’m still not 100% sure I’m structuring my code properly, but Stack Overflow’s stalwart iPhone SDK answerers have been incredibly helpful in pointing me in the right direction.

Next Steps

Now that I’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’s idiomatic drill-down table navigation to filter the database.

Continued in Part 3, Part 4, and Part 5

My first iPhone App - Part 1

June 23, 2010

Background

Last year, I spent most of my free time becoming familiar with Ruby, Rails, and Scala. I’m by no means an expert, but I’m trying to follow the advice of the Pragmatic Programmers and learn a new language/system every year. This year, it’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’t totally unfamiliar, but the iPhone SDK, obviously, is. After working my way through the first several chapters of the Dudney and Adamson’s “iPhone SDK Development” book, I decided I was ready to try my first real app.

First App

My girlfriend and I enjoy wine, but are largely novices. On a trip to Napa we started writing down the wines we’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’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.

User Experience

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 “add a new wine” screen. This will be the screen I spend the most time in, and it’s important to make it fast and easy.

The Google Spreadsheet currently collects:

  • Wine Name
  • Vineyard
  • Vintage (year)
  • Varietal
  • Type (e.g. red/white)
  • Where we had
  • When we had
  • My rating
  • Her rating
  • Tasting Notes

That’s obviously too much for one iphone screen, and, if I’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:

First Attempt

As you can see, I tried to fit the “where” on the bottom, as well as a “enter more information” 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).

My next attempt simply ignores the “add more” 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 “slot-machine”/picker.

Second Attempt

My plan is to load this onto the phone and try using it the next few times I’m out. I figure I can do without the tasting notes or location if it keeps the UI simple

The Code

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 “copyXXX” or “initXXX” to create a new object, you must release it when you are done with it. If you get access to an object through any other means, you should not release it.

// my class has an NSArray called varietals that I'm initializing here
varietals = [NSArray arrayWithObjects:
                  @"Barbera",
                  @"Cabernet Franc",
                  // snip
                  @"Zinfandel",
                  @"Other",
                  nil];

Since I’m not calling an “init” style method, I figured I didn’t need to release it in dealloc. For some reason, this made me decide that I didn’t need to retain it. This caused my first crash and trip through the debugger to figure out what in the heck is going on.

// my class has an NSArray called varietals that I'm initializing here
varietals = [[NSArray arrayWithObjects:
                  @"Barbera",
                  @"Cabernet Franc",
                  // snip
                  @"Zinfandel",
                  @"Other",
                  nil] retain];

Since I needed varietals to survive the method where I was initializing it, I had to retain it.

Other struggles

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

At any rate, I figure if I can get the UX to be reasonably good, the rest should sort itself out.

I’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).

Continued in Part 2, Part 3, Part 4, and Part 5

In defense of vi

June 14, 2010

Sadly, I was unable to attend RailsConf this year. It was in Baltimore, and it would’ve been a lot of fun, but it just wasn’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 DHH speak, I try to never miss one of Uncle Bob Martin, author of the must-go-read-this-right-now Clean Code.

This year, he gave an awesome talk 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 vim). 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 “still” using vim.

I’m sure that unclebob is one of the more advanced IDE users, but it just pains 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.

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’s intuitive and logical. When you understand the “zen” of vim, you can fly through your code, playing it like a musical instrument. It affords muscle memory and allows sophisticated chaining of movement, intent, and action. You can see 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.

Think of it as a piano; it’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.

Are private methods code smells?

May 26, 2010

Having had discussions with co-workers on the utility of private methods and recently on the scala mailing list, there’s been the notion that private methods (or even protected methods) are code smells – 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.

Definitions

While the technical meaning of access modifiers varies with the language, the intent these concepts communicate is what we’re talking about here. I assert that the intent of public/protected/private is (and/or should be) as follows:

  • public - this method is part of the published API and will not change within major versions of the class
  • protected - 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).
  • private - this method was refactored out of a well tested public or protected method 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
  • package private (bonus for Java) - this method was written by someone lazy or ignorant, or by someone who acknowledges that this code should be pulled out into its own class, but hasn’t done so, yet still wants to test it separately, thus breaking encapsulation.

Why would private methods be code smells?

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:

override def contextInitialized(event:ServletContextEvent) = {
  event.getServletContext.log("Initializing our hasher/DB")
  val dirName = event.getServletContext.getInitParameter(
    ShortyServlet.DB_DIR_PARAM)
  if (dirName != null) {
    val dir = new File(dirName)
    if (dir.exists()) {
      if (dir.isDirectory()) {
        val hasher = URIHasher(DB(dir))
        hasher.start
        uriHasher = hasher
        event.getServletContext.setAttribute(
          ShortyServlet.URI_HASHER_ATTRIBUTE,uriHasher)
      }
      else {
        throw new ServletException(dir.getAbsolutePath 
          + " is not a directory")
      }
    }
    else {
      throw new ServletException(dir.getAbsolutePath + " doesn't exist")
    }
  }
  else {
    throw new ServletException("You must supply a value for " 
      + ShortyServlet.DB_DIR_PARAM)
  }
}

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’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’s a cleaned up version:

override def contextInitialized(event:ServletContextEvent) = {
  event.getServletContext.log("Initializing our hasher/DB")
  getDBDir(event) match {
    case Right(dir) => {
      val hasher = URIHasher(DB(dir))
      hasher.start
      uriHasher = hasher
      event.getServletContext.setAttribute(
        ShortyServlet.URI_HASHER_ATTRIBUTE,uriHasher)
    }
    case Left(errorMessage) => 
      throw new ServletException(errorMessage)
  }
}

private def getDBDir(event:ServletContextEvent) = {
  val dirName = event.getServletContext.getInitParameter(
    ShortyServlet.DB_DIR_PARAM)
  if (dirName != null) {
    val dir = new File(dirName)
    if (dir.exists()) {
      if (dir.isDirectory()) {
        Right(dir)
      }
      else {
        Left(dir.getAbsolutePath + " is not a directory")
      }
    }
    else {
      Left(dir.getAbsolutePath + " doesn't exist")
    }
  }
  else {
    Left("You must supply a value for " + ShortyServlet.DB_DIR_PARAM)
  }
}

We’ve added lines of code, but our public method is a lot clearer: we get the dir for our DB; if we get a “right”, we have a usable dir, and if we get a “left” (the Scala convention for an error), we have the error message to use for our exception.

So, is getDBDir now a code smell? This is a private method and, this means that contextInitialized was tested and we extracted the private method as step three of the TDD “Test/Fix/Refactor” cycle.

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

Well, if we did do that, we’ve now actually added a public API to our codebase. Unless we make the new class completely private to the enclosing class, we’ve now introduced a new public class that must be tested and managed as part of our system’s public API.

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

When IS this a code smell?

This was a simple example. Consider a class like SignedUrl in my Gliffy Ruby client. This class has a fair number of private methods and, overall, is pretty large. The private methods are vague things like handle_params and get_signing_key. The private methods aren’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 UrlParams, UrlSigner and UrlAssembler (just off the top of my head). The result would be more smaller classes, each with fewer public and private methods.

What about protected methods?

In Ruby, you don’t see a lot of protected methods. In well-designed Java frameworks (such as Spring), you’ll see them as I’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’m working on has a BaseController that provides common methods to the actual web controllers. Having used protected methods for both of these purposes, I think that, honestly, both can be code smells.

Protected methods as hooks

In the case of providing “hooks”, I think it’s clear that by providing them at all, you are acknowledging that your class might be poorly designed (or that your language lacks the expressiveness to better design it). Consider the venerable (and now deprecated) SimpleFormController, a Spring MVC class that provides many protected-method hooks, one of which is protected Map referenceData(HttpServletRequest request). 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 SimpleFormController overrides this to provide the data as a map.

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

In Scala, however, this could simply take a function:

  def referenceData[A]((HttpServletRequest) => Map[String,A]);

  // ...


  controller.referenceData{ request => 
    // create our map based on the request
  }

In Ruby, the overhead of creating a new class isn’t nearly as onerous, and we could still inject a block as we do in Scala.

Ultimately, I would say that you have to make a tradeoff here, and it has 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.

Protected methods as code sharing

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 BaseController. It has a helper method as follows:

protected Person getAndValidateLoggedInPerson() {
  Person p = this.personService.getPerson(
    this.authenticationService.loggedInUserId());
  if (p == null) {
    throw new NotFoundException;
  }
  return p;
}

Because of Spring MVC, we have specialized exceptions for HTTP errors, such as “NOT_FOUND”. 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.

But, is this a code smell?

We could make a class that does this, turning this code:

Person p = getAndValidateLoggedInPerson();

into this:

Person p = this.personValidatorAndGetter.getPerson();

creating a one method class that has many lines of injected dependencies and other boilerplate with a few actual lines of code.

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. Ultimately, “too much” of this sort of thing should be a code smell, but small bits of this, in the name of simplicity, clarity, and simply keeping the codebase smaller isn’t an automatic red flag.

Conclusions

So, are non-public methods code smells? If we take the wikipedia definition, which is clear that a code smell indicates merely the possibility of deeper problems in your code, then, yes, private and protected methods are code smells.

But, should they be avoided at all costs? Absolutely not. There’s many valid reasons to use them, and they do not deserve the blame for an ill-conceived 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 According-to-Hoyle OO (or functional) design, but we’re not writing code to provide examples of programming paradigms or design patterns; we’re writing it to accomplish something and provide value. And, as professionals, we need to do it at a predictable rate that doesn’t incur too much technical debt.