Red Sweater Acquires MarsEdit

February 22nd, 2007

You read that right, no need to run for another cup of coffee. MarsEdit, the kick-ass, intuitive web-publishing powerhouse which I’ve been using to write entries here since I started blogging almost two years ago, is now part of the Red Sweater family of products. What an exciting day!

This is the first time I’ve clicked “Send to Weblog” since the acquisition was completed. It was as easy as it ever was, but now I get to share in the pride of that ease. Man, that felt good.

Check out the press release, and be sure to send it along to your favorite news editor or blogger. I know I will! Also be sure to check out the nifty Q&A session Brent Simmons (original developer of MarsEdit) and I took part in, to help put the acquisition into perspective.

This is a classic “everybody wins” situation. Users are going to see a lot more development activity, Brent and NewsGator are happy to see the application in my capable hands, and I get the satisfaction of steering the future of one of my favorite applications. Precious!

For those of you who aren’t familiar with MarsEdit, it’s worth taking a look. Whether you’re a seasoned blogger or just thinking about getting started, this application has power and ease-of-use that will knock your socks off. Long story short, if you’ve got one or more blogs, MarsEdit will make posting to them effortless and reliable. Just what you’d expect from a Mac.

People sometimes remark on the relatively large quantity of content I publish here. A major reason for that is MarsEdit makes it easy to collect my ideas, refine them, and publish them. I don’t think I could handle writing all these entries, managing the drafts, correcting mistakes, etc., if it weren’t for the convenience of MarsEdit.

Since I’ve been writing so much about a certain Cocoa-Java port lately, I should probably make this completely clear: MarsEdit is not the Java-based product that I recently acquired. MarsEdit is completely Objective-C based from the get-go, and I couldn’t be happier about that. It means that I can acquire it and immediately make it available for download. In fact, the version you download today still has NewsGator’s name in it :) I’ll be releasing an update soon.

So what’s the Cocoa-Java application? I can’t announce everything on one day can I? Stay tuned for more exciting news in the weeks to come.

Reaction To The News

“MarsEdit Family”

Greg Reinacker (NewsGator CTO and Founder)
Brent Simmons (MarsEdit’s original developer)
Gus Mueller (Former MarsEdit Developer)
NewsGator Daily Blog

Press

Ars Technica – Infinite Loop
Daring Fireball
MacGeneration (French)
MacMinute
Macnews.de (German)
MacsimumNews
MacUser Blog
Macworld
Macworld UK
NonStopMac
TUAW
901am New Media News

Blogs

Paul Kafasis, my trusted confidant, spilled the beans last night in a vaguely worded post. Check out the subtle hint in the permalink URL. But nobody really picked up on it. Somebody asked me if I was becoming an employee of Rogue Amoeba :)

Baron.vc
Erik Barzeski
Michael Boyle
Paul Burd
Simone Carletti (Italian)
Dave Dash
Luis de la Rosa
Evan DiBiase
Michael Dupuis
Geek Patrol
Grimaldello (German)
Steve Harris
Will Henderson
Takaaki Kato
Paul Kim
Steve Kirks
MacStansbury
Michael McCracken
Marcus Puchmayer (German)
Switchblog
Startup Squad
Jon Trainer
Michael Tsai
Kevin Walzer
Justin Williams
Mike Zornek

Cocoa-Java Porting Step 2: Life Support

February 20th, 2007

In the first part of this series, Triage, I talked about some of the earliest steps I took in the process of purchasing a Cocoa-Java application and porting it to Objective C. In this article, I’ll discuss some techniques I stumbled upon for working with a legacy Java code base while gradually migrating functionality to Objective C. In keeping with the medical metaphors, I’m calling this segment “Life Support” because, while the project in this state is by no means dead, it’s far from healthy.

What does it mean for a project to be alive? I’m adopting a definition of life that is roughly “as freaking close to original functionality as possible.” That means the application needs to be launchable. It needs to perform its advertised purpose. Ideally, a project in “life support” should be less than a week away from “shippable” at any time.

The bad news? To maintain this standard, you might put up a ton of scaffolding code today to keep the application alive, only to tear it down in a few days when the complementary structures in another part of the application have been comparably revised. Some would argue that it’s better to bid farewell to the life of the application, and commit to a dark period of zero functionality while everything is redesigned and/or ported to the desired specification. This would certainly make for less “throwaway” code, but an unfamiliar, non-functioning application scares the living daylights out of me.

Clean Code In A Strange Land

Back to the specific project at hand. You’ll recall that during triage, I discovered some cool Objective-C hacks that allowed me to fix the heinous crashing bugs on Intel, while leaving essentially the entire Java code base unchanged. This trick relied on a basic truism of the Cocoa-Java runtime: calling methods on Java objects from Objective-C is relatively easy, while calling back to Objective-C from Java is not.

To call a Java class method from Objective-C, you look up the class by name, and send it a message that will, by convention, map to an associated Java class method. When the Java class you’re messaging is in fact a subclass of a Cocoa class, the messaging can feel extremely natural. For instance, assuming you’ve got a Java-based Preferences Window controller, this is how you might message it to show its window, from an Objective-C based class:


Class theClass = NSClassFromString(@"PrefsController");
NSWindowController* myPrefs = [theClass sharedInstance];
[myPrefs showWindow:self];

Going the other direction, from Java to Objective-C, requires compiled-in bridge code. Much of the Cocoa frameworks from around the 10.2 era is represented in the bridge code provided by Apple. Everything else, including any custom Objective-C classes you’ve written, would require new bridge code to be generated and linked in to your application. This is apparently still possible, using Apple’s unsupported and poorly documented “bridget” tool. Personally I didn’t want to touch it. The idea here is to eventually get rid of the Java code completely, so I don’t want to waste a lot of time making it easier for it to stick around.

So here’s my approach: pragmatically move stuff from Java to Objective-C, keeping in mind that everything I move “up” must not be depended on by any other Java code. For example, if I move the Preferences controller from Java to Objective-C, then no longer can any Java code say “PrefsController.sharedInstance().showWindow(this)”. So deciding how to proceed will require at least some sense of the dependencies between the various Java classes in my project.

I was hoping there might be a nifty way of automatically gathering this information from Apple’s class diagram tool in Xcode, but it turns out not to be as entirely useful as I’d hoped. I used a combination of its member variable information, combined with some brute-force global text searches, to roughly plot out a list of all classes, and the Java-based classes that they depended upon. For instance my Java-based application delegate depended upon the Java-based document class, which depended on several Java-based model classes. So I can’t really port the document or model classes to Objective-C, but I can port the delegate, because no other Java code links directly to it.

The idea is to look for “childless nodes” in the class hierarchy, and decide whether it is pragmatic to port them no or later. As classes are migrated up from Java to Objective-C, it reduces the amount of Java code in the project, while keeping the application functionally identical to its former self.

The Objective-Java Chimera

Obviously things are never quite so simple. In a real project, dependencies between classes never fall into a perfect tree structure where one can simply pluck classes one-by-one from the top of the tree. In some cases, two classes might mutually depend on one another, in which case it would make sense to port both of them to Objective-C in one fell swoop. Or maybe the vast majority of a class is not dependent on Java, but one small component is. It might make sense to port the class with the caveat that things will not be completely functional, for a short period. The application isn’t dead! It might be wheezing, but it still basically works.

I came up with a technique which I found pretty useful, especially for some of the largest classes in the project. What if a class is half dependent on Java, and half not? It would be great to be able to port just the half of the class that can make it to Objective-C, while postponing the rest for later. Using a “Chimera” object that is conceptually part Java and part Objective-C, I was able to achieve this monstrous goal.

I applied the technique first to a custom NSView subclass, because I observed a slowness in drawing that I guessed might be sped up by minimizing the amount of cross-bridge messaging and structure conversion that going on every time the view was drawn. In any case, I knew I was not confident about applying Shark measurements to a Java class, and would have a much easier time fine-tuing the performance if all drawing was done in Objective-C. The custom view in this case was a major piece of the application, though. It had its hooks into the model code, and other classes had their hooks into it. And it was relatively huge. It made a great candidate for the Chimera technique.

The technique depends on Objective-C’s ability to forward messages a class doesn’t implement to another class. So for most practical purposes, an Objective-C class can “wrap” another class such that clients of the class think all the work is being done by the wrapper. In this case, we want to sneak a new CustomView class in to the runtime, where the nib file will unarchive and automagically contain an instance of our view instead of the old Java one. Then we’ll fulfill the contract of the old view class, both by implementing our own methods and by dispatching to it when necessary. Simplifying the situation somewhat, converting a Java class to a Chimera class involves the following steps:

  1. Rename the Java class to something new. For instance, “CustomView” becomes “JavaCustomView.”
  2. Create a new Objective-C class, named after the original. In this case, “CustomView.m” is our new source file.
  3. Implement message-forwarding methods. These are where the magic happens.

That’s the skeletal Chimera. Now you can add whatever methods you like in ObjC and they will automatically take precedence over the Java equivalents. You can even rename the Java equivalents if appropriate, and partly implement methods in ObjC. For instance, you could implement “awakeFromNib” such that it first called the Java class’s “javaAwakeFromNib” and then proceeded to do whatever Objective-C based setup was appropriate.

So which are the “message-forwarding methods” that you need to implement? In my experience, it’s important to implement respondsToSelector:, methodSignatureForSelector:, and forwardInvocation:. In each case, you’ll want to dispatch to the underlying Java object, but only when appropriate. To have an instnce of the Java object around, you’ll need to add code that, at init time and awakeFromNib time, respectively, instantiates and configures the underlying class. You may also need to do some patching up of IBAction connections or whatnot. The fine-tuning will all be very application-specific.

The idea for the “responds to” and “method signature” methods is you want to return the union of your Objective-C class functionality and the Java class functionality. So first ask your superclass to handle the method, and then only if the result is NO or nil, pass-through to the Java class for further inquiry. The forwardInvocation method will only be reached if nothing in your class could handle the method, so you can just blindly pass these through to the Java class, if it will take them.

To make this work, you have to manage the dependencies between the two halves of the Chimera. For instance, it might make sense to maintain redundant copies of the IBAction outlet variables, so that both sides of the world have access to “outside the class” dependencies. A pitfall is you might end up storing data in one half of the Chimera and not realizing that the other half is still trying to depend on it. I never said this wasn’t going to be messy, but it gets the job done.

Applying this technique essentially opens the doors wide to staging the port. You can carefully port parts to Objective-C while keeping the application alive. You’ve got a full-fledged Objective-C class to pass around in “clean land,” while Java objects continue to operate as necessary on the Java subset of the class.

A Healthy Outlook

In the next and final installment of this series, I’ll talk about the grunt-work of actually going the final mile, and what we gain by getting there. Porting all those Java classes to Objective-C is fairly easy work, but it’s tedious. I came up with some tricks that might affect your approach in attacking a similar problem.

Daring Valentine

February 14th, 2007

I don’t often visit the Daring Fireball home page, since I’m a dues-paying member and get the luxury of full-content feeds delivered straight to NetNewsWire.

But today I found myself there and was charmed by this minor tweak to the usual logo:

Nice touch! Amy and John, sittin’ in a tree…

Hexy Little Thing

February 14th, 2007

I’m working on an application now that uses a custom document format. Since my code manipulates this format and spits it back out to disk, I find myself frequently examining the resulting documents using Peter Ammon’s excellent Hex Fiend to examine the resulting files, and make sure the content is still format-compliant.

But while I’m debugging the code that actually does the manipulation, I find myself stuck doing stupid stuff like:

(gdb) p/x ((char*)[imageData bytes])[14]
$1 = 0x28

Ugh! That’s no way to win the software wars. It occurred to me today that what I really want is something like Hex Fiend built right into the debugger. Why shouldn’t I be able to hex-dump my NSData objects directly from the console? It turns out I wasn’t alone in this wish, because Dan Wood recently published a category on NSData that allows just that.

By simply compiling the NSData category into a given application, you give NSData’s debugging description superpowers. For instance, here’s me at the gdb console, examining the contents of the favicon.ico response I just received from NSURLConnection:


(gdb) po imageData
NSData 350 bytes:
00 00 01 00 01 00 10 10 10 00 00 00 00 00 28 01 | ..............(.
00 00 16 00 00 00 28 00 00 00 10 00 00 00 20 00 | ......(....... .
00 00 01 00 04 00 00 00 00 00 C0 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF | ................
FF 00 00 00 FF 00 00 00 EF 00 00 00 DE 00 00 00 | ................
CE 00 00 00 BD 00 00 00 AD 00 00 00 9C 00 00 00 | ................
8C 00 00 00 7B 00 00 00 52 00 00 00 42 00 00 00 | ....{...R...B...
29 00 00 00 10 00 00 00 00 00 00 00 00 00 11 11 | )...............
11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 | ................
11 11 11 11 11 11 13 31 11 11 12 55 21 11 1B B1 | .......1...U!...
13 D8 7F FF FB 31 1B B1 6F D4 FB 65 9F D2 1B DB | ....1..o..e....
FB 21 84 11 15 F5 1B FF FC 41 12 78 8D D1 1B B1 | .!.......A.x....
3C C1 2D FF FB 51 1B B1 1A D1 5F 71 11 11 1B C5 | < .-..Q...._q....
BF 81 1C C7 58 61 1A FF C6 11 12 BF FF 81 12 54 | ....Xa.........T
11 11 11 13 52 11 11 11 11 11 11 11 11 11 11 11 | ....R...........
11 11 11 11 11 11 11 11 11 11 11 11 11 11 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00       | ..............
Current language:  auto; currently objective-c
(gdb)

Dan’s code is pretty much perfect as-is, but I couldn’t resist tacking on some additional features. His category hardcodes the dumped data to 1024 bytes, but in my case there are times when I’m interested in seeing more. I added two category methods to the mix:


// startOffset may be negative, indicating offset from end of data
- (NSString *)descriptionFromOffset:(int)startOffset;
- (NSString *)descriptionFromOffset:(int)startOffset
				limitingToByteCount:(unsigned int)maxBytes;

Now I can peek at a specific subrange, or expand the default limit of 1024 bytes. I can even peek at the end of a chunk of data, by specifying a negative offset:


(gdb) po [mDocumentData descriptionFromOffset:-11]
NSData 109 bytes (showing bytes 98 through 109):
02 43 41 54 41 54 4F 4E 49 43 00                | .CATATONIC.
(gdb) 

Wow! This is a pretty huge addition to my debugging and development toolbelt. Many thanks to Dan Wood for providing the ready-made code to speed up my implementation.

NSData+RSHexDump is freely available to you, under an MIT license.