MarsEdit 1.1.3

February 26th, 2007

When the news went out last Thursday that Red Sweater had acquired MarsEdit, the reaction from the public was just amazing. I’ve never heard so much positive feedback in a single day. People are excited about MarsEdit, and they’re not afraid to let me know :)

How am I going to reward users for their enthusiasm? By releasing updates. With fixes. And features. And stuff. It’s been four days since the acquisition, and I’m happy to announce the immediate availability of MarsEdit 1.1.3, a free update for all registered users.

MarsEdit 1.1.3 is mostly a “bug-fix and rebranding” release. All the little spots where the app takes you to a web page or whatnot are now updated to point to Red Sweater instead of Ranchero. The release includes three pretty significant bug fixes. Two that should please long time users, and one that might prevent scaring off new ones!

  • Fix a bug with LiveJournal blogs that contain Unicode chars
  • Fix the infamous “Preview Flickering Images” bug
  • Fix a slow memory leak when text filters are applied in preview

Another exciting change in this release is the addition of Sparkle for automatic software update support. I’ve tweaked the basic Sparkle Plus profile information so that users can, if they choose, include information not only about their computer and operating system, but about the blogging systems they’ve set up blogs for in MarsEdit.

So now when you “Check For Update,” you’ll also be sort of voting for your preferred blog systems. This isn’t about winning or losing, but about allowing me to be pragmatic in choosing which features to prioritize in which systems. Not to say I won’t look at support for new systems, but I’m very interested to see what current users are running, so I can do everything possible to keep them satisfied.

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…