Kristian Glass - Do I Smell Burning?

Trying out Puppet

Things recently had been a bit quiet on the development front, and when the opportunity arose to get involved in some more “operational” things, I jumped at it. Faced with a bunch of machines spanning production, development slush boxes, and office servers, a general desire to clean them up, consolidate a variety of services, and generally just apply some consistency.

The machines in question had had a varied and chequered history - most were hooked up to authenticate via LDAP but not all of them; some ran SUSE, most ran some version of Ubuntu; various nominally identical/similar/clustered machines had a whole range of differently configured sudoers and packages, et cetera.

I’d already heard a lot about Puppet, “an automated administrative engine for your *nix systems, performs administrative tasks […] based on a centralized specification.” and it sounded rather good. I took a brief look at Chef and Cfengine, which seemed to be the main competitors; Chef was discounted because Puppet seemed to have much more in the way of install-base, community and documentation (I also preferred the idea of a small DSL for configuration rather than “write some Ruby”; Cfengine seemed much lower-level and more in the “I have some scripts, push them out” sense - Puppet’s ability to succinctly express “ensure the package of this name is present” seemed far superior.

So far, my experiences have generally been excellent. Two things I’ve learnt so far:

First, modules are “just” building blocks. If it feels organisation-specific, it’s a service. This is documented in Puppet Best Practices but not something I fully appreciated until after I’d played around a bit more. Still, it all needed a refactor anyway!

Second, Puppet Forge and puppet-module seem truly excellent resources for grabbing other people’s modules to save yourself the leg-work. My initial foray into Puppet involved writing a basic module or two myself, to improve familiarity with the DSL and concepts, but seriously, unsurprisingly you’re not going to be the only Puppet user who has found themselves wanting to add an apt repository and keys or configure munin et cetera.

Ultimately, Puppet has been an invaluable tool so far in my current mission to bring some more sanity, order and consistency to these configurations, and I heartily recommend it.

MBeans and naming collisions

I currently spend some time with a setup where every application has its own embedded Jetty listening on its own port with its own magically-generated properties files for resource configuration. At the moment I’m leading the migration to replace this with a per-machine servlet container (probably Apache Tomcat) with JNDI support. This way we have just one port number to remember, one JMX URL to point JConsole at, far more centralised configuration, and a greater separation of “application” from “system”.

One issue that came up when centralising the JMX setup, and having everything register with the One True MBeanServer, rather than there being one for each application, was handling overlapping MBeans.

Fortunately, it turns out that the people over at Xebia France have some nice public “JMX-based extras to ease monitoring”. In there is the rather nifty “Servlet Context Aware MBean Server” (licensed under the pretty user-friendly Apache License 2.0) which solves this problem beautifully by adding a “path” attribute to each MBean matching the context path of the app.

So, since no two applications in the same servlet container (and thus sharing the MBeanServer) will have the same context path, we achieve MBean naming uniqueness!

They even include the necessary chunk of Spring XML, meaning it took me seconds to try out. All in all, a nice and concise solution that is absolutely trivial to get up and running - thanks guys!

Evelyn

A friend recently told me about some sort of interactive audio story going on via Spotify. Turns out that if you search for “B1W8”, you get taken to a track called “Evelyn” (for the lazy, a HTTP link and a Spotify URI) consisting of a short spoken story that concludes by giving the listener a choice of two codes they can choose from to continue the story.

As someone who can’t resist a bit of a mystery, and who has a small obsession with mapping choices, I couldn’t resist exploring the whole thing. It appears to be a (rather nifty seeming, if selective) advertising campaign for the release of a new album, “Happiness”, by a band called “Hurts”. Many paths lead to (in-game!) death or failure, but a number lead to segments of songs from the album. All in all, I found it really engaging, and while the music isn’t of the sort I normally enjoy, I think I’ll find myself listening to them occasionally on Spotify.

For those who want spoilers, I built a map of the whole story, the source for which is on GitHub.

Java Melody

While idling in #spring on Freenode, I saw someone mention Java Melody as a good monitoring tool, so thought I’d give it a quick spin.

I significantly overestimated the amount of effort installed, and was genuinely impressed. I admittedly haven’t played with any of the more advanced bits, but basic installation is so incredibly easy and featureful that I’m more than satisfied for now.

First step, pull it into my project. I’m using Apache Maven, so this was just a matter of scrolling to the Dependencies section of the documentation and copying in the requisite chunk of XML to add three dependencies and a repository to source them from.

Second, hook it up. In my case, this just involved scrolling back up to the web.xml section, and copying in another small chunk of XML to add a filter, filter-mapping and listener.

A whole 5 minutes later, and it was just like the screenshots! Charts of various attributes, request statistics, system information, thread monitoring and more. The app I’m currently working on is pretty light-weight, so I don’t have any database connections, batch jobs or other advanced fun to monitor, but if it’s anything like my experiences so far, it’ll be a breeze to sort.

At some point I’ll make time to try out the beta “Deployment on Tomcat without modification of monitored webapps” so I can get monitoring across a range of apps without them needing to care or know. For now, I’m definitely genuinely very impressed!

JIRA

I’ve finally bought myself a copy of the rather fabulous Atlassian product, JIRA, with which I plan to organise all my side-projects. Their “Get Started for $10” is, as well as a fine piece of salesmanship, incredibly beneficial to me.

I’m still sorting out a VM that can cope with running Java - my current provider offers excellent quality cheap lightweight slices, but I haven’t yet played with combining them, and a plain Tomcat with no actual apps (beyond the manager) proved too weighty for a single slice. So my meaty-but-bulky server that runs in the house appeared an excellent staging ground.

All my servers run Debian Lenny, normally with only main and contrib areas enabled, so a little bit of faff was required to actually get a Sun JRE. A little while later, and I was ready to go, so I ran ./bin/startup.sh, only to be faced with…

Detecting JVM PermGen support... PermGen switch is NOT supported and will NOT be set automatically.

The first time, I didn’t notice this, and went to fill in the JIRA install page, during which it (quite reasonably) fell over as it ran out of PermGen. A quick look in startup.sh showed it calling setenv.sh which called permgen.sh, which contained this little snippet:

# This will try to detect whether the PermGen command line arguments can be used.

On an IBM JVM, the default permgen arguments are not valid</code>

Well, I definitely wasn’t running an IBM JVM! However, a quick sanity check of my environment lead me to observe that I had no JAVA_HOME set. Revisiting permgen.sh, I noticed that if there was no JAVA_HOME, the detection script would leave JAVA_PERMGEN_SUPPORTED with its default value of false! A quick export later, and:

Detecting JVM PermGen support... PermGen switch is supported. Setting to 256m

Lo and behold, it turns out things operate a lot better when you have a working environment! I’m unsure whether to go down the bug-filing route though - expecting the user to have a not-broken environment seems like a pretty reasonable premise, though in this case, it would probably be something fairly easy to handle better.

Regardless, I’ve set my environment up properly now, and so have a working JIRA instance, and a fun time ahead of me setting it all up, so here I go!

Objective-C and the Delegate pattern

Misunderstandings about delegates quite frequently come up on #iphonedev. This post should hopefully clarify a few things; arguably it doesn’t contain anything beyond that covered in the Apple docs, but hopefully presents it all in a more straightforward manner.

First, the basics. Everyone loves MVC right? The basic premise is that the View layer is dumb presentation, the Model is a straightforward data-store, and the Controller contains the logic, wiring and glue. Since most iPhone apps tend to be light on the Model-side, it’s common to combine the Model and Controller, but that’s just a common convenience.

So, you’ve got your view, and you want to add a button to, say, send you a “Button Pressed!” email. Now you could subclass your generic Button class and override the “buttonWasPressed” method, adding the “send email” code there. That doesn’t fly so well with MVC though, as now your View is doing Controller-type stuff. So, instead, you have the Button just forward things like “buttonWasPressed” on to another object, its delegate (a quick google for “define:delegate” gives “transfer power to someone” - pretty much!). Now your Button is free from pesky decisions like what to do when it’s pressed, it just passes on the message and lets its delegate (probably the Controller) handle it.

Now, here’s where we hear the question “Now I’ve got delegates, how do I deal with object ownership and such?”. This can also manifest itself as “My object’s delegate goes away and then my program crashes!” or “I have a retain cycle!”. There are some slight subtleties involved that frequently catch people out, but basically:

An object has no claim on its delegate

An object’s delegate is just something to which it sends messages, nothing more. Specifically, this means that it should NOT retain its delegate. Just in case that wasn’t clear, @property(retain) id delegate; should be taken out back and hit with a shovel until it agrees to stop retaining, and becomes a nice happy healthy assign property.

In almost every case, an object with a delegate will be the responsibility of its delegate, for example a UIViewController creating a UIButton, or a model object kicking off an asynchronous NSURLConnection. The delegating objects don’t want to lay claim to their delegates, they just want to message them. If they retained their delegates, cue the aforequestioned (I wonder if that’s a real word) retain cycle.

Along that line, it’s not the delegating object’s responsibility to deal with its delegate going away, but its creator/manager etc. So, if at init-time my FooObject creates a BarObject and sets itself as that BarObject’s delegate, it should set that BarObject’s delegate to nil in -[FooObject dealloc] prior to performing a [barObject release];. There’s lots of Foundation and UIKit code that uses delegation without explicitly using the word delegate, e.g. UIButton and NSURLConnection as mentioned above. In UIButton’s case, it’s unlikely that a Controller will go away before its View, thus clearing a UIButton’s targets can be ommitted; in NSURLConnection’s case, this is why -[NSURLConnection cancel] should be called at dealloc time, to ensure that the connection isn’t going to message its “delegate” after it goes away.

I hope that this has gone some way towards answering some of the common delegation queries, and that people find it useful. As ever, all input welcome.

Types and printf

Came across this post about printf-ing fixed-size types today and am very glad to have found macros for printf! Developing for the iPhone, with its platform-specific typedefs like NSInteger (either a long or an int), then seeing people just assuming one or the other when printf (or similar - I’m looking at you NSLog() and -[NSString stringWithFormat:]!) always pains me somewhat.

The advised solution was to upcast to long and use the specifier for that. Not bad, and nicer than the (ugly in retrospect but still preferable than doing it wrong) solution I had involving -[NSNumber numberWithInteger:] and -[NSNumber stringValue]! However, it won’t really do for fixed-size types, so it was nice to see that it was an already-solved problem!

Code Tools

I think I’ve hit on one of the biggest reasons I prefer the parts of my job that involve writing Java to the parts of my job that involve writing Objective-C.

No it’s not that the Java code is a server while the Objective-C code is an end-user-facing client (though I do prefer that). No it’s not that I get generics in Java but don’t in Objective-C (though I do prefer that). No it’s not that Java is a lot easier to statically check than Objective-C (though…).  It’s not that Java is more Simula-style while Objective-C is more Smalltalk-esque (and I’m undecided on that one!)

It’s the amount of tools that I get.

I can fire up Eclipse with a chunk of Java code, and easily extract Interfaces (protocols) or superclasses, rename entities, push code down or pull code up, get a list of functions I might want to override via tab completion, and much more. Tonnes of Java-friendly Continuous Integration systems exist that take mere moments to set up. Dropping in an analysis platform like Sonar is trivial, which gives me test coverage metrics, lots more static analysis, and other such useful information. I get tools like Maven that make dependency management easy.

I start Xcode and open some Objective-C. I get the Xcode refactor tool, which is flaky at best (and as I go to try it right now to see what options it gives me, it’s just greyed out, making it entirely non-obvious what it lets me do). Continuous Integration wasn’t actually too bad to set up, except Hudson (the CI system we use) seems highly Java-focussed, so I’m having issues wiring in warning counts and test failure counts - I acknowledge that as a fault of the choice of tool, though I’m yet to find anything else that seems significantly better for this, and am open to recommendations. Static analysis, well, I’ve got the Clang Static Analyzer, which, while a great piece of kit, seems incredibly young, and there’s only so much it can pick up. For dependency management, the best we’ve found is svn:externals, which just feels nasty, but is quite honestly the best solution we’ve found so far. Sure, I can measure test coverage with gcov, but the process is far more involved and takes much more effort and time than being able to just throw things at Sonar and ask for a percentage.

Now, I recognise that some of these problems are as much to do with the nature of the language as they are with the tools - there’s only so much static analysis that can be done on code written in a dynamic language like Objective-C. However, hopefully this shows some of the reasons why sitting down to write Objective-C in Xcode feels like such a massive step backwards.

Streamlining Life

I’ve recently become quite a fan of “self development literature”, for want of a name with less risk of sounding pretentious. I recently finished David Allen’s Getting Things Done and Dale Carnegie’s How To Win Friends And Influence People, and found them fascinating reads. They don’t claim to offer miraculous improvement, they simply offer anecdotes and advice from the experiences of their (seemingly rather accomplished) authors. I’m still determining exactly what I want to take from them, but it’s been a thoroughly positive experience.

One of the most productive steps I’ve taken recently has been to adopt Martin Keegan’s advice for Not Wasting Time on Computers. With the amount of time I spend online, then something akin to Amdahl’s Law would appear to highlight this as a prime target for improvement. A shortcut homepage has saved me a great amount of time, though I have two - a “personal” one, that is really little more than a list of web comics and periodicals, and a “work” one that is mostly useless without being on the work LAN/VPN. The former will be hosted on my personal website as soon as I get that sorted, which is on my new revised GTD-style TODO list!

GNU Screen has been wonderful at providing a persistent environment, whether I’m at home, at work, or wandering along with my trusty N810. Centralisation of my data has been a desire for some time - avoids fragmentation of data, and lets me switch seamlessly from place to place.

Finally, aggressive email management. I receive vast quantities of email about a vast quantity of subjects, and having them all arrive in the same inbox would be a nightmare. Unlike Martin, I’m quite happy with the version of alpine currently packaged for Debian stable, though must move the filtering location to something a little more under my control.

All of these tips have vastly helped to improve my productivity; I can’t promise they’ll do the same for you, but hey, maybe my account will help.