Programming Archives


September 08, 2003

Java 1.4.1 Update

Apple has released an update to the 1.4.1 JDK for Mac OS X, hopefully this will fix the majority of my complaints about it and enable it to run jEdit without any problems. I hope they at least fixed the crasher that would take down the entire window system.

I've been running jEdit with the 1.3.1 VM for a couple weeks and it works fairly well, but the lack of scroll mouse support is really annoying.

Posted by kstaken at 09:23 PM | TrackBack

Cocoa Literature List

Cocoa Literature List
is page of Cocoa articles broken down by topic. Lot's of good stuff listed there.

Posted by kstaken at 09:09 PM | TrackBack

August 27, 2003

Java on Mac OS X

I mentioned in my rant about window proliferation on Mac OS X that I was looking at using JEdit as a solution. It turns out JEdit is almost a perfectly workable solution, through various plugins I was able to get it to do everything that I wanted and it felt close enough to a native app to not drive me crazy. Unfortunately, all is not well in this world.

The JDK on Mac OS X has some serious problems when running JEdit. With the 1.4 JDK the VM crashes far too often. This shouldn't be JEdit's fault as it's the VM that's crashing. Unless jEdit is running some native code a Java app should never be able to crash the VM. This wouldn't have been a huge deal as JEdit is really good about saving its current state, just restarting the app is a minor annoyance. However, the real problem is that sometimes when the VM crashes it takes the whole WindowServer process down with it. This results in instant termination of all your running apps and getting logged out of the system. To say that's a bit of a problem is an understatement.

When you install jEdit it recommends that you use the 1.3 VM. Unfortunately doing this also results in the loss of a number of functions (in particular mouse scroll wheel support) and substantially changes the display of the app (i.e. tab layouts). Also if you turn on the hardware acceleration it has problems with garbled text and incorrect positioning in text areas. Running without mouse scroll wheel support is extremely annoying.

I'm quite disappointed with the current situation of Java on Mac OS X for running GUI apps. I've had no problems with it running server apps, it seems most of the current problems can be traced to the things they're doing with Swing, i.e hardware acceleration and the switch to the Cocoa toolkit for GUIs in 1.4. This stuff will be great once it's fully stable, but I've heard nothing about progress in this area for some time.

I'm still trying to make do with jEdit running on the 1.3 VM with no hardware acceleration. However, I would definitely prefer to be able to take advantage of the 1.4 features, that scroll wheel thing can really spoil you.

Posted by kstaken at 11:08 PM | TrackBack

August 19, 2003

Java Programmers Unite: Say NO To Python

In his comparison of Java and Python productivity, Steve Ferg notes that: A programmer can be significantly more productive in... Via: Nu Cardboard

This is kind of funny, but I do agree with the assessment that Python is vastly more productive then Java. I spent several years working with Java and in retrospect it was astonishingly unproductive. This included a project where I converted a team development effort from Perl to Java for all the reasons that are commonly stated for making such moves. In retrospect that was a horrible decision. I did it under the belief that we would have a more scalable process, more stable code and ultimately faster development of new applications because of this. It never really worked out that way and this was with Perl. I really regret making that move even though Perl is a far worse language for team projects then Python is. Over the last few months I've been working more and more with Python and I'm pretty convinced that the difference in raw productivity makes up for any loss from static typing and a compilation phase. I believe the same applies to Perl, although not quite as much.

What's important to understand about running scripting languages in large projects is you have to have good tests. When we were using Perl we had lots of unit tests, however when we switched to Java the code itself took too much precedence and the creation of unit tests suffered. Sure it's nice to have a testing policy, but schedule pressure can have nasty ways of interfering, especially when the overhead of the language is slowing things down. In the end our system became even harder to change then when we started out. The problem of course is that just because a language is statically typed and compiled it does not remove the need to write tests. So you're now taking on the burden of a less productive language while not shedding the burden of writing comprehensive tests. In addition, because of the static typing, compilation phase and OO access protection features of languages like Java your tests have also become much harder to write.

Because of this, I'm really starting to believe that efforts to improve software quality by tightening up the language features through stronger typing and rigid language features are really the wrong approach. I tend to believe a more profitable future will be attained by making languages easier to use and building in mechanisms that improve the testability of code. My feeling is that it isn't really important that you pass the right type to the right method, what's important is that the code does what it is supposed to do. Passing the right type to the right method may be a precondition for this, however it is not sufficient to guarantee it, and that to me just makes it overhead. Tests are still required. If dealing with all the static typing and compilation phases makes test development suffer, then I tend to believe those features are counterproductive and just get in the way.

Posted by kstaken at 10:46 AM | TrackBack

August 09, 2003

Installing Berkeley DB XML on Mac OS X with Python and Perl API support

I just wanted to post some notes about installing Sleepycat Berkeley DB XML on Mac OS X 10.2 with Perl and Python support. The builds are relatively straight forward and Sleepycat has posted a simple script to help build Berkeley DB XML it self. However, it isn't clear what is necessary to get Perl and Python working.

The most important thing, before you start compiling anything, make sure you have the latest GCC 3.3 from Apple. This is distributed as a patch to the December 2002 developer tools. This is critical, without it Python and Perl support will not work.

Next, unfortunately, you'll have to build a new Perl and Python. The Mac OS X 10.2 Python should be the right version, but I couldn't get it to work. Building a fresh Python 2.3 does work. For Perl, Mac OS X includes Perl 5.6 and Berkeley DB XML requires 5.6.1 so you have to build a new one. I used Perl 5.8.0 and it seems to work fine. So you have to build a new Python, a new Perl and the Berkeley DB XML distribution. These should all build using the standard instructions and for DB XML you can use their script.

Once you have all that built, you can then build the DB XML Perl and Python libraries.

For Python you first need to build and install bsddb3, once that's done you can build the python support for DB XML in the usual Python fashion. Make sure the python you're using is the one you built previously. Unless you specified otherwise, it's installed in /usr/local/bin/python.

cd dbxml-1.1.0/src/python
/usr/local/bin/python setup.py build
sudo /usr/local/bin/python setup.py install

There's an example Python program in dbxml-1.1.0/examples/python/examples.py that you can run to test the build.

For Perl you just build it in the usual Perl manner. Again, make sure you use the perl you compiled.

cd dbxml-1.1.0/src/perl
/usr/local/bin/perl Makefile.PL
make
sudo make install

There are some examples for the Perl API in dbxml-1.1.0/src/perl/examples.

Posted by kstaken at 08:33 PM | TrackBack

XML Document Construction With Python and libxml2

The libxml Python API is very lightly documented, so this is an attempt to fill in some of the holes that exist.

Creating a new document

To create a new document using the libxml2 API you use a document constructor function that returns an empty document instance. This method takes one argument that repesents the XML version of the document being created.

 import libxml2
 doc = libxml2.newDoc("1.0")

Creating elements

Once you have a document instance you then need to add elements to it. First off you need to create the root element.

root = doc.newChild(None, "root-element", None)

The root node is created using the xmlDoc.newChild() method. This method takes three parameters.

  • namespace - The namespace that the element should belong to or None if no namespace.
  • node name - The name of the node with no namespace prefix.
  • element content - The content for the element or None if the element is empty.

In this particular case we're creating an empty element named root-element. If we were to print this out at this point it would look something like this.

<?xml version="1.0"?>
<root-element/>

If we wanted to put the node into a namespace we would write this instead.

root = doc.newChild(None, "root-element", None)
namespace = root.newNs("http://example.com/sample", "sample")
root.setNs(namespace)

The resulting document then becomes.

<?xml version="1.0"?>
<sample:root-element xmlns:sample="http://example.com/sample"/>

Now that we've created the root we can continue adding elements to the document. We can add a element child-node in the http://example.com/sample namespace by adding.

child = root.newChild(namespace, "child-node", None)

And our document now looks like

<?xml version="1.0"?>
<sample:root-element xmlns:sample="http://example.com/sample">
    <sample:child-node/>
</sample:root-element>

If we had wanted to included some text within the added child it's as simple as just changing the third parameter to newChild.

child = root.newChild(namespace, "child-node", "Some sample text")

Which generates the document

<?xml version="1.0"?>
<sample:root-element xmlns:sample="http://example.com/sample">
    <sample:child-node>Some sample text</sample:child-node>
</sample:root-element>

Adding an attribute to an element is also very easy.

child = root.newChild(namespace, "child-node", "Some sample text")
child.setProp("an-attribute", "with a value")

Which of course generates a document that looks like this.

<?xml version="1.0"?>
<sample:root-element xmlns:sample="http://example.com/sample">
    <sample:child-node an-attribute="with a value">Some sample text</sample:child-node>
</sample:root-element>

If you wanted the attribute to be part of a namespace, you use setNsProp instead of setProp.

child = root.newChild(namespace, "child-node", "Some sample text")
child.setNsProp(namespace, "an-attribute", "with a value")

And the result

<?xml version="1.0"?>
<sample:root-element xmlns:sample="http://example.com/sample">
    <sample:child-node sample:an-attribute="with a value">Some sample text</sample:child-node>
</sample:root-element>

Beside simple elements and attributes libxml defines methods to create all the other common XML types. Here's a summary of the methods that are available.

  • xmlDoc.newDocComment(comment) - Creates a comment node.
  • xmlDoc.newCDataBlock(content, length) - Create a CDATA section.
  • xmlDoc.newDocText(content) - Creates a new text node.

These methods are all node construction methods that are called to create the instance of the required type. Once you have the instance you then need to add it into the document tree where ever you want it. There's also a function available to create processing instructions. This function differs in that it called on the libxml2 module, rather then an xmlDoc instance.

  • libxml2.newPI (name, content) - Creates a processing instruction

Since these functions require you to create the node and then add it to the document in two steps, libxml provides a number of methods to control where the node is placed in the document tree. These methods are available on any instance of an xmlNode.

  • xmlNode.addChild(node) - Appends the new node to the list of children for the node.
  • xmlNode.addChildList(nodeList) - Appends a list of new nodes to the children for the node.
  • xmlNode.addNextSibling(node) - Adds the new node as a sibling after the selected node.
  • xmlNode.addPrevSibling(node) - Adds the new node as a sibling before the selected node.
  • xmlNode.addSibling(node) - Adds the new node as a sibling after the selected node. (similar to addNextSibling)
  • xmlNode.addContent(content) - Appends additional text content to an element.

Here's an example that puts everything together.

#!/usr/local/bin/python 
import libxml2
doc = libxml2.newDoc("1.0")

root = doc.newChild(None, "root-element", None)
namespace = root.newNs("http://example.com/sample", "sample")
root.setNs(namespace)

child = root.newChild(namespace, "child-node", "Some sample text")

child.setNsProp(namespace, "an-attribute", "with a value")

comment = doc.newDocComment("Just commenting")
child.addPrevSibling(comment)

pi = libxml2.newPI("a-sample-pi", "with some useless content")
root.addPrevSibling(pi)

text = doc.newDocText(" This will be added to the existing text.")
child.addChild(text)

child.addContent(" This will also be added to the text")

print doc.serialize(None,  1)

And a final result.

<?xml version="1.0"?>
<?a-sample-pi with some useless content?>
<sample:root-element xmlns:sample="http://example.com/sample">
<!--Just commenting-->
  <sample:child-node sample:an-attribute="with a value">Some sample text This will be added to the existing text. This will also be added to the text</sample:child-node>
</sample:root-element>

Posted by kstaken at 07:42 PM | TrackBack

Bought Eclipse in Action

To check out the Manning eBooks process I went ahead and bought a copy of Eclipse in Action. It's a straight PDF, no stupid DRM. That makes it a very good value and means I'll probably be buying more eBooks from Manning in the future. I still have my eye on AspectJ in Action, but the Eclipse book is something I have more real use for. I've never bothered to sit down and learn how to use Eclipse, now I will.

Hopefully, with my Tablet PC, O'Reilly's Safari service and other sources of eBooks like Manning I'll never have to buy another 2" thick technical book again.

Posted by kstaken at 06:43 AM | TrackBack

Manning Publishing eBooks

I just noticed that Manning is publishing their technical books in PDF format. It looks like the book is typically 50% off the cover price of the print edition. You buy them directly from the publisher. Even better, if you then decide to buy the print edition later they apply the purchase price of the eBook to the price of the printed edition.

I'm not positive, but it also looks like the books don't have any DRM to screw things up. If that's the case, this is another great step forward for eBooks in the technical field. Of course they have a license agreement that goes with the books, but it's basically what you'd expect. I'm tempted to pick up a copy of AspectJ in Action to try this out. If there's DRM I'll be pissed.

Posted by kstaken at 06:12 AM | TrackBack

August 04, 2003

Rendezvous Implementation for Windows and Linux

Rendezvous is something I really wish Microsoft would include in Windows, until they do there's Howl. It looks like it's a fairly simple C API and works on both Windows and Linux. Pointer from Hack the Planet
Posted by kstaken at 10:34 PM | TrackBack

August 03, 2003

a natively-compiled version of the Eclipse IDE

Red Hat finally succeeded in building a natively-compiled version of the Eclipse IDE with GCJ. They've also integrated the OProfile continuous full-system profiler into Eclipse. [Hack the Planet] Cool, looks like GCJ might actually be getting useful. Eclipse is a pretty big application.
Posted by kstaken at 02:35 AM | TrackBack

July 22, 2003

Hydra 1.1.1

Hydra 1.1.1 has been released. The biggest change in this release is the addition of a live HTML preview window that uses the Safari engine for rendering. I played with it for a few minutes and looks like that will be a really great addition. It works quite well. It's good to finally see some decent applications embedding web browser support on Mac OS X, the old Apple browser component was quite pathetic.

Hydra has become my preferred editor for things like scripts, XML and HTML. It becomes particularly powerful if you use something like TextExtras to add additional capabilities and a script menu to the application. What's really cool is that you can write the scripts in any language and they'll be usable in any Cocoa application that supports NSTextView. It's definitely a geek oriented feature, but it's very handy.

Posted by kstaken at 01:35 PM | TrackBack

July 18, 2003

Tablet PC and O'Reilly Network Safari: a perfect match (almost)

A couple years ago when I was working on a book for O'Reilly I was given an account on the Safari Bookshelf service. Safari is an online service that allows you access to a large library of technical books, including it appears the entire O'Reilly library. I really didn't care much for the service. At the time I had a clear preference for paper books and reading at the computer was just not pleasant. I saw the value as a reference, but the price wasn't appealing since I was still buying a lot of paper books.

Technology has advanced since then and display quality has improved quite a bit. My current 20" Apple Cinema Display is vastly more readable then the 19" Sony CRT monitor I was using at the time when I tried Safari. Even more importantly though, I now have a Tablet PC and this finally makes the Safari service a must have if you're a technical user. Reading on the tablet works very well, and allows you to comfortably take your reading away from your desktop system. This was always a big reason I preferred paper books. Sitting at a desk and reading long passages just doesn't feel comfortable, but reclining with a Tablet PC works perfectly well.

Interestingly, the Safari service is also a place I would actually like to see DRM applied. The one big limitation with Safari is that you have to have a network connection to access it. You're given bookshelf space based on the service level you subscribe to. For instance for $14.95 per month you get a 10 slot bookshelf. You can swap the books at any time as long as the book your replacing has been on your shelf for at least 30 days. Basically it's a book rental service and as long as you're the type who accesses lots of books and swaps the books out often it presents a good value. With the Tablet PC it would be very nice to be able to download books in PDF format that could be accessed anywhere. Since you're basically renting the books, it would be perfectly acceptable to require the books be renewed once per month to continue using them. Buying books with DRM is a bad use of DRM because it takes value from the customer, but using DRM to enable an alternative service model that gives value that wouldn't otherwise exist can be a very good thing.

It may seem strange that this presents good value, but you have to consider the particular market this is playing in. Technology books are expensive ($30-$60) and go out of date extremely fast. Very few maintain their value past about two years and will generally be updated in that time (requiring another full price purchase). They're also often big and heavy which makes it impossible to carry a library around with you. In the past I constantly ran into problems where I would own a book on a subject, but that book was not where I needed it to be. The Safari service solves this, as long as you have a network connection. Using DRM and the PDF format would even enable this limitation to be removed without spoiling the basic business model. I've reduced my book spending considerably, but I still spend hundreds of dollars per year on technology books, in the past I actually spent at least $1000 per year (usually much more) on technology books. I now have boxes and boxes of tech books that just aren't worth anything because they're so out of date. Just giving them away is painful considering how much they cost. The Safari service allows you to keep an up to date library, accessible from anywhere there's a network connection without the problem of storage and disposal of paper books. Considering this, the Safari service is an outstanding value. Hopefully the service will be able to offer the same value and eliminate the need for the network connection by leveraging DRM in a good way.

Oh, yeah, just thought of something else. The Safari service will also allow me to get rid of all the other books that I'd been hanging onto, "just in case". Those books are out in the garage right now, there's not much value in that.

Posted by kstaken at 03:52 PM | TrackBack

July 10, 2003

LDAP Replication

Here's a tip, if you're setting up multi-master replication with iPlanet directory server and have the servers connected by 100mb ethernet or greater don't follow the iPlanet recommendation that says to use an LDIF export to initialize the consumers. The last time I did this, I followed that recommendation and ended up wasting several hours while importing the LDIF into the consumer only to have replication fail because of replica id inconsistencies. Use online initialization. Even over SSL it took something like five minutes to initialize the consumer, compared to about 3 hours using LDIF. The bonus of course being that Replication actually worked after it was done.

Posted by kstaken at 09:15 AM | TrackBack

July 09, 2003

PyObjC 1.0b1 Released

The improvements include: Improved performance and stability, Better tutorials and examples, Initial support for MacOS X 10.1, Support for the WebKit framework, Write plugin bundles in Python (requires Python 2.3) [Studio Log]

I've been playing around with the 0.9 release of PyObjC. It's a very promising project badly in need of better documentation. I've really been getting into Python lately and have been using it heavily with my Cocoa projects. I'd love to see Python included by Apple as a full peer with Objective C and Java for Cocoa applications. It would make Cocoa development even easier then it already it. Applescript Studio is nice, but Applescript is still not a language that I feel comfortable with and the way it is integrated with Cocoa means there are quite a few things you can't do with Applescript. I've found it easier to just stick with Objective C. The way PyObjC is being integrated it is functionally equivalent to Objective C and should bring all the power along with the ease of a scripting language.

Posted by kstaken at 12:18 PM | TrackBack

July 01, 2003

Death to the Manual Save

OK, I'm going to rant a little. This is aimed at people developing software for Mac OS X. Will you please quit making people manually save. Manual saving sucks, let me say that again it SUCKS! It's an artifact of the computer that has been passed through to the user and that's something that needs to stop. Computers are bad enough without having to remember to save your damn work all the time. There's no reason for it anymore, so quit doing it already. Yes I know it's more work for the developer, but Mac OS X is about usability and developers should be striving to make the computer more humane. Manually saving files is not humane. Yes I also know it will take people time to get used to not having to manually save, but I promise they'll be happier for it, really I promise. People have just been conditioned to manually save because of how crappy all the past software has been. On Mac OS X this can change, it's time for the manual save to die.

I just downloaded what I thought looked like a cool piece of software aimed at writers called Ulysses. I'm trying to write more and was excited to see what looked like software focused around writing and not the computer. It has a project metaphor where you create documents within a project and keep stuff together in a nice bundle. Well guess what? Not only does Ulysses make you manually save your files, it makes you save both your documents and your projects. When you create a document you have to save it to the project and then you have to save the project. NO, NO, NO, NOOOOOOO!! WHY! God how stupid. Just save the god damn thing for me. I HATE saving stuff manually, HATE IT, HATE IT, HATE IT! To be fair Ulysses is 1.0 and very well might turn out to be pretty cool, but I guarantee I won't be using it until it can save itself.

Another example is Spring, I use this to keep track of the music I want to download from eMusic. I never, never remember to save this thing. In fact I've become so annoyed that it can't save itself I've actually stopped using it. I've complained to Robb about this and he'll fix it eventually, but having to manually save in Spring is like having to manually save in the Finder. What's that you say? Oh you don't manually save in the Finder, ah yes exactly.

One more example, one of my favorite pieces of software is NetNewsWire Pro, in fact I'm using it to write this post. But, umm, well if the power were to go out or my computer were to crash in some manner I'd lose everything I've written so far because I have to manually click on "Save as Draft". Why? Why doesn't it just work like mail where all new messages are saved as drafts? The problem is that when you click "Save as Draft" it clears the compose window and you then have to go track down your message in the drafts folder. So that provides discouragement for saving a draft. Really the button should be titled "Save as Draft and Start a New Message". Of course that's never what I've wanted to do when clicking on "Save as Draft", but oh well. It's also quite jarring to click on "Save as Draft" and instantly have your post disappear. I know I'd rather manage a little draft clutter then to ever lose any work. I'll give NetNewsWire credit though, it does auto save once you click the Save as Draft button and then continue editing, after you've actually found your post in the drafts folder of course. BTW, did I mention NetNewsWire is one of my favorite pieces of software, it's just the "Save as Draft" function that has a pretty poor user experience.

Just image how much iTunes would suck if you had to save it every time you moved a song to a playlist, or in iPhoto having to save every time you added a picture, or in iCal every time you added an appointment. Are the functions of these applications really any different then what Ulysses, Spring, NetNewsWire Pro and "insert you favorite app" do?

Death to the Manual Save! Death to the Manual Save!

Posted by kstaken at 05:58 PM | TrackBack

June 29, 2003

SS_PrefsController

More from the Irate Scotsman, SS_PrefsController allows you to easily create an iTunes style preferences pane. Looks pretty slick.

Posted by kstaken at 09:53 PM | TrackBack

Mac Developer Blogs List

Yes there is a list of Mac developer blogs. I actually saw this a while back, but forgot about it.

Posted by kstaken at 07:55 PM | TrackBack

Mac Developer Blogs

I'm wondering if there is a list of Mac OS X software developer blogs? I just discovered Sci-fi Hi-fi from a comment left in the 100th Window review. It's a blog by Buzz Anderson, the author of PodWorks. Lots of interesting pictures and comments from last weeks WWDC, makes me even more sorry I missed it.

Posted by kstaken at 07:43 PM | TrackBack

iTunes Playlist to Blog

While messing around today I wrote a little Python script to post an iTunes playlist to a Metaweblog API enabled blog (like MovableType). I'm toying with the idea of using it to auto-post a top 25 list of songs once per week or something. The script is available here.

Here's what the top 25 looks like for this week. This is from an iTunes smart playlist that shows the top 25 most played songs that have been added to my library in the last month. iTunes smart playlists are an absolutely great feature that I hope shows up in other places in Mac OS X, like oh maybe in the Finder as a smart list of files.

ArtistSongAlbumPlay Count
MetallicaFranticSt. Anger12
Massive AttackAntistar100th Window11
Massive AttackButterfly Caught100th Window11
Massive AttackEverywhen100th Window11
Massive AttackFuture Proof100th Window11
Massive AttackName Taken100th Window11
Massive AttackHymn Of The Big Wheel (OriginHymn Of The Big Wheel11
MetallicaDirty WindowSt. Anger11
MetallicaMy WorldSt. Anger11
Annie LennoxA Thousand Beautiful ThingsBare10
Annie LennoxBitter PillBare10
Annie LennoxErasedBare10
EvanescenceBring Me To Life (Feat. PaulFallen10
Massive AttackPrayer For England100th Window10
Massive AttackSmall Time Shot Away100th Window10
Massive AttackSpecial Cases100th Window10
Massive AttackWhat Your Soul Sings100th Window10
Massive AttackAny Love (Larry Heard Mix)Hymn Of The Big Wheel10
Massive AttackHome Of The WhaleHymn Of The Big Wheel10
Massive AttackHymn Of The Big Wheel (NelleeHymn Of The Big Wheel10
Annie LennoxHonestlyBare9
Annie LennoxLonelinessBare9
Annie LennoxOh God (Prayer)Bare9
EvanescenceEverybody`s FoolFallen9
EvanescenceGoing UnderFallen9

What's funny is that I have a tremendous breadth of musical interest, but you sure wouldn't know it from this list. I bought a number of more popular albums a couple weeks ago which skews the results away from the more eclectic mix I usually get from eMusic.

Currently Playing "Marquis Cha-Cha" by "The Fall" from the album "Palace Of Swords Reversed", a little more eclectic bit from eMusic.

Posted by kstaken at 05:01 PM | TrackBack