Cliff Hacks Things.

Friday, March 09, 2007

Cesta lives!

I've been putting in a lot of work on Cesta, my network analyzer, due in no small part to continual goading from clee. (He has a Mac now, and is trying to load it up with shiny Mac software.)



I hadn't touched Cesta's code in over a year, and it was getting pretty crufty even then, so I didn't bother trying to modernize it. Instead, I'm applying a marvelous technique I learned from John Brewer: TONSO, or Take Off and Nuke the Site from Orbit.

(It's the only way to be sure.)

The interesting thing is how fast it's come along. I bootstrapped the core system (with an Ethernet decoder) in an evening of work, while distracted by clee and Ben-from-Apple. Starting from a clean slate really helps you reduce a system to its essentials -- and working in Objective-C didn't hurt either. (Still one of my favorite languages of all time.)

I've rebuilt most of what the last Cesta generation could do, and killed off a number of ingrained-but-incorrect assumptions in the old domain model. We should have feature-parity with Wireshark in the not-too-distant future, which is not a slam against the Wireshark devs by any means -- they're very smart. No, it's a tribute to how easy developing Mac software in Objective-C has become.

We're targeting Tiger-and-later with this rev, whereas the original Cesta worked all the way back to 10.2. This makes things a lot cleaner: Mac OS X really is evolving at a breakneck pace, and while all the old APIs are still supported (and much faster), there are new ways of doing everything that are so much better.

Case in point: Cocoa Bindings. Much of the code in Cesta Of Old was dedicated to shuttling pieces of data onto, and off of, the screen. I'm a user-interface geek, so it had to be blindingly fast, absolutely intuitive, and as fluid as Mac apps are expected to be -- and I paid for my high standards in code.

Now? There is no code.

Using Cocoa Bindings, I wire up my UI widgets to my underlying domain model using Interface Builder, and the runtime figures out how best to move and cache the data. The new Cesta UI is entirely Bindings-driven, leaving the whole user interface as a thin projection of the underlying objects -- from the chooser that lets you pick the network interface(s) to capture from, right up to the three-paned packet list and dissector.

If I have to, I can drop in optimizations where needed (Objective-C's category mechanism keeps it clean) -- but thus far, it hasn't been necessary. Cocoa Bindings is fast; far faster than I expected, and they say it'll only get faster with time. It doesn't break a sweat displaying hundreds of thousands of decoded packets in a table. I am impressed.

(I met the folks behind the Bindings API at a recent Cocoaheads meeting, and not only do they produce great things, they're also very friendly and tolerant of n00b questions.)

Not having to hand-code the user interface has freed me up to work on more interesting parts of the application. In the two weeks that this Cesta codebase has been under development, we've added features that I only dreamed of in the last rev. For example, Cesta can now integrate data from any number of network interfaces in a single capture, and can attach and detach interfaces on the fly. (These changes are even recorded inline, right in the capture, for future reference.)

It's also grown a general framework for finding, highlighting, and explaining problems in packets. If an IP checksum is wrong, for example, it's highlighted in the UI, and the user can see a localized explanation of the issue.

We have found one issue, however. clee is totally new to Cocoa, just having cracked open the Hillegass book, and the Cesta codebase is total greek to him -- even though he's a very sharp programmer, fluent in half a dozen languages.

I can't blame him. The main difference between this Cesta and the last is that I now fully grok the Cocoa application/document architecture. It took me a couple years of diligent study to get everything right (because some important parts of it are not terribly well-documented -- and I didn't have the Hillegass book). To a newcomer, the control flow is almost entirely opaque. Sure, you can see that CSCaptureDocument seems to be some sort of document that holds a capture, but it's never created anywhere -- and neither are most of the other classes! How on earth do they talk to each other?

The answer, of course, is that a good chunk of the application logic is effectively hidden. It's not in the source code; it's in property list files, in the Interface Builder nibs, in interactions with closed-source frameworks. To a programmer used to programming, well, code, and accustomed to fully open-source systems, Cocoa can be pretty mysterious. To really understand a Cocoa application, particularly one that has drank as deeply of the Kool-Aid as Cesta has, one must understand all these non-code resources -- and, in some cases, read the API docs on every dependent class, trying to figure out who calls what delegate method and why.

Ironically, the loose coupling that makes control flow hard to understand is also one of Cocoa's greatest strengths. (Though part of the problem -- possibly a large part -- is Xcode, which is firmly lodged about six years behind the IDE state-of-the-art. From a Java perspective, it feels like my 1999 work in Forte, rather than my 2007 work in Eclipse.)

To diverge even further from the alleged topic of this post, this also worries me on my applications at work. Us loosely-coupled object systems guys are leaning pretty heavily on dependency injection and event-driven applications these days, and it may come to the point where the only way to understand the flow of control is to step through the app in a debugger. Not an ideal solution.

Anyway. Coming back around to Cesta, there's one other point of interest: we'll be open-sourcing this version, most likely under a BSD license. I've been out of real open source development for too long. It'll be good to be back.

Labels: , ,

1 Comments:

Post a Comment

<< Home