Tag Archives: Engineering

BWToolkit

BWToolkit is a library of code for Cocoa development.

Actually, it’s more than just a library of code. It comes with an Interface Builder (version 3) plugin that simplifies development and use of the framework. BWToolkit is open source under the generous BSD license, and you can obtain it as source code or you can obtain it as a nice “drop and play” package.

I’ve stumbled across BWToolkit a few times in my development work, but it wasn’t until recently that I could begin using it (seems to have a requirement of Mac OS X 10.5 as a minimum…. doesn’t state that explicitly, but you can see it in some of what it does plus examining the source code). In my use of it so far, it’s been really well done and a real joy to development. Having been an engineer of the PowerPlant C++ Mac application framework back in the day, I know what it can be like to write reusable code modules like this, and BWToolkit has a lot of spit and polish.

Some things I like about it:

  • Drop and play. Just download the distribution, install the IB plugin, ensure the framework is added to your project (link to it, copy it into your resulting bundle) and that’s it. So simple.
  • Use is very simple, because there’s no extra work. Just edit merrily away in Interface Builder.
  • It’s got a lot of those widgets that you commonly want to use but there’s nothing standard from the OS for you to use. Oh sure you could make the widgets, but BWToolkit makes things like the BWAnchoredButtonBar, BWAnchoredPopUpButton, BWUnanchoredButtonContainer and so on… it just helps round out those commonly used widgets so all you have to do in IB is just drag and drop and get on with your work.
  • I love the BWSheetController. I wish I had thought of that class! It’s so common to have a xib with a main window (e.g. document) and then you need to display a sheet on the window. To display the sheet, there’s a lot of infrastructure code you have to write every time, and it’s the same code over and over — perfect candidate for a reusable class to factor that out. With BWSheetController it’s even better because it’s just adding an instance of the controller to the xib, hooking up some outlets, and viola… functional sheet with just a few clicks. Wonderful!
  • Most of the classes are based upon Cocoa classes. For instance, BWSplitView is an NSSplitView, the button classes are typically just aggregates of other NSButton’s. It’s good to subclass where it makes sense, instead of fully recreating from scratch.
  • The use of the BSD license pretty much means there’s little reason NOT to use BWToolkit. It makes your life a lot easier, little restriction upon use, it’s free (beer and speech). What’s not to like?

Some things I don’t like:

  • I found a bug (BWSplitView’s show up in initial random locations if the host window’s “visible upon launch” setting is not on). I reported the bug via email but have received no reply from the author (it’s been long enough). Granted, it seems he’d prefer filing it in his bug tracking system, but I don’t have the cycles right now to do that so I wanted to at least email to ensure the bug didn’t slip through the cracks. So, I’m not sure how active the project is right now. *shrug*
  • There’s not much documentation. Granted, there’s enough to get you going, and eventually you can figure things out. But to make a well-rounded distribution, full documentation of the classes/widgets and an accompanying sample application that shows everything off would make for a better final product.
  • Some of where documentation would be very useful would be things like bottom bars…. you can do bottom bars now so, what’s the point of this class? What advantage does it provide? Or is it a holdover from long ago when the OS provided no means whatsoever? In which case, is the bottom bar class smart about the OS version? Again, one could figure it out from reading code, but formal documentation is better.

All in all, a nice little toolkit.

About these ads

Still can’t GetLabel()

So we’re at a point in our development cycle where we can finally upgrade our toolset. Installed Xcode 3.2.3, using the LLVM-GCC4.2 compiler, the 10.6 SDK, and setting 10.5 as our minimum OS.

Of course now I compile code and lots of OS function deprecation warnings come up. Time to clean up the source code.

If you need to obtain a Finder label, the old-school way was to use GetLabel(). Even today we still have to use GetLabel(), despite the fact they have deprecated it since 10.5. And while they deprecated it in 10.5, they didn’t provide a replacement API until 10.6. Unfortunately this replacement API isn’t 100% workable.

1. It’s an Objective-C API, in AppKit. Specifically: -[NSWorkspace fileLabels] (and -fileLabelColors).

The old API was a pure C API so you could easily use it anywhere, and we use it in a pure C++ library. Fine. I can create a .mm file with an extern “C” function to provide my own C wrapper and mimic GetLabel()‘s API. But it’s just extra work.

2. It’s only available as of Mac OS X 10.6.

It’s not a huge problem, but it’s irritating they deprecate the old way and didn’t provide a new way until the next OS revision.

3. -fileLabels crashes.

Isn’t that wonderful? They provide a new API and the new API doesn’t work.

And it’s not like it’s any sort of difficult API to work with either. It’s just a simple call.

But how can you get it to crash? Simple. Call [[NSWorkspace sharedWorkspace] fileLabels] 3 times. The first time will be OK. The second time might generate the crash but could also just generate console messages. The third time, you should crash or certainly generate bad messages in the console. If you didn’t crash the third time, certainly on the fourth you should. But typically 3 calls and boom.

-fileLabelColors doesn’t have this problem.

Investigating it, it seems there’s something being double-released/freed/deleted inside of -fileLabels. You can turn on garbage collection and it won’t crash, but lots of ugly console messages are generated.

What also bugs me? How did this API ship with such a bug?  Didn’t they test it? Didn’t they unit test it? Did they only test it under garbage collection? Did they write the API only for the Finder and figure if the Finder wasn’t crashing that was a good enough test to say a public API for the OS would work?  I mean, I can understand complex bugs, I can understand how code paths can be what they are and how bugs can ship (been a professional software engineer for over 15 years). But something like this? I can’t see how this managed to get out the door.

*sigh*

rdar://problem/8301881 Seems it was also reported as rdar://problem/8084710.

So… there’s no GetLabel() replacement for me until they fix it, 10.7 if I’m lucky. Yes I’ve considered other workarounds, no they won’t work in my particular context, or with a lot of work I could get it working but it’s not mission critical and I have bigger issues to deal with.

Updated: Apple DTS wrote back saying this is a known issue being tracked under its original number: rdar://problem/7287108, which as you can see is at least the third report of the problem. So we can only hope Apple’s going to fix it, but I bet we won’t see it until 10.7 at the earliest.

Named pipes and unwanted hangs

The past few days I’ve been dealing with a wonderful little problem.

They’re called “named pipes“.

The main product I work on in my day job was doing some filesystem scans and would hang for some unknown reason. After much investigation we noticed the file it was hanging on was a named pipe file way down in the bowels of the system (a temporary file created by the com.apple.notify process). What was happening was well… it’s a pipe. Something in my app was opening that pipe and thus the app “hung” because it was now wanting to read from the pipe. Thing is, my app doesn’t care about pipes at all, it’s just working with files. As well, we weren’t explicitly opening the file; we would call some other OS routine and somehow somewhere in that OS function’s implementation it called open() and thus we hung.

And so, what a bear this is.

In the end we decided to check for and avoid pipe and socket files at all costs. Any means by which a file can “get into” the app, we put up a wall at the perimeter so no such files can even get in. We figure we keep them out at the wall, then we don’t have to spend lots of CPU cycles internally to constantly deal with them (tho critical code should still perform checks). Plus, since one big part of the problem is we can’t control what others do and if they might open() the file, we have to nip it in the bud as soon we become aware of the file and minimize how much “work” is done on the file in case some other function might open() the file and we risk hanging.

To check is pretty simple. Code something like this (NB: I tried using the “code” tags and less-than/greater-than signs for the #include, but WordPress’ editor seems to get confused… so I just used the “pre” tag, which isn’t quite giving me the results I want either… oh well.).

#include "sys/stat.h"

bool
FileUtilities::IsUnsupportedFilesystemItem(
const char*    inPath)
{
    bool is = true; // assume failure, because if we fail on such 
                    // a simple operation something really has to be wrong
    if (inPath != NULL)
    {
        struct stat statInfo;
        int retval = lstat(inPath, &statInfo); // use lstat() instead of stat() because 
                                                   // we want to minimize resolutions or other "work"
        if (retval == 0)
        {
            if (!S_ISFIFO(statInfo.st_mode) && !S_ISSOCK(stat.st_mode))
            {
                is = false;
            }
        }
    }
    return is;
}

How you actually cope with it or if you consider them problems or not is up to you and your code and your situation. The key of the above is to get the file’s mode then check the FIFO and SOCK flags. If set, reject the file.

For most people, this isn’t going to be an issue or a problem. I mean, we went around for quite some time and never dealt with the issue. And in daily use, most people aren’t going to see pipe or socket files.

But it’s worth noting and thinking about. Nothing wrong with being a little defensive.

Self-document code is anything but

If you know me, or maybe you can just tell from my blog, I can be verbose.

It’s how I am. I tend to prefer more information to less. I think you get further in life by knowing more, not less.

But I also know this wears on a lot of people. They just want the bottom line and don’t care why or how you got there. IMHO that’s a pity because then they never truly understand and can never arrive at educated conclusions on their own. OK fine, a baby is made, that’s the bottom line. If you want to stop there and never know more, that’s your business. But in my book, knowing how to make that baby is interesting, and then going through the motions of making that baby even more interesting. :-)  Like I said, it’s good to have knowledge and information.

I write software for a living. There’s great debate about documenting code, be it formalized documentation apart from the code or writing comments in the code itself. I’ve never jived with folks that say code should be self-documenting and that’s all the documentation you need. Sure, you should write readable and maintainable code. Naming your variable “numberOfObjects” is far better than just naming the variable “i”. But you must have comments. Why? Precisely.

Self-documenting code can tell you what and how, but it cannot tell you why. For that, you must use external documentation.

You must go through the effort of writing comments to explain bits of code. Depending on the code, you may also want to write larger external documents (e.g. in a word-processor) that explain the greater architecture and how all the parts of the code fit together and how to use it all. This is something that cannot be conveyed by reading the code itself, and I just don’t understand those that think this sort of documentation is a waste of time and somehow if you do it makes you “not a real programmer”.

Well buddy, real programmers know the moment after the code is written it must start being maintained. If you can’t remember what you had for breakfast a week ago, can you expect to remember why you wrote this code when you come back to it in 6 months?

Case in point. Just yesterday I was working on a bug in our software where the application would hang. All signs and symptoms were odd but somehow made sense to each other. When our QA guy told me one key point (“looking at the permissions flags, there’s a ‘p’… what’s that?”) it all came back to me. The file was a named pipe and I dealt with this very problem in the past. I went looking in code for where I previously dealt with it. I found it. The comment was dated over 5 years ago.

5 years ago.

When I fixed the problem — 5 years ago — I added copious comments to the source code to explain the problem in great detail; 50 lines of comments. I know many would say that was ridiculous! That it’s just his (annoying) verbosity! Well, thank goodness for it because without it there would have been no way I would have remembered that 5-year-old problem in such great detail and know exactly how to fix it (again) today.

Here’s an article by Jef Raskin discussing the same thing. Jef Raskin would know.

So yeah… people tell me I’m verbose. I really don’t care. I am who I am and I know when to be curt and I know when to ramble on. There are times when comments aren’t needed (don’t tell me what or how), but you do need to explain why and not be afraid to go into detail because the code you may have to maintain may be your own. Do yourself a favor and explain yourself. And if someday that code gets to be maintained by someone else, do them a favor and explain yourself.

I’ve never known anyone to say there’s such a thing has having too little ammo. I feel the same way about code comments and information. :-)

Spare me

Yesterday I was at McBride’s Gun Store to meet someone. I arrived early so I looked around and picked up a few things. Of course, I had to look in the gun cases. I wanted to look for a revolver in .44 Magnum.

I saw a S&W 629 with a 4″ barrel. I would prefer at least a 5″, 6″ maybe…. so I asked the guy at the counter about that and he said he might have a 6″ elsewhere. I then asked “do you have any models without the internal lock?” and boy that set him off. He went on about how that’s the way things are now, get used to it, it’s no big deal, I’ve read all the stuff on the Internet but *I* have never experienced it and with so many guns sold and in circulation blah blah blah… and started talking down to me.

All I wanted to hear was “yes” or “no” the have it in stock or not. I didn’t ask for his opinion. To my fault, I engaged the conversation a bit, but he wouldn’t hear anything of it… I was obviously a moron.

You know, Michael Bane is no dummy and he’s personally experienced revolver lock-up. Read that thread and see that others have experienced it too, like Massad Ayoob. The point is simple to me: you have added something that isn’t necessary for the gun to function (it’s only there because of the gun grabbers and lawyers). You have now made the machine unnecessarily more complex, which just means with more parts there’s more ways for the thing to fail. And sooner or later it will. Given the nature of this mechanism, any failure with it could be fatal. It’s the engineer in me, what can I say. If the gun is a safe queen, who cares. If I’m betting my life on it? It’s a different story.

It may be a million in one chance of it happening and happening when your life depends upon it, but that’s little comfort when you’re that one.

xml standalone

Apple changed the NSXML/CFXML implementation in Snow Leopard to use libxml. Generally a good move, but so far it appears to have caused some problems:

  • The notion of -[NSXMLDocument isStandalone] changed, at least in the sample code I’m using as a reproducible case for the bugs. In 10.5 the value is NO, in 10.6 it’s YES.
  • Having the XML declaration contain standalone="yes", at least in the sample code, eventually causes the libxml parser to crash. Maybe not always, but if you send the sample code an AppleScript of
    tell application "SimpleScriptingPlugin"
        beep
    end tell

    the sample app will crash. Force [myNSXMLDocument setStandalone:NO] and no more crash. Or run it under Leopard regardless of the standalone setting and no crash.

It’s taken many months of investigation and going back and forth with Apple to figure out this OS bug, mostly because due to how the problem comes up we were chasing down other avenues (was this an AppleScripting problem? Still could be, at least in part.). But for now, it seems we’ve a few issues with how NSXMLDocument generates XML, how NSXMLDocument regards being standalone (and across the OS versions), and then how libxml ungracefully handles that specification. Hopefully with my further information, Apple will be able to properly remedy all of this. Yes, it’s all properly filed with Apple, so they’re aware.

I tell you. This crash problem has been plaguing me and our users for quite a while. We’ve been able to provide the users with ways to work around things, but it’s not optimal. My hope is now with this information we can provide a better solution in our code and hope that Apple will soon fix this in the OS. Finally hitting upon this last night was quite the euphoric moment. :-)  Granted, there may still be other things to deal with for this, and I could be premature in celebrating… but certainly it’s more info for Apple towards fixing the problem, and it’s still a hopeful step in the right direction for me and the users of my product.

Code Bubbles

For you developers out there, check this out: Code Bubbles.

And you really need to watch it full-screen, high def, as it’s hard to understand what they’re talking about without being able to see the text they’re editing.

Present development IDE’s are all about text files… you are organized based upon the way the data is stored. I recall long ago thinking about how that, well, sucked. :)  It’s one way to organize things for sure, but why should we be limited by the storage constraints of the system if that’s not the best way to actually organize and access the data? We should be able to abstract that notion away. Isn’t that part of what computers are all about?

I really like how this “code bubble” approach works to allow you to focus on work. The data is just the data. You work with the data. You can see how the data relates to other data. If you need to add your own data, like a flag or a note, you can do that. How you can preserve data that is generated, such as a debug session, and then come back and revisit that at another time be it just starting a second debug session or something you did weeks ago. How documentation, how bug reporting, how annotations are just integrated into the system and so you can hook all of these things together to allow you to work on a problem with all the necessary parts just right there and connected together. Then how you can take all of this and serialize it to share with a colleague?  That’s pretty cool.

I will say, some of the bubbles are a little annoying, mostly because I think the left-to-right hierarchical structure is a bit cumbersome on screen. But that’s a minor nit, and they’ve actually done a fair job at trying to address a lot of that mundane usability minutia. The concepts here are really good, and I figure all it takes is time in use to actually develop and truly refine the workflow. Bubbles may not be the final solution to improving the developer workflow, but it’s great to see someone working to develop a model that rethinks the whole process and strives to improve upon our existing paradigms.

Neat idea.

NSRuleEditor – you are so cool but so frustrating

If you’re not a Mac programmer, you can stop reading now. :-)

Apple has this cool new widget called NSRuleEditor, introduced in Mac OS X 10.5. A lot of the software I’ve written over the past some years involves searching for things and often the user needs to provide you with rules by which to search. I’ve always had to invent my own solutions, and it’s a non-trivial thing to do. So when I finally heard about NSRuleEditor some years ago I was most excited to finally have an OS-provided solution.

The way Apple implement the widget is pretty cool. They realize people will use it to display whatever arbitrary data model they have, so they structured it that way. The NSRuleEditor iself is a single control, the contents of which are opaque to you… mostly. There’s your data model objects, which NSRuleEditor calls your criteria (that bugs me, as “criteria” is plural and the API uses it in a singular sense, but oh well… I can understand why they did that). The criteria can be whatever you want them to be, it doesn’t matter. But each criteria object then has a “display value”, which is how the criteria is displayed and/or worked with in the GUI, such as a string or a menu item or a text field or date picker. Thus I can have a LabelObject, an OperatorObject, and a TextObject which represent my data model. The LabelObject would have a display value of “name” and a predicate value of “left hand expression” and kMDItemDisplayName, the OperatorObject would have a value of “contains” and a predicate operator value of  “IN”, and the TextObject would have a display value of an NSTextField and a predicate value of the “right hand expression”. Thus I could get the GUI to display “name contains <foo>” and create a query string like “kMDItemDisplayName IN <foo>”.

It’s a little obtuse to wrap around at first, but once you figure it out, it’s actually pretty well done. Apple has to make a generic control that anyone can use, and rule display/editing is non-trivial. Really, they did a pretty good job with this.

One thing to realize is the displayValues are not necessarily what is displayed in the GUI. Yes they generally are, but when you do this there is no localization. However, NSRuleEditor has a way you can provide a dictionary of formatting strings that allow you to change the displayed format. You see, the criteria objects are truly the data model. The displayValues aren’t truly the view… they can be, but they’re like “one step back” from being the view. Really, you should be using the formatting strings to get the real view… and then it’s like the displayValues are a “view model” for the view. Confusing? I know, but this is how it is. The formatting strings are your way to localize the display, but of course you don’t need to use it for localizing… you could just use them to change what is truly displayed to something other than the strict “view model”. There’s flexibility in the mapping the formatting strings provide.

So for instance I want to do a name criteria. The formatting strings are a key-value pair. The key is a pattern that matches the labels of your criteria objects. For instance:

%[Name]@ %[matches, contains, is, begins with, ends with]@ %@

Provides the formatting key. The %@ groups demarcate special identifiers, so that in your value, you’d have something like:

%1$[Name]@ %2$[matches, contains, is, begins with, ends with]@ %$3@

As the formatting value is parsed, it picks up the “x$” identifiers and knows this affects the ordering of the elements in the string, so you could shuffle things around. As well then, the items within the brackets are also ordered. So for instance if I had a value string like:

%1$[Name]@ %2$[ends with, begins with, is, contains, matches]@ %$3@

then when my data model said “matches” the GUI would present “ends with” to the user. Of course, this would be highly confusing to the user thinking they were doing an “ends with” search but the actual search ended up doing a “matches” search. But it shows what you can do.

Of course, the real benefit of this is localization. Let’s say we were converting “name contains foo” to Japanese. The key is the same as above, but the value then becomes:

%1$[お名前は]@ %$3@ %2$[が入っている]@

Which is “name contains”.

All of this is good and great. But where it falls flat? You have no way to know what NSRuleEditor is displaying. What if you wanted to get that that information? You can’t. You can get the -criteriaForRow: to get the row’s criteria objects. You can get the -displayValuesForRow:, which gets the raw display values. But you can’t get the formatted display values, like a -formattedDisplayValuesForRow:

*sigh*

This put a big crimp in things for me and the code I’m presently working on. Granted, I can get all the elements myself, of the criteria, the display values, and the formatting strings, but to apply the formatting strings to the display values is a non-trivial task. IMHO, a bug/shortcoming in the NSRuleEditor API. Bug filed: rdar://problem/7741182.

NSPredicate trick

That all said, there is a cool NSPredicate trick.

This comes from blacktree-alchemy’s code for QSMDPredicate. It’s basically a way you can shove a MDQuery syntax string into an NSPredicate and have it all work out. Handy because NSRuleEditor is based upon NSPredicate, but since NSPredicate and the MDQuery syntax don’t have a perfect one-to-one correspondence (or maybe you’re using MDQuery instead of NSMetadataQuery), it’s handy.

In case the QSMDPredicate code ever goes away, here it is. Again, this is NOT mine, just someone thankful for it’s existence and release under the Apache License 2.0.

QSMDPredicate.h

//
// QSMDPredicate.h
// QSSpotlightPlugIn
//
// Created by Alcor on 5/6/05.

//

#import

 

@interface QSMDQueryPredicate : NSPredicate {
NSString *query;
}
+ (id)predicateWithString:(NSString *)aQuery;
- (NSString *)query;
- (void)setQuery:(NSString *)aQuery;
@end

QSMDPredicate.m


//
// QSMDPredicate.m
// QSSpotlightPlugIn
//
// Created by Alcor on 5/6/05.

//

#import "QSMDPredicate.h"

@implementation QSMDQueryPredicate
- (id)generateMetadataDescription{
return query;
}
+ (id)predicateWithString:(NSString *)aQuery{
QSMDQueryPredicate *predicate=[[[self alloc]init]autorelease];
[predicate setQuery:aQuery];
return predicate;
}
- (NSString *)predicateFormat{
return query;
}
- (NSString *)query { return [[query retain] autorelease]; }
- (void)setQuery:(NSString *)aQuery
{
if (query != aQuery) {
[query release];
query = [aQuery copy];
}
}
- (id)copyWithZone:(NSZone *)zone
{
id copy = [[QSMDQueryPredicate allocWithZone:zone]init];
[copy setQuery:[self query]];
return copy;
}
@end

 

(Wow… I just realized my current WordPress.com theme is crappy at handling blocks. I need to learn more CSS so I can tweak that).