By Andrew Stone of Stone Design
September 1990
One of the most compelling features of writing software is that there are many ways to accomplish the same thing. This gives you a large lattitude for creativity, but also "the power to run off into the weeds" [I over- heard an Apple Employee using this phrase] . In this ar- ticle I present some guidelines for creating usable and reusable objects.

Our current project has 125 new objects, and about 40 nib (NeXT InterfaceBuilder) files. This granular structure makes it trivial and speedy to change one component, and has the added benefit of lazy loading of the nib files when needed. NeXT System Release 2.0 is said to have idle time loading of nibs, which will be a clever way to speed up what the user perceives as soft- ware performance.

1] Every .nib file should have an owner object which you say "new" to.
This means that a client needs to know only the object’s name: this presents a simple interface. By separating the details of the class (such as the nib name) from its use,you obtain a cushion from changes in the object. Then your client code looks like this:
id aCoolObject= [CoolObject new];
In your CoolObject’s +new method, you would have:
+new
{
        self = [super new];/* great name for a objc rag! */
        [NXApp loadNibSection:"CoolObject.nib" owner:self];
        /* place initialization code here */
        return self;/* don’t ever forget this! */
}
Moreover, the +new method provides a place to send initialization messages to your nib objects after they are guaranteed to exist,so that you can be sure these messages are not being sent to nil objects. This has bitten me before!

2] Name your .nib file the same as the owner’s class
Your project directory will have three associated files: the .h, .m, and .nib for each object which has a visual representation. For understanding large projects, the naming of each class is one of the most important aspects of creating comprehensible,not reprehensible, code. The name should clearly and concisely describe the object’s function. I like to include the superclass object as part of the name if my custom class is a subclass of a NeXT object, such SliderDualActing, which descends from Slider. Usually, nib owners will just descend from Object, so they can have more terse names, such as "AlignPanel", "Defaults","OpenAccessory".

If the owner’s class name coincides with the nib file name, the following code will load a nib file based on that class name:
#import <appkit/Application.h>/* for NXApp */
#import <appkit/nextstd.h>/* for NX_MALLOC */
#import <strings.h>/* for strcpy,strcat */
#define NIB_SUFFIX ".nib"

+new
{
        char *name;
        self = [super new];
        NX_MALLOC(name,char,strlen([self name])+strlen(NIB_-
SUFFIX)+1);
        strcpy(name,[self name]);
        strcat(name,NIB_SUFFIX);
        if(![NXApp loadNibSection:name owner:self]) {
        printf("%s not linked\n",name); return [self free]; }
        NX_FREE(name);
        /* place other initialization code here */
        return self;
}
You can pre-write reusable code snippets like this one by including it in your .editdict file for automatic entry into an Edit file.

3] Reduce the number of global variables by caching the object in the method where it is being used.
Example: Let’s say we have a globally used alignment panel (only need one of them) that any given view can use to configure its alignment parameters. In your application subclass or application delegate class, have a method like this:
- runAlignmentPanel:view
{
        static id alignPanel = nil;
        if (!alignPanel) alignPanel = [AlignPanel new];
        return [alignPanel runModalForView:view];
}
Your view might respond to a method named "setAlignment:sender" which gets sent by a menu item to the first responder:
- setAlignment:sender
{
        return [NXApp runAlignmentPanel:self];
}
To connect menu items to the first responder, you have to:
1] Open main nib, [ie the one with menus.]
2] Click on First Reponder in project window: it’s the big 1 icon.
3] Select "Class" from Inspector pop-up.
4] Click on "Action" on the Outlet-Action button.
5] Enter the method names that your first responder responds to.

4] Subclass early, subclass often
The power and elegance of Objective C is exemplified by subclassing. It provides a way of testing changes to software without modifying an existing line of code, but by following Marvin Minsky’s advice on correcting bugs: don’t fix it, head it off with more code! From a design standpoint, it means you can create more general, resusable code which gets subclassed to provide extra functionality for a given project.

5] Document the object.
Bug NeXT for the text processing tools which take header files and turn them into the beautifully formatted WriteNow Objective C Class Specifications, and document what your object does and how it should be called.

6] Don’t Panic
I guess this belongs in every list of guidelines!

Happy Hacking.






Stone Design's Create(tm)
2005-06-30 22:24:12 -0500