Planet Cocoa

February 09, 2010

waffle

Retainer

HexColorPicker.m, circa one hour ago:

- (void)hcp_checkForUpdateUIFinish:(NSDictionary *)updateDict {
    /* Note: updateDict is by call site convention 
       already passed a retained dictionary */

    NSString *verdict = [[updateDict objectForKey:HexColorPickerUpdateVerdict] copy];
    [updateDict release];
    /* .. */
    if ([verdict isEqualToString:HexColorPickerUpdateNewerAvailable]) {
        NSString *infourl = [updateDict objectForKey:HexColorPickerUpdateNewerURL];
        if (updateInfoURL) [updateInfoURL release];
        updateInfoURL = [[NSURL alloc] initWithString:infourl];
        /* .. */
    }
    [verdict release];      
}

Did you spot it? If a newer version is available, you’re running Hex Color Picker outside of garbage collection and you’re unlucky, updateDict won’t just be released prematurely, but also be dealloced before an attempt is made to pull some more data (the new version URL) out of it. That might leave updateDict pointing to nil, messaging nil also returns nil which makes infourl nil and we end up feeding it to NSURL’s - initWithString:. Which produces an exception. Which takes down the entire application Hex Color Picker is hosted in.

Ruh-roh.

I’ve fixed this and pushed Hex Color Picker 1.6.1, which, in a delicious fit of irony, will expose every single Hex Color Picker user (of a version of such a vintage that it has the bug in it) to the conditions that trigger the bug.

I am reminded of O’Toole’s Commentary on Murphy’s Law: Murphy was an optimist.

by Jesper at February 09, 2010 06:10 AM

Translation From PR-Speak to English of Selected Portions of Microsoft’s Corporate Vice President of Corporate Communication Frank X. Shaw’s Remarks on the New York Times Op-ed Piece Detailing Microsoft’s Ineffectivity to Let Its Own People Do Their Job, Most Famously by Pointing Out the Sad and Tragic Pre-History of ClearType

(See: “Measuring Our Work by Its Broad Impact“)

At the highest level, we think about innovation in relation to its ability to have a positive impact in the world. For Microsoft, it is not sufficient to simply have a good idea, or a great idea, or even a cool idea. We measure our work by its broad impact.

In fact, and to wit, since we’re so consistent in using those terms, we regard the Zune and Windows Mobile 6.5 as resounding successes due to the transformative work they’ve done lately in redefining their industries, ushering in virtually every revolutionary trend for the past few years. Our customers, the broad groups of people who are so content with our innovation that they need only look out for the Microsoft brand when they buy mobile phones or media players, surely agree. We are pleased with the broad impact we manage to acheieve while selling tens of Zunes daily, and we don’t regret for a minute how we relegated great or cool ideas to lower positions on its or Windows Mobile’s priority lists.

After all, if you don’t have any users, and if you’re not being innovative, what’d be the point in maintaining stillborn and carcinogen platforms, desperately touting their superiority on some imaginary scale and refusing, flesh-wound style, to admit huge flaws that are causing users to leave the sinking ship?

Now, you could argue that this should have happened faster. And sometimes it does. But for a company whose products touch vast numbers of people, what matters is innovation at scale, not just innovation at speed.

The mean guy who was obscuring ClearType’s development for a number of years was actually subconciously doing so because he was deeply pondering technical issues of adoption at screen sizes between 2″ and 200″.

Another point worth addressing is Dick’s assertion that Xbox is “at best an equal contender in the game console business.” Fact is, Xbox 360 was the first high-definition console. It was the first to digitally deliver games, music, TV shows and movies in 1080p high definition. The first to bring Facebook and Twitter to the living room. And with Project Natal for Xbox 360 launching this year, it will be the first to deliver controller-free experiences that anyone can enjoy—a magical experience for everyone that Popular Science, Popular Mechanics, and Time magazine each named one of the top inventions of 2009.

Fact is, it was the first at doing a lot of things. That’s all that matters. First first first. I wonder if any of our competing consoles were first with anything this generation, like some new control scheme, media format or general art style of personal avatars. Hm. Um. Nope. Not a looker among ‘em. Trust me.

And they weren’t more powerful or more popular either. What’s that? Popular means “broad impact”? No it doesn’t. If it did, it’d look pretty stupid right now.

There is always the opportunity to do more, to move faster, to bring products and services to the world in new and interesting ways, and we embrace this. But thanks to the contribution of Dick and others on the ClearType team, ClearType certainly stands as an example of how it works well.

The unearthed story of ClearType’s multi-year detainment in arbitrary development hell at the whim of a manager sends a clear message: Microsoft’s management structure works well, has no impact on the quality of the products and certainly doesn’t need to change.

by Jesper at February 09, 2010 12:08 AM

February 08, 2010

Parmanoir

Who's calling ?

NSThread's callStackSymbols will dump the call stack in an array. What is usually the realm of gdb, callStackSymbols will do at runtime.

Here's how it looks called during awakeFromNib :

0   MyApp          -[MyAppDelegate awakeFromNib] + 44
1   CoreFoundation -[NSSet makeObjectsPerformSelector:] + 205
2   AppKit         -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] + 1445
3   AppKit         loadNib + 226
4   AppKit         +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] + 248
5   AppKit         +[NSBundle(NSNibLoading) loadNibNamed:owner:] + 326
6   AppKit         NSApplicationMain + 279

When are bindings calling your code ? Walk up the callstack and look for NSBinder :

0   MyApp      -[MyAppDelegate setSliderValue:] + 67
1   Foundation _NSSetIntValueAndNotify + 256
2   Foundation -[NSObject(NSKeyValueCoding) setValue:forKey:] + 434
3   Foundation -[NSObject(NSKeyValueCoding) setValue:forKeyPath:] + 240
4   AppKit     -[NSBinder _setValue:forKeyPath:ofObject:mode:validateImmediately:raisesForNotApplicableKeys:error:] + 264
5   AppKit     -[NSBinder setValue:forBinding:error:] + 266
6   AppKit     -[NSValueBinder _applyObjectValue:forBinding:canRecoverFromErrors:handleErrors:typeOfAlert:discardEditingCallback:otherCallback:callbackContextInfo:didRunAlert:] + 197
7   AppKit     -[NSValueBinder applyDisplayedValueHandleErrors:typeOfAlert:canRecoverFromErrors:discardEditingCallback:otherCallback:callbackContextInfo:didRunAlert:] + 567
8   AppKit     -[NSValueBinder performAction:] + 300
9   AppKit     -[_NSBindingAdaptor _objectDidTriggerAction:bindingAdaptor:] + 136
10  AppKit     -[NSControl sendAction:to:] + 63
11  AppKit     -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 1715
12  AppKit     -[NSSliderCell trackMouse:inRect:ofView:untilMouseUp:] + 1053
13  AppKit     -[NSControl mouseDown:] + 624
14  AppKit     -[NSWindow sendEvent:] + 5409
15  AppKit     -[NSApplication sendEvent:] + 4719
16  AppKit     -[NSApplication run] + 474
17  AppKit     NSApplicationMain + 364

Writing recursive code and stuck with a method definition that does not specify the recursion depth ? Count how many times the method appears in the call stack.

If you have a dummy NSLog that you want gone but can't find among the legit ones, add this to your precompiled header :

#define NSLog(args...) NSLog(args), NSLog(@"%@", [NSThread callStackSymbols])

It will call the original NSLog and pinpoint the offending function.

by Patrick Geiller at February 08, 2010 10:44 PM

Matt Legend Gemmell

NSConference 2010 US Workshop

If you’re attending my workshop in the US at NSConference 2010, I’d like to ask you to please read this and email your questions, topics and suggestions for what you’d like to cover. Anything at all is most welcome; it’s your workshop, and the reason the UK one went so well is because so many people contributed interesting points for us to discuss.

You can ask to remain entirely anonymous if you wish, and you can similarly contribute a question or issue that you’ve already solved – there might be scope for other views or some useful additions. In you have a possible topic in mind and aren’t sure about it, send it anyway!

You can send your thoughts to me via email to my gmail account (matt.gemmell) or to matt at this domain. Get those suggestions in.

by Matt Legend Gemmell at February 08, 2010 05:15 PM

Cocoa With Love

Custom build rules, generated tables and faster floating point

As fast as computers are, heavy use of floating point functions can still slow them down. One way around this, is to use a lookup table instead of calculating floating point values at runtime. But keeping a generated table up-to-date is annoying work. In this post, I'll show you how to create a lookup table automatically using a custom build rule, making an OpenGL animation 5 times faster in the process.

Introduction

In this post, I'm going to work with a modified version of Apple's default OpenGL ES 1.0 program. In this program, a colored square will spin in the center of the window:

spinner.png
Download the complete project for this post: Spinner.zip (25kb).

To artificially create a situation where this simple program is bound by CPU performance, I will calculate the location of the square thousands of times for every frame.

Initial code and performance

The initial code for updating the model matrix before drawing is:

static float transX = 3.14159265f * 0.5;
static float transY = 0.0f;
for (int i = 0; i  2e5; i++)
{
    translateX = sinf(transX)/2.0f;
    translateY = sinf(transY)/2.0f;
    doNothingff(&translateX, &transX);
    doNothingff(&translateY, &transY);
}
transX += 0.075f;
transY += 0.075f;

glTranslatef((GLfloat)(translateX), (GLfloat)(translateY), 0.0f);

This is a very simple calculation: it translates out to the edge of the unit circle and progresses around the circle by 0.075 radians per frame.

The code loops 2e5 (i.e. 20,000) times and passes its variables by reference into a dummy function (to prevent the compiler optimizing the loop away).

On my iPhone 3G, this runs between 5 and 6 frames per second.

Faster with tables

The reason this code is slow, is the sinf() function — the iPhone simply isn't meant for heavy floating point arithmetic.

However, this code only uses 84 steps to get around the circle. We can precalculate all of those points, store them in a table and use the table instead.

static int tableIndexX = -1;
static int tableIndexY = 0;
if (tableIndexX == -1)
    tableIndexX = SinTableSize / 4;

for (int i = 0; i  2e5; i++)
{
    translateX = SinTable[tableIndexX];
    translateY = SinTable[tableIndexY];
    doNothingif(&tableIndexX, &translateX);
    doNothingif(&tableIndexY, &translateY);
}
tableIndexX = (tableIndexX + 1) % SinTableSize;
tableIndexY = (tableIndexY + 1) % SinTableSize;

glTranslatef((GLfloat)(translateX), (GLfloat)(translateY), 0.0f);

This code is the same as the previous code except instead of calculating each point, it simply steps through an array of values.

The SinTable just looks like this:

const float SinTable[84] = 
{
    0.000000f,
    0.037365f,
    0.074521f,
    0.111260f,
    //... 80 more entries ...
};

With the change to a lookup table, the code now runs at 26-28 frames per second. A 5 times speed increase.

Using code to generate code with a build rule

If you've ever used lookup tables, you'll know that they can be annoying to maintain. If you want to change them, you need to regenerate them and then reintegrate them into your project.

With a custom build rule, the regeneration and reintegration can be done automatically.

The code that generates the SinTable looks like this:

enum
{
    ProcessName = 0,
    OutputFile,
    TableSteps,
    ArgumentCount
};

int main (int argc, const char * argv[])
{
    if (argc != ArgumentCount)
        return 1;
    
    FILE *outputFile = fopen(argv[OutputFile], "w");
    long tableSteps = strtol(argv[TableSteps], NULL, 10);
    
    fprintf(outputFile, "const float SinTable[%ld] = \n", tableSteps);
    fprintf(outputFile, "{\n");
    for (long i = 0; i  tableSteps; i++)
    {
        fprintf(outputFile, "    %ff,\n", 0.5f * sinf(i * 2.0f * 3.14159265f / tableSteps));
    }
    fprintf(outputFile, "\n};\n");
    fprintf(outputFile, "const long SinTableSize = %ld;", tableSteps);
    
    return 0;
}

I put it in a file named SinTable.gen.c then I added a custom build rule to the target (Project→Edit Active Target→Rules).

The custom build rule looks like this:

buildrule.png

What this does is:

  1. Takes any file that ends in .gen.c
  2. Compiles it to a .gen file in the Derived files directory
  3. Executes the .gen program to generate a gen.result.c file in the same directory
  4. Tells Xcode that it produces the gen.result.c file and Xcode will then build it according to Xcode's standard C compilation rules, integrating it with the rest of the program.

Custom Build Rules versus Custom Build Phases

Many people are familiar with Custom Build Phases for running scripts during their builds. It is important to understand the differences between the two:

Custom Build RuleRun Script Custom Build Phase
Is an arbitrary /bin/sh scriptIs an arbitrary /bin/sh script
Runs on every input of a given typeRuns exactly once per build
Only runs when sources changeRuns on every build
Outputs can be automatically picked up by Xcode for further processing by other build rulesXcode doesn't touch outputs — you must handle all processing yourself
Only visible in the Target's Settings windowVisible in the Group Tree by expanding the Target

Custom Build Rules are ideal for generating files that will be picked up by another build rule (for example, generating source code or .o files). Custom Build Phases are a better option for applying build numbers or handling the final built product.

Conclusion

Download the complete project for this post: Spinner.zip (25kb).

5 times faster, easy to implement and maintain.

Of course, lookup tables have a major limitation: they use memory. This table was only 84 entries long, so there's no real problem but if you need thousands of entries, you'll need to test to make sure you're actually gaining performance. Also, if the table is never in cache (because you're using huge amounts of memory between lookups), you're unlikely to save much time.

The point of this post though was to demonstrate build rules. This build rule keeps the lookup table up-to-date on every build and won't run unless the .gen.c file changes, so it won't recompile unnecessarily.

This last point is the primary advantage of a build rule: it only runs when the source file changes. Of course, if you need to run something on every build, you should use a Run Script Custom Build Phase instead.

by Matt Gallagher (noreply@blogger.com) at February 08, 2010 04:59 PM

February 07, 2010

Matt Legend Gemmell

Ask me anything

I discovered Formspring today via Twitter, and I think it’s an interesting idea: you can ask people questions on anything you like, and see their responses listed. Very simple and not very original, but the lack of a need to sign up (though you can if you want to) and the simplicity of the interface is somehow very conducive to just asking and answering.

I’ve already answered almost 40 questions on all kinds of things (mostly Mac/iPad/iPhone UI/interaction questions), and I’ve love to hear yours – though please note that I’m more interested in giving my opinions on things than answering specific technical questions. You can ask me a question here.

by Matt Legend Gemmell at February 07, 2010 11:25 PM

waffle

Not All About You

Once again, the universal approach, presented slightly differently. Joshua Prince-Ramus talks about how architects have strayed to being “above” execution; how the sketch and the initial idea is genius, and the rest is a long, grueling let-down as the artistic vision collapses into a realistic compromise. And shows a project he was involved with where they didn’t do that — a theater that is flexibly constructed and can be arranged into different configurations.

I say the universal approach because this pattern is evidently sane, well-tested and produces good results: talk to people. Figure out what they want. Don’t rely on them telling you what they want, and don’t rely on you knowing what they want. Figure out a way to separate what they want from how they want it, which problem they want solved from how they want it solved, and work towards delivering that in the most appropriate way possible. Do rely on them and yourself telling you what they like.

This way of doing things is hard: it takes time and effort and introspection. Easy mode for Joshua would have been to tear down the hulk of an arena that was there before and build something that was just beautiful instead. People would have liked it and he would probably have gotten awards and pats on the back. And then ten years later, when the theater had lost their advantage (watch the talk; I won’t spoil everything), people would blame it on the stupid new building and conclude that beautiful is bad and that architects will charge a mint to make things pretty and round every corner but not actually do something. That’s not only stereotypical but probably true in a sad number of cases.

Look deeper. Think about things. Change them. But do it as you get the facts, not beforehand.

by Jesper at February 07, 2010 01:40 PM

February 06, 2010

Uli's Web Site

Debugging Assembler on Mac OS X

The thing a programmer probably does most is, unsurprisingly, debugging. Not that programmers necessarily love debugging, but if you don't have a high pain tolerance for debugging, you probably don't want to pursue a career in programming. On the other hand, if you like the challenge of the bug hunt, you should try getting into this biz. Or into exterminating. Whatever makes you happy, man.

Anyway, my recent posting on Intel Assembly Language Programming on Mac OS X kinda left you hanging in the air on this one. I didn't say anything about debugging. Why? Because, honestly, I hadn't got that far yet. Of course, the first bug didn't leave me waiting for long, so here's some handy tools if you want to debug your assembler program.

First, you need to compile your assembler source files with GCC using the -g option. That will give you debug symbols, which means the debugger will show you each line. Once you've done that, you just launch GDB, on the command line, as usual:

% gdb path/to/your/executable

You'll get the GDB prompt you may have already seen in Xcode's debugger console. Type in

(gdb) start

and it will jump to the start of your main function. GDB will always print the next line, and you can use the step command to execute it and see the next one. Of course, you may want to see what is in a particular register or at a particular memory address. Easy:

(gdb) print/x $eax

will print register eax as hexadecimal (that's what the '/x' means - there's also '/d' for decimal, '/c' for character, '/s' for string and '/t' for binary). If you want to view a memory location, you use the 'x' command instead.

(gdb) x/1xb $eax

will take the address in $eax, and print 1 byte at that address in hexadecimal. The parts after the slash decode into /<count><displayFormat><type>. displayFormat is the same as the thing after the slash when you print, count is a number indicating how many to print, and type is 'b' for byte, 'h' for halfword (2 bytes) or 'w' for word (4 bytes).

Oh yeah and to get out of gdb again, the command is quit. Happy debugging!

Update: I recently realized I'd omitted two important little tricks from this description: If you don't have debug symbols, you can still step through code. The relevant commands are

(gdb) si
which steps through code by one instruction (this even works with system functions etc.) and
(gdb) p/i
which disassembles and prints the current instruction.

February 06, 2010 11:00 PM

Cocoa With Love

A sample Mac application with complete unit tests

In this post, I present a complete Cocoa Mac application implemented with unit tests for all created code. I'll create the tests first and then only add the code required to make the tests pass, largely following a test-driven development (TDD) methodology.

Next week I'll show the configuration and implementation of this project as an iPhone application for the benefit of Cocoa Touch developers.

Introduction

A few days ago, I spent some time searching for a Cocoa application with source code and full unit tests but I was only able to find Apple's trivial iPhoneUnitTests sample project.

With more than four years of official support (Apple added OCUnit to the Developer Tools in 2005) and a large number of articles and blog posts by Mac programmers endorsing unit testing and offering solutions to problems within unit testing, it is surprising to me that there are so few code examples showing Cocoa applications with full unit tests.

So I decided to re-implement one of my own projects (the WhereIsMyMac application from an earlier post) with complete unit tests using a test-first approach — I'll create failing tests and only add code to the project to pass those failing tests.

I'll be cheating a bit relative to proper test-first development (since this is a re-implementation of an existing project, I already know what the final code should be) but I'll keep to the spirit of the process by only adding as much code as I need to make the tests pass.

I know people will want to see how this works on the iPhone but since this post is already large, I've deferred that implementation until next week.

Xcode unit testing targets

There are two different ways of configuring Xcode for unit testing: logic test targets and application test targets.

  • Logic tests — these are run in a executable that is separate from your application. The separate build can be easier to manage, faster to build and is easier to run objects in isolation since it avoids the application setup. However, you cannot test components which rely on the application (which is most user interface components). Generally, this type of test target is intended for libraries, frameworks and testing the back-end (model components of model-view-controller) of your application.

    Logic tests are easily run at build-time or from the command-line, which is helpful for continuous integration or automated test processes.

  • Application tests — these tests let the application load first and are subsequently loaded into the existing application. This means that the full application environment is available to your tests. In many cases, controller tests and view tests need to be run as application tests since they are reliant on the full environment.

    Application tests allow your application to be tested in a more realistic environment, reducing the chance that environment or integration level issues will be missed. They are normally run as a separate step (not as part of the build) and therefore may be less convenient for tests that need to be run every time.

I'll focus exclusively on the second type of testing target, since it will allow full testing of the application.

It may seem strange to talk about "unit tests" which are supposed to be run in isolation but then talk about "Application tests" which provide the environment in which to run tests. The reality is that you can only isolate user-interface unit tests from your own code — there will always be some interaction (in hidden and not controllable ways) with the application framework code. Windows, views and controls simply won't work if there's no application around them.

Mac project configuration

One of the best sources of information on configuring Xcode for Unit Tests is Chris Hanson's series on unit testing. I'll follow many of the steps that he describes and further add OCMock integration to the procedure.

After you've created a blank project, use the "Project→New Target..." menu item to add a new "Cocoa→Unit Testing Bundle" Target to the project.

Note: The testing target is a separate target. This means that you need to be careful of target membership. All application source files should be added to the application target only. Test code files should be added to the testing target only.

It'd be great if that's all that you needed but there's more.

First, drag your application's target onto the unit testing target to create a dependency (force the application to build before the unit tests).

Then edit the unit testing target's settings (Right click→Get Info) and set the "Build→Linking→Bundle Loader" for all configurations to:

$(CONFIGURATION_BUILD_DIR)/WhereIsMyMac.app/Contents/MacOS/WhereIsMyMac

where "WhereIsMyMac" is the name of the application you're unit testing. This will let the testing target link against the application (so you don't get linker errors when compiling).

Also set the "Build→Unit Testing→Test Host" to $(BUNDLE_LOADER) (this will give this property the same value as the above setting). This property lets the automated build-time script know to launch the application and inject the unit testing bundle into it to start the tests.

Logic tests note: If you want to do logic tests instead of application tests, leave the Bundle Loader and Test Host fields empty and add all files you want to test to the test target (so the test target becomes a separate, self-contained target instead of linking against the main application).

Finally, download a copy of OCMock, place the OCMock.framework in the same directory as your .xcodeproj file and set the "Build→Search Paths→Framework Search Paths" to:

  • "$(SDKROOT/Developer/Library/Frameworks"
  • "$(SRCROOT)"

Neither need to be recursive. The quotes are to handle potential spaces in your paths. The first search path will probably already exist in the settings but we add the second search path so that the OCUnit framework will be found in the project's directory.

The configuration so far will run all tests as a build step (the Cocoa Unit Testing target includes a Run Script build step that runs all the unit tests).

To allow debugging as well as build-time execution, add a new executable to the project ("Project→New Custom Executable...") with a path relative to the Build Product of:

WhereIsMyMac.app/Contents/MacOS/WhereIsMyMac

and in the custom application's settings (Right click→Get Info) on the Argument tab, set the arguments and environment variables as follows:

executable_settings.png

Most of these settings configure the application to load our test bundle into itself when it runs. The :$(SRCROOT) at the end of fallback framework path is to allow the application to find the OCUnit framework in our project directory at runtime.

Separate executable: since this test debugging executable is a separate executable, you will need to switch to the debugging executable for debugging tests and switch back when you want to run the application normally.

AppDelegate Tests

Startup integration

The application will start with the WhereIsMyMacAppDelegate and we'll use the the WhereIsMyMacAppDelegate to load the main window.

The first test is therefore to ensure that application's delegate is an instance of WhereIsMyMacAppDelegate on startup.

- (void)testAppDelegate
{
    id appDelegate = [[NSApplication sharedApplication] delegate];
    STAssertTrue([appDelegate isKindOfClass:[WhereIsMyMacAppDelegate class]],
        @"Cannot find the application delegate.");
}

This is a short and simple test but it isn't a unit test. It's actually an integration test (since it is testing the fully connected +[NSApplication sharedApplication] in place.

An ideal unit test would test the NSApplication in isolation and ensure that it creates and sets its delegate property correctly. This is infeasible since NSApplication can't be isolated so we simply accept the nature of the class and test the instance of sharedApplication that should be created on startup. Of course, unit testing NSApplication itself shouldn't be necessary but an integration test to ensure that the startup of the program leads correctly to the creation and setting of the WhereIsMyMacAppDelegate is still a good idea.

applicationDidFinishLaunching:

The next test is to ensure that applicationDidFinishLaunching: on the delegate will:

  1. create the WhereIsMyMacWindowController and set it on the delegate
  2. load the WhereIsMyMacWindowController's window
  3. make the WhereIsMyMacWindowController's window the main and key window
- (void)testApplicationDidFinishLaunching
{
    WhereIsMyMacAppDelegate *appDelegate =
        [[[WhereIsMyMacAppDelegate alloc] init] autorelease];

    id mockWindow = [OCMockObject mockForClass:[NSWindow class]];
    [[mockWindow expect] makeKeyAndOrderFront:appDelegate];

    mockWindowController = [OCMockObject mockForClass:[WhereIsMyMacWindowController class]];
    [[[mockWindowController expect] andReturn:mockWindow] window];
    NSUInteger preRetainCount = [mockWindowController retainCount];

    [appDelegate applicationDidFinishLaunching:nil];
    
    [mockWindowController verify];
    [mockWindow verify];
    
    NSUInteger postRetainCount = [mockWindowController retainCount];
    STAssertEquals(postRetainCount, preRetainCount + 1, @"Window controller not retained");

    id windowController;
    object_getInstanceVariable(appDelegate, "windowController", (void **)&windowController);
    STAssertEqualObjects(windowController, mockWindowController,
        @"windowController not set on appDelegate");

    object_setInstanceVariable(appDelegate, "windowController", nil);
    mockWindowController = nil;
}

This test is a near perfectly decoupled unit test of the -[WhereIsMyMacAppDelegate applicationDidFinishLaunching:] method. However, the approaches used to decouple it from the rest of the program probably make it tricky to understand.

The first two lines create a clean WhereIsMyMacAppDelegate to test.

The second two lines create a mock NSWindow that we use to check that the window is brought to the front by makeKeyAndOrderFront:. In conjunction with the later [mockWindow verify] this will test the 3rd requirement in the list above.

The next three lines create a WhereIsMyMacWindowController that will be swapped in place of any WhereIsMyMacWindowController that the appDelegate tries to create (more on how this works in the next paragraph). The mockWindowController is told to expect window to be invoked and when it does, will return the mockWindow. In conjunction with the [mockWindowController verify], the retain count checks and the STAssertEqualObjects will verify the first two requirements in the list.

I mentioned that mockWindowController will be substituted in place of a real WhereIsMyMacWindowController any time the appDelegate tries to create a WhereIsMyMacWindowController. This works because mockWindowController is a global variable that affects the following category:

id mockWindowController = nil;

@implementation WhereIsMyMacWindowController (WhereIsMyMacAppDelegateTests)

- (id)init
{
    if (mockWindowController)
    {
        [self release];
        return mockWindowController;
    }
    
    return invokeSupersequent();
}

@end

This category overrides the -[WhereIsMyMacWindowController init] method to return the mockWindowController if it exists, otherwise the default behavior. The invokeSupersequent() comes from my old Supersequent implementation post (it's like invoking the super method but will invoke the current class' base or earlier category implementation, not just a genuine super method and is more flexible — though slower — than method swizzling).

Of course, we only want this override to return the mock object at specific times. This is why the mockWindowController must be explicitly set back to nil at the end of the method.

Notice that the category overrides init, not alloc: technically, overriding alloc would prevent any method being invoked on WhereIsMyMacWindowController (making the test perfectly decoupled from other classes) however this would mean that we'd need to invoke init on the mock object and OCClassMockObject does not let you mock any methods that it implements for itself (this includes all of the NSProxy methods plus initWithClass: and mockedClass). So instead, we override init and make the acceptable tradeoff to allow +[WhereIsMyMacWindowController alloc] to be invoked.

A related point is that OCClassMockObject can't mock retain or release. This is why manual checks on the retainCount are used instead of asking the mock object to expect a retain. If you expect autorelease to be used instead of release, you'd need to wrap the tested method invocation in an NSAutoreleasePool to flush the autorelease before testing the retainCount.

A final point about this test: it uses object_getInstanceVariable and object_setInstanceVariable to get the windowController from the appDelegate instead of the property accessor. The reason for this is that object_getInstanceVariable directly reads the value from the object without invoking any accessor methods that might have secondary effects. Some code presented elsewhere uses valueForKey: to achieve the same effect but the problem with this is that valueForKey: will use the window getter method if it exists — we want to directly test that the actual instance variable is set on the class without interference.

applicationWillTerminate:

The final tests for the WhereIsMyMacAppDelegate are for the applicationWillTerminate: method. This method should close window and release it.

- (void)testApplicationWillTerminate
{
    WhereIsMyMacAppDelegate *appDelegate =
        [[[WhereIsMyMacAppDelegate alloc] init] autorelease];
    
    id mockWindowController = [OCMockObject mockForClass:[WhereIsMyMacWindowController class]];
    [mockWindowController retain];
    object_setInstanceVariable(appDelegate, "windowController", mockWindowController);
    
    NSUInteger preRetainCount = [mockWindowController retainCount];
    [[mockWindowController expect] close];

    [appDelegate applicationWillTerminate:nil];
    
    [mockWindowController verify];

    NSUInteger postRetainCount = [mockWindowController retainCount];
    STAssertEquals(postRetainCount, preRetainCount, @"Window controller not released");

    id windowController;
    object_getInstanceVariable(appDelegate, "windowController", (void **)&windowController);
    STAssertNil(windowController, @"Window controller property not set to nil");
}

After creating an appDelegate to test, this method creates a mock WhereIsMyMacWindowController, tells it to expect a close invocation, sets it as the windowController on the appDelegate to this new mock object, invokes applicationWillTerminate: on the appDelegate, verifies that the close method was invoked, ensures that the retainCount is decremented by one and that the windowController instance variable is set to nil.

That's three failing tests. One is more of an integration test than a unit test (since it relies on the NSApplcation operating in place) but the others are genuine isolated unit tests on the WhereIsMyMacAppDelegate. The implementation to pass these tests is less interesting but you can have a look at the sample project to see how I added code to pass these tests.

Window Controller Tests

loadWindow integration

As with the application delegate, the first test is an integration test. We need to test that the loadWindow method will load the required user interface elements from files in the bundle. This is similar to Chris Hanson's "Trust by verify" approach except that I test the loading of the window separately from the windowDidLoad and window methods.

- (void)testLoadWindow
{
    [windowController loadWindow];

    WebView *webView;
    object_getInstanceVariable(windowController, "webView", (void **)&webView);
    CLLocationManager *locationManager;
    object_getInstanceVariable(windowController, "locationManager", (void **)&locationManager);
    NSTextField *locationLabel;
    object_getInstanceVariable(windowController, "locationLabel", (void **)&locationLabel);
    NSTextField *accuracyLabel;
    object_getInstanceVariable(windowController, "accuracyLabel", (void **)&accuracyLabel);
    NSButton *openInBrowserButton;
    object_getInstanceVariable(windowController, "openInBrowserButton", (void **)&openInBrowserButton);
    
    STAssertTrue([windowController isWindowLoaded], @"Window failed to load");
    STAssertNotNil(webView, @"webView ivar not set on load");
    STAssertNotNil(locationLabel, @"locationLabel ivar not set on load");
    STAssertNotNil(accuracyLabel, @"accuracyLabel ivar not set on load");
    STAssertNotNil(openInBrowserButton, @"openInBrowserButton ivar not set on load");
    STAssertEqualObjects(windowController, [openInBrowserButton target],
        @"openInBrowserButton button doesn't target window controller");
    STAssertTrue([openInBrowserButton action] == @selector(openInDefaultBrowser:),
        @"openInBrowserButton button doesn't invoke openInDefaultBrowser:");
}

The windowController is a fixture that's allocated in the setUp method. The majority of this method then gets the instance variables from the windowController after the loadWindow method is invoked and tests that the required properties are all set.

We can now test the windowDidLoad method as a separate step to the loadWindow. The windowDidLoad should create a CLLocationManager object, set the window controller as the delegate and start location updates.

windowDidLoad
- (void)testWindowDidLoad
{
    mockLocationManager = [OCMockObject mockForClass:[CLLocationManager class]];
    [[mockLocationManager expect] setDelegate:windowController];
    [[mockLocationManager expect] startUpdatingLocation];

    [windowController windowDidLoad];

    [mockLocationManager verify];
    
    object_setInstanceVariable(windowController, "locationManager", nil);
    mockLocationManager = nil;
}

This uses the same category override approach that was used in the testApplicationDidFinishLaunching method to swap in a mock CLLocationManager and ensure that the appropriate methods are invoked.

locationManager:didUpdateToLocation:fromLocation:

Next step: verify that the correct Google Maps location is loaded in the WebView's mainFrame when a given coordinate is passed to the WhereIsMyMacWindowController implementation of the -[CLLocationManagerDelegate locationManager:didUpdateToLocation:fromLocation:] method.

This test method is pretty big but the essence is that:

  • The web view and its main frame are mocked.
  • The main frame is told to expect specific a specific HTML string that's loaded from a pre-created file.
  • The method is then passed the exact location that should trigger that HTML string.
  • The mock web frame is then asked to verify that the expected HTML string was loaded.
  • The window's labels are also tested to ensure they receive the correct values.
- (void)testUpdateToLocation
{
    NSString *htmlString =
        [NSString 
            stringWithContentsOfFile:
                [[NSBundle bundleWithIdentifier:@"com.yourcompany.UnitTests"]
                    pathForResource:@"WebPageTestContent" ofType:@"html"]
            encoding:NSUTF8StringEncoding
            error:NULL];
    id mockWebView = [OCMockObject mockForClass:[WebView class]];
    id mockWebFrame = [OCMockObject mockForClass:[WebFrame class]];
    [[[mockWebView stub] andReturn:mockWebFrame] mainFrame];
    [[mockWebFrame expect]
        loadHTMLString:htmlString
        baseURL:nil];
    object_setInstanceVariable(windowController, "webView", mockWebView);

    NSTextField *locationLabel = [[[NSTextField alloc] init] autorelease];
    NSTextField *accuracyLabel = [[[NSTextField alloc] init] autorelease];
    object_setInstanceVariable(windowController, "locationLabel", locationLabel);
    object_setInstanceVariable(windowController, "accuracyLabel", accuracyLabel);

    CLLocationCoordinate2D coord;
    coord.longitude = 144.96326388;
    coord.latitude = -37.80996889;
    CLLocation *location =
        [[[CLLocation alloc]
            initWithCoordinate:coord
            altitude:0
            horizontalAccuracy:kCLLocationAccuracyBest
            verticalAccuracy:kCLLocationAccuracyHundredMeters
            timestamp:[NSDate date]]
        autorelease];
    
    [windowController
        locationManager:nil
        didUpdateToLocation:location
        fromLocation:nil];
    [windowController
        locationManager:nil
        didUpdateToLocation:location
        fromLocation:location];
    
    [mockWebFrame verify];
    
    STAssertEqualObjects(
        ([locationLabel stringValue]),
        ([NSString stringWithFormat:@"%f, %f", coord.latitude, coord.longitude]),
        @"Location label not set.");
    STAssertEqualObjects(
        ([accuracyLabel stringValue]),
        ([NSString stringWithFormat:@"%f", kCLLocationAccuracyBest]),
        @"Location label not set.");
}

An interesting point to notice here is that the WebPageTestContent file is loaded from a bundle that isn't the mainBundle. This is because the test resides in the UnitTests.octest bundle, not the application's bundle (which is the "main" bundle).

locationManager:didFailWithError: and openInDefaultBrowser:

I'll leave out the code for the locationManager:didFailWithError: test — it's largely the same as the previous test but with a different HTML string to load in the web view's main frame. You can see it in the downloaded project if you wish.

Similarly, openInDefaultBrowser: is just a URL, generated from the current location and sent to the shared NSWorkspace (which we mock through category overrides) so the test contains largely the same elements — so I'll omit the code for this test too. Again, check the downloaded project if you're interested.

dealloc:

All that remains is to create tests for the dealloc method to ensure that the locationManager receives a stopUpdatingLocation and a release message.

- (void)testDealloc
{
    id mockLocationManager = [OCMockObject mockForClass:[CLLocationManager class]];
    NSUInteger preRetainCount = [mockLocationManager retainCount];
    [mockLocationManager retain];
    object_setInstanceVariable(windowController, "locationManager", mockLocationManager);
    
    [[mockLocationManager expect] stopUpdatingLocation];

    [windowController dealloc];
    
    [mockLocationManager verify];

    NSUInteger postRetainCount = [mockLocationManager retainCount];
    STAssertEquals(postRetainCount, preRetainCount, @"Location manager not released");
    
    windowController = nil;
}

Notice that we have to set windowController to nil at the end. This is because invoking dealloc on the windowController fixture has deallocated it and we need to ensure that the tearDown method doesn't try to invoke release on it.

Six failing tests for the WhereIsMyMacWindowController. You can look at the downloadable project to see the code added to pass these tests.

Conclusion

Download the complete WhereIsMyMac-WithUnitTests.zip (139kb).

Warning: Custom executables (like the UnitTestWhereIsMyMac discussed in this post) are part of user data in the project file, so you will not see the UnitTestWhereIsMyMac custom executable in the downloaded project unless you create it yourself or your username happens to be "matt".

This project includes OCMock.framework, which is Copyright (c) 2004-2009 by Mulle Kybernetik. OCMock is covered by its own license (contained in the OCMock.framework/Versions/A/Resources/License.txt file).

In this post, I created a Mac project, created unit tests for all required functionality (plus two integration tests) and ultimately added code to make the project pass those tests. I've shown the configuration required for unit testing targets in Xcode and the implementation of the tests themselves, which show how to isolate units of a program (using mock objects and category overrides) for properly decoupled unit testing.

Unit tests for all created code does not mean that the project is "fully tested". There are lots of aspects associated with integration, runtime and memory behaviors, user events and the behaviors of the Cocoa frameworks that are not covered by these tests. Of course, this is the limit of "unit testing" for classes that operate in an application framework — to test these other aspects requires different kinds of tests.

Next week, I'll be presenting the same post developed for the iPhone. I apologize that this will result in two posts that almost the same but there are enough differences between the two that I couldn't squeeze both into a reasonable sized post. I also hope that by separating the posts, the result will be easier for dedicated Mac or iPhone programmers to follow.

Finally, a disclaimer: please don't consider the existence of this post as a recommendation that you should necessarily write your applications with full unit tests. It is important to look at the work involved and weigh the associated time costs and against your project's need for unit level validation. There are alternative approaches for maintaining code quality that have different associated costs and benefits which I hope to discuss and compare in a later post.

by Matt Gallagher (noreply@blogger.com) at February 06, 2010 10:48 PM

Clickable Bliss

Ira Glass: On Good Taste

In this excerpt from a longer series on story telling Ira Glass talks about having good taste and growing as a creator. If you are a software developer, podcaster, if you create stuff, watch at least the first three minutes.

http://www.youtube.com/watch?v=-hidvElQ0xE

by Mike Zornek at February 06, 2010 02:24 AM

February 05, 2010

Clickable Bliss

ProfitTrain updates

The open beta for ProfitTrain continues this week with the latest 2.0b21 release. My hope is to finish up the 2.0 for official release by the end of the month so if you have some time to give it a quick beta test please do.

The help book for ProfitTrain is coming along as well. The Help Book is offered via the built-in Apple Help Book application as well as online.

Mirroring the help book online will be so nice for support emails. So many times I would have to give a blind reference to check out article X in the built-in help. It’s going to be so nice to have some real links to send people too. Not to mention how people will find answers via Google.

The latest article in the help book is Recording Expenses.

This article will give an overview of how expenses work in ProfitTrain. Using the expense record system in ProfitTrain enables you to keep track of business expenses. There are many reasons you want to do this but the main two are keeping track of the profitability of your business and recording tax deductible business expenses for your end of year tax filing.

Expenses was something I had to cut for time in the introduction screencast but I hope to do a separate screencast of it soon. Until then, this article is a nice overview.

Quick note though, there is a bug in the current build. Expense Categories you create don’t show up in the pulldowns for line items or blueprints right away. If you close and restart ProfitTrain they will show up properly so for now, please use the work around. Hope to have this one fixed soon.

Thanks again for you help and support.

by Mike Zornek at February 05, 2010 07:40 PM

NSBlog

Friday Q&amp;A 2010-02-05: Error Returns with Continuation Passing Style

The Earth has moved 6.9 degrees around the Sun since my last post, which means it's time for another edition of Friday Q&A. This 6.9-degree segment, Guy English has suggested that I talk about the use of continuation passing style to simplify error returns in Objective-C code.
(Read More)

February 05, 2010 06:36 PM

Cocoa With Love

Finding the cause of performance issues in your programs

This post is a response to reader questions asking how, in my previous post on Replacing Core Data Key Paths, I knew that the biggest performance problem in my initial approach was the incremental reallocation of NSMutableSet. In this post, I'll look at basic time and memory profiling on the Mac and talk about the most common types of scenario to look for when you're trying to solve performance problems.

Introduction

In my previous post, Performance Tests: Replacing Core Data Key Paths, I presented a simple category to improve Core Data key path fetching by 25%-35% (actually the improvement was much greater at small set sizes but they rarely matter). The improvement worked by using property accessors to access the Core Data values instead of looking up the properties by string name.

However, the original "naïve" approach that I used to do this actually took more than twice as long as the original Core Data string key paths.

This week, I'll look at how I analyzed this code and how I worked out where the performance bottleneck was.

The code to analyze

The purpose of the code was to replace this:

NSSet *projectNames = [company valueForKeyPath:@"projects.name"];

with this:

NSSet *projectNames = [company.projects slowObjectValuesForProperty:@selector(name)];

But, as the "slow" in the method name reveals. The initial approach was slower — by approximately a factor of 2.

The implementation of the slowObjectValuesForProperty: method is really simple. Let's look at it:

- (NSSet *)slowObjectValuesForProperty:(SEL)propertySelector
{
    NSMutableSet *result = [NSMutableSet set];
    for (id object in self)
    {
        id value = [object performSelector:propertySelector];
        if (value)
        {
            [result addObject:value];
        }
    }
    return result;
}

The test harness that I'll be using will be the PropertyAccessors project from the Performance Tests: Replacing Core Data Key Paths post, with all tests except the "Key Path Accessor" and "slowObjectValuesForProperty: accessor" ifdef'd out.

Time profiler

The first approach you should use when your code isn't running as fast as desired is a basic time profile.

As preparation for this, you should make sure that the test will run for long enough to give useful test results. Time profiling works by suspending the program at regular intervals and reading the program's current position. This amounts to a random sampling over time. But these random samples won't be helpful unless there are enough in your time critical code. Increase your data size or put the code you're looking at in a loop and try to make it run for at least 2 seconds.

For this test, I set the NumCompanies and NumProjectsPerCompany to 100 (giving a total data size of 10,000 project names) and further set the NumTestIterations to 1000 (so this test will fetch 10 million names in total).

This gives the following test durations:

Key Path set iteration test took                4.13078 seconds.
Slow objectValuesForProperty: test took         8.83262 seconds.

By default, the Time Profiler will sample once every millisecond. If your tests cover a large amount of code, you'll need more samples — so either make your tests run longer or increase the sample frequency (Time Profiler can go as fast as 20 μs).

Build the project (but don't run it directly from Xcode). Then select the "Run→Run with Performance Tool→Time Profiler" menu. You can also use "Shark" for this but they both work in a similar way and the Time Profiler runs in Instruments which has a nicer, newer interface (although Shark can track a few lower level metrics that Instruments still lacks).

iPhone note: The Time Profiler is not available to iPhone projects. For iPhone projects, select the "CPU Sampler" in the "Run with Performance Tool" menu. The "CPU Sampler" is higher overhead and cannot sample as often or as rigorously but will normally provide similar information.

The PropertyAccessors test will self-run, so you can just watch it go. For other projects where some interactivity may be required, you'll need to interact with the program until it runs the code you want to examine. If your test has a short duration or a large amount of code, you may need to click the "i" next to the "Time Profiler" Instruments icon at the top to change the sample rate to get good coverage for your program (you'll need to rerun the test if you make this change).

instruments1.png

Your window should look like this. If it doesn't, make sure the "Detail" view is visible (you won't need the "Extended Detail" view). Also make sure the "Call Tree" view is selected in the "Detail" view (it's the icon at the bottom of the window that looks like three horizontal lines stacked slightly askew).

Once the program finishes, uncheck the "Invert call tree" checkbox in the left column then expand the "Main Thread → start → main" elements and we'll see the most expensive steps in the main() function (which is where all the tests are run in this project).

instruments2.png

The top item in the main() function is the fetchObjectSetForRequest: method but we're not looking at that here (it's just Core Data loading and prefaulting the entire database).

Instead, we want to know why the second item, slowObjectValuesForProperty:, takes 2.23 times longer than the third item, valueForKeyPath:.

Expanding the tree from the slowObjectValuesForProperty: method twice, we see CFBasicHashAddValue() occupies almost all of this method's time.

If we expand the valueForKeyPath: call tree 7 times, we can see the same CFBasicHashAddValue() is used to create the set here but for some reason, this function only takes 1402 milliseconds here, compared to 5996 milliseconds for the slowObjectValuesForProperty: method.

The same function, acting on the same data. But one takes 4 times longer than the other. What is the explanation?

There are two possible answers: either the slow case is suffering from poor memory caching performance, or it is acting repeatedly and is slow due to repetition.

Object allocations

Shark can measure event counts (like cache misses and memory bandwidth) if you actually think that's the cause of a problem but it's unlikely to be the problem here. In most situations where the Time Profile isn't clear cut, the best thing to try here is a object allocation analysis.

As with the Time Profile, we run the Object Allocations performance tool from "Run→Run with Performance Tool→Object Allocations" menu in Xcode.

instruments3.png

Again, switch to the "Call Tree" view and make sure "Invert Call Tree" and "Separate by Category" are off.

Additionally, right-click (or control click) in the table header of the "Detail" view and make certain that "Count" and "Bytes" columns are both enabled.

If you navigate into "Main Thread → start → mainslowObjectValuesForProperty:", then follow the biggest allocation 4 times and you'll see that __CFBasicHashRehash is responsible for allocating almost all of this method's memory.

Similarly navigating into the valueForKeyPath: of the other test, reveals the same method 7 levels in allocates a majority of this method's memory.

However, there are three big differences between the memory performances of the __CFBasicHashRehash in each case:

  1. The slowObjectValuesForProperty: version performs 800,000 allocations whereas the valueForKeyPath: version performs exactly 100,000 (equal to the number of tests).
  2. The slowObjectValuesForProperty: version allocates 210.57MB whereas the valueForKeyPath: version allocates just 97.66MB.
  3. The slowObjectValuesForProperty: version is found inside CFSetAddValue where the valueForKeyPath: version is found inside CFSetCreate.

From the first point, it would appear that the presumption that the slow version is slow because it unnecessarily repeats itself is looking accurate — it is repeatedly reallocating.

The second point also suggests that the slow method is wasting extra memory (which is probably causing mild performance penalities). On low memory systems, this would be even worse.

The third point suggests why the first two might be the case: the slow method needs to reallocate as it adds more data.

Understand what the code you're invoking does

All this helps to identify where your program is spending its time. From here, you could probably work out that allocating the NSMutableSet once, instead of repeatedly as you go, is a good idea.

Of course, you need to confirm this by applying your changes and testing. Changing this code to allocate once instead of repeatedly as it goes is easy — it takes a matter of seconds. You do need to be wary though about spending too long optimizing code on a whim. The more involved the code change, the more confident you should be that you're actually fixing a problem and not inspecting irrelevant code or making unhelpful changes.

This is where it helps to really understand the code you're playing with.

For example: the reason why moving to a single allocation with the NSMutableSet above is helpful, is not actually directly because of the allocation itself — since the biggest block of time inside slowObjectValuesForProperty: that we're trying to optimize is spent in __CFStringEqual and memcmp when you drill all the way down; it is not spent in malloc itself.

Instead, I know that whenever NSMutableSet resizes, it needs to rehash every single object back into the newly resized hash table. It is this rehashing that is hammering the __CFStringEqual and memcmp functions (since they are the functions used to hash and detect collisions in the hash table). Yes, reducing reallocations makes it faster but the biggest reason for this improvement is the nature of hashed storage: because reducing reallocations reduces the need to rehash.

As I reported in the original post, fixing this allocation so that it happens just once will speed this code up by 2.6 times but it is important to understand that the need to rehash is why this change helped — other reallocation situations may not gain as much as we have here.

Finding the best candidates for speed improvements

Generally though, allocations and reallocations are always a prime place to look. Large allocations are expensive to move around in RAM, millions of small, irregular allocations can fragment memory and every allocation normally needs to be initialized, incurring some kind of expense. Even with NSArray, which doesn't need to rehash when it reallocates, there is still a copy of the elements from the old array to the new one. The performance gain will not be as great but it is still a place to squeeze extra performance.

When optimizing, the first things to look for are:

  • Memory allocations. They're easy to find and easy to tweak. They don't always give the best performance improvements but they're a good first point to examine.
  • Iteration over large arrays to find elements. If you need to search large arrays often, you should be storing in a dictionary or other constant time access structure. Depending on the size of the array, this can be a near 100% speed improvement. i.e. never, ever search anything bigger than a trivial array.
  • Nested loops over medium to large data sets. Easy to find. Eliminate the nesting if you can. Although they can be hard to eliminate since you need to rethink how you access your data but you can often do something to reduce their impact. If you have 1 loop inside another, always put the smallest loop (in terms of number of elements) inside the bigger one if you can, since memory scales better to doing small packets of work huge numbers of times.
  • Anything non-polynomial on more than trivial data sets. Non-polynomial actions are the slowest, worst things you can do. They are occasionally required but if at all possible, think up another design. What's non-polynomial? Anything where the number of packets of work involved in processing a collection grows greater than polynomially with respect to the size of the collection (i.e. if the packets of work are "y" and the number of objects in the collection is "x", then non-polynomial means the number of packets of work exceed y=x^a for large values of x, where a is any constant). Exponential growth (i.e. y=a^x) or factorial (i.e. y=x!) are the most common kinds of non-polynomial growth. If all this is confusing, then at least know the common case: trying to find an ordering or arrangement for a set of objects by exhaustively testing every combination is non-polynomial.

You may be tempted to think that pervasive multi-threading, OpenCL, SSE vectorization or assembly optimizations are the best way to solve performance issues, since they are all "high performance" technologies and the fastest programs all use them in some combination. However, these technologies are much harder to implement than simple design improvements so they should always be something you consider once you're sure that the design can't be further improved.

Conclusion

The first rule with optimization is that you should always optimize based on evidence.

Don't begin to optimize if you can't find a bottleneck or create one with data. Optimizing without actual evidence of a bottleneck (just suspicion that there might be one in future) is called "Premature Optimization" and is normally considered a waste of time.

However, even once you know where the bottleneck is, you need to know what is causing it. If the code is small, you can just play with it to see what happens but generally you need to inspect closely. It is surprisingly easy to make the wrong guesses about what is causing performance issues and waste time changing code for no gain.

I hope I've shown you how to gather the information you need to understand simple performance problems and the types of clues you'll need to narrow down the locations in your code that can be improved.

by Matt Gallagher (noreply@blogger.com) at February 05, 2010 03:50 PM

Cocoa Therapy

The shape of interfaces to come

Real apps

I am curious about how “real apps” will work on the iPad, how an application that is more than a utility or casual/light use exposes functionality in a touch-optimized user interface.

The only available information is what Apple has shown at the iPad announcement on January 27th. We will surely discover more soon, but I wanted to get a head start and, well, couldn’t help watching the keynote a few times and grab all available footage from the post-keynote hands-on.

I assume you have probably seen the section of the keynote where iWork is shown, if not you can catch up by watching just that part, extracted and cut by Luke Wroblewski. Fraser Speirs also discusses the screenshots of iWork apps as seen in the keynote in his article iPad Fallacy #1: “It’s not for content creation”.

Many of the interactions are pretty obvious on the surface, but on a second (or third) look reveal the non obvious or the unexpected. So here’s a quick rundown of what I have found, mainly in the iPad version of Keynote, Pages and Numbers.

A lot of the UI and interaction that wasn’t shown on stage is visible in the hands-on videos. It is interesting and sometimes hilarious seeing the Apple representative stumble into features and expose the difficulties as he or she learns the UI, sometimes even failing to discover the proper gesture — notably how to exit a Keynote presentation in the endgadget hands-on video.

Many thanks to engadget, gizmodo and gdgt for their pictures of the keynote and Slashgear for their detailed hands-on video.

Controls

A slight indentation of the slides in the outline on the left in Keynote could seem just a visual representation of hierarchy, it actually is a fully functional outline with collapsible sections, note the disclosure triangle.

Sidebar Hierarchy
Outline hierarchy
Sidebar Collapse sequence
Collapse sequence after the disclosure triangle has been pressed

In two instances in Keynote popovers and UI persist in-context (next to content) only when in a mode explicitly entered and exited by the user, which seems like a reasonable rule to follow.

Transition build popovers
Transition build popovers
Image masking
Image masking in-context controls

Interaction issues

There are inconsistencies in how UI modes are entered in Keynote. Slide reordering mode is entered by tapping and holding a slide in the outline, transition setup is entered tapping the corresponding menu icon, image resize mode is entered double tapping an image.

Pictures, charts and shapes can’t be dragged out of the “insert object” popover, so in Keynote the new items are just lumped on the slide. The inability to drag is inconsistent with press-and-drag to reorder slides on the sidebar and while we don’t know what pressing and holding does, I’ll guess that since a single tap inserts the image, pressing and holding has no effect. The reason for the non functional drag and drop might also be related to the modality of popovers.

Failure to drag
Attempt to drag an image to the slide fails

Reordering columns in Numbers doesn’t appear hard to perform, but I feel like it’s nearly impossible to discover that you have to tap exactly on the column header to select it, then tap and hold to drag it.

Dragging columns
Dragging columns in Numbers

I haven’t found any footage of pictures or charts being deleted (or slides for that matter), nor any UI that could be thought to perform deletion, and the Apple representative in the Slashgear video solves it by repeatedly pressing the (prominent) undo button. This could either mean it hasn’t been implemented, or the delete gesture isn’t all that obvious.

Undo
Reaching for the visible Undo button

Multitouch is one thing, multihand a whole other, it doesn’t look at all comfortable and Phil Schiller actually had to put the iPad down when moving multiple slides and when matching image sizes in Keynote.

Multihand multitouch
Multihand multitouch. Ouch!

Complete?

The inspector icon always shows the proper inspector for the selected object, in this case text. Aside from the questionable, arguably not-keynote-ready design, the text inspectors scream incomplete! There are text styles, but where is the text style editor? Where’s a font picker? How about a color picker? These are UI elements we take for granted on a desktop, and they are necessary for content creation. Clearly they’re coming soon.

Text style
Text style popover
Text layout
Text layout popover

Finds

Here are screenshots of things I haven’t seen elsewhere.

Pressing the bottom left + opens the “Tap to insert a new slide” popover, tapping on one of the theme-preset slides animates it to the center of the screen.

Adding a slide
The new slide popover

Even though the popover arrow points to the left, the tools menu appeared after pressing the wrench icon. I didn’t expect to see “Find” or “Help” in here. The last two items are “Slide numbers” and “Check spelling”.

The Tools menu
The Tools menu

The shapes pane of the “insert object” popover.

Shapes
Shapes pane

Here Keynote had just been reopened after a crash, evidently unable to save a preview of the document.

After a crash
Keynote document browser after a crash

Content creation?

In conclusion, is the iPad going to be a good platform for productivity apps, apps that go beyond content consumption? For the time being I will have to answer with a conditional yes, despite Phil Schiller insisting that you can do “really advanced” things “with just a finger”. I feel like Apple is stil figuring out the UI and iWork will likely be a little different when it ships.

The overarching problem seems to be that finding a place for UI elements and finding a way to interact with them is a new science and needs new conventions. Additionally gestures aren’t always easily discovered even when they are consistent across apps, but the lack of conventions leads to non-uniformity which makes it even harder. The best bet here is following iWork’s behavior as much as possible.

I will say that the iPad is going to be good enough for “casual content creation” at the very least. Given time and research and experimentation with touch UIs, it definitely feels like it has the potential of eventually replacing desktop UIs for many tasks.

by duncan at February 05, 2010 12:19 AM

February 04, 2010

waffle

Another Thing

Guy I don’t know on Flickr nailed the reason for my continuous and unwavering interest in the iPad:

The iPad is the Hitchhiker’s Guide to the Galaxy.

Somewhere out there, Douglas Adams is smiling.

That might have been a reference to Numbers’ use of “42″ to represent numeric input, but all things considered, he sure is.

by Jesper at February 04, 2010 10:55 PM

Red Sweater Blog

Michael L. Jalkut – 1950-2010

Today I learned that my dad, Michael, has passed away while traveling in Washington, D.C. We were never the closest father & son pair, but I loved him, and he loved me. Over the years of my adulthood, and especially since my son Henry was born, I have been trying to work towards a closer relationship with him.

He taught me to love computers. When I was 5 and living alone with my Mom, he brought me a copy of a BASIC programming magazine, and a Timex Sinclair computer. He tried to talk through the logic of control flow with me. Of course, it flew over my head, but it taught me enough to know that my dad’s finger could move across the rules on a piece of paper, and the rules dictated where his finger would go.

A few years later he and my Mom got back together and we all moved back in together. He bought me a Commodore 64, and set me up with some fun games. I didn’t program anything, I was too busy playing Little League baseball and trying to be a normal kid. Sometimes he played catch with me. On Father’s day we would drive to San Francisco to see the Giants. He didn’t even like baseball, but he did a good job faking it for me. He bought me frozen Carnation malts.

My Dad had gone back to school in his 30’s to earn a computer science degree. When we moved back in with him, he was starting his late-blooming career at IBM, where he worked for a short time. He moved on to Digital Research and worked on GEM, a graphical windowing system not terribly unlike the Mac. Later he joined MetaWare, where he worked as a compiler engineer with the same group of people for almost 20 years.

When I was 17, a friend of mine got into legal trouble, and I could have snitched on him and made it worse. I asked my dad for help, so he took me to a lawyer and paid for it. He didn’t judge me for wanting to protect my friend. He made it possible for me to be a loyal friend, even to somebody who may not have earned my Dad’s respect.

After I graduated from college and left the house, the years seem to rush by like a blur. I did my thing in San Francisco, working at Apple, meeting my (now) wife, and going back to school for a second degree. Meanwhile, I saw my Dad a few times a year. We always expressed our love for each other, but there was a lingering anxiety and awkwardness. Our relationship had frozen somewhat in the form we had left it in my teens: each of us struggling to come to terms with our significantly differing political and metaphysical beliefs. After my wife and I moved to Boston in 2005, I saw even less of my family, sometimes only once or twice a year.

He always expressed great pride about the career path I followed. He was impressed that I had graduated from University, found a great job at Apple, and then founded my own business, all after dropping out of high school (against his wishes!). He let me know so often of his pride, that he gave me the gift of never having to worry particularly that I might have disappointed him. I think this helped me to pursue my dreams more freely than ever.

His satisfaction with my career turned him slowly but surely from an Apple-hater into one of its biggest fans. A few years ago he lost his long-time job as a compiler engineer, and reoriented himself towards the Mac, starting a business of his own, and feeling his way towards a niche. He became certified in all manner of OS X support technician programs, and even decided to attend WWDC a couple years ago. Some of you will probably remember having met him there.

His business never really took off, and a sequence of unfortunate events handed him some serious blows. Life didn’t hand him a perfect hand, but he managed to leave some beauty here with us, and I am grateful for that. I would have loved to have seen what would have become of the rest of his life, and how my own young family would have fit into it.

The circumstances of his death are sad, and personal. We barely spoke over the past year, but I had a good conversation with him at my Grandmother’s funeral in November. Suffice to say, he died too young. I miss you, Dad.

by Daniel Jalkut at February 04, 2010 02:15 AM

February 03, 2010

waffle

No Dogs Allowed

Simon Willison’s experimental dogproxy; A node.js HTTP proxy that bundles requests to equal URLs into one actual request.

Node will continue to fascinate me for a long time: it’s a tight product perfecting an existing concept, bringing it into the purview of general purpose programming and coming along at the right time. It’s wonderful how applying the right kind of design and technology can help bring out the problem (lack of asynchrony) that needs to be solved.

by Jesper at February 03, 2010 08:28 PM

Red Sweater Blog

Scantastic

I have never owned a fax machine in my life, and I hoped that things would stay that way until the last obnoxious faq-requisite institution on earth had pulled the plug on these foul machines. But … I’m dealing with some entities recently that are hard-set on faxing, and I have needed to send rather large numbers of pages.

It occurred to me, as I faced the prospect of a $100+ bill for faxing at, say, Kinkos, that I could probably buy a cheap fax machine and save some money. I was right about the money, but as far as time and anguish goes, I’m not sure I’m making out well.

I bought the HP Officejet J3680 All-in-One. It’s a printer, scanner, copier, and fax machine. How handy! We don’t have a scanner or copy machine, and I figured it would be handy to occasionally do these tasks, as well. After I got the machine out of the box I immediately sent a huge fax with it which, I have to say, went very smoothly. Unfortunately, things started to go downhill quickly after I hooked it up to my computer and installed the software from the included CD-ROM.

The install process itself was slow, but seemed to go “OK”. When it was done, I had a huge list of Hewlett-Packard apps to choose from.

I’m feeling pretty good because, not only was this machine a bargain at $50, I got all this free software with it, as well. Sweet.

I looked for something vaguely fax-related, because I wanted to see whether the fax I had sent had kept a log or copies of the pages on the machine. Hmm. “HP Fax Setup Utility” sounds promising.

Yep, that’s my new printer software, crashing straight-off-the-bat. OK, it’s possible I could just be unlucky. I mean, I am a software developer, I know that it’s impossible to write perfect software. Somebody reading this has undoubtedly run one of my applications and had it crash on them. There’s something special about this crash, though. Every crash log contains clues about the crash, and this one contains a very obvious clue. Let’s look a little closer:

To many of you, that reads as gibberish, so let me translate. What it says is that the HP application cannot launch because it relies on an external library, located in a home directory for a user named “admin”. In other words, whoever developed this application for HP did so in such a way that the application will only ever launch on their computer. Or, possibly, on the computers of other people who happen to name themselves “admin.”

What?! Say it ain’t so. It can’t be so. But, I followed all the directions. I opened the box, and I put the CD-ROM into the computer, and it says Mac support, and … I decided maybe I need to start with the software at a higher level. Hmm, this “HP Setup Assistant” sounds like a nice refuge from the storm. I’m sure this will get me back on track.

Yes, HP. I’m feeling pretty loved. At least I have the comfort of the HP logo and, as my friend Paul Kafasis observed, its “greasy mirrored surface”, to go along with my tuxedo.

OK, this is nuts. I gotta see if there are updates. I go to the HP web site and search for downloads. After a few levels of clicking, I come to this useful, if disconcerting page. In a nutshell, they know their software doesn’t work on Mac OS X 10.6:

Important: Please do not reinstall software from original HP Photosmart, Officejet, Deskjet CDs, or HP web downloads from previous Mac OS X 10.3, 10.4, or 10.5. Older software is not compatible with Snow Leopard. The latest Snow Leopard compatible software is included in Mac OS X 10.6, and you will experience the best performance and functionality if you use the latest HP software.

So on the one hand, they made a great deal with Apple to supply basic functionality in the operating system, starting in 10.6. On the other hand, the very instructions that ship inside every box will turn the user’s experience into a nightmare as I have described, until they discover the sage advice on HP’s web page. And if I can’t install the software from the CD-ROM, does that mean I don’t get access to all the additional features provided by that illustrious list of free software above? I don’t think I need it all, but I would at least like to be able to, say, read a scan off the scanner.

What has HP done wrong? As I said, mistakes happen. Bugs happen. Things are bound to go wrong. But the sheer number of things that went wrong in my attempt to use this device with my Mac made it unacceptable. At the very least, HP should put a prominent sticker on the CD-ROM that ships with these devices, alerting Mac users that it is dangerous to install the software on Mac OS X 10.6. I suppose 10.6 is still relatively new, but Apple makes pre-release versions of major releases available to companies like HP. They probably knew months and months ago, if not years ago, that the supplied software would not work with 10.6. It’s only good business to warn users of this fact.

Furthermore, some of the errors I encountered were not OS related. See the first crash I mentioned above. Bluntly, HP has shipped on their CD-ROM a utility application that will not properly run on any customer’s Mac, whether it’s 10.6 or not. I suppose they can just hope that nobody will run that application, but as it hasn’t been modified (according to my Mac) since April 26, 2007, I suppose they have had plenty of time to yank it from the CD.

OK, this has been a bit of a whine-fest, but hopefully it’s also instructive as to how hostile a company’s obliviousness in software can feel. When the simplest steps, followed as advised in the packaging, lead to a nightmare of crashes and ill behavior, then your company has a disconnect from its target audience.

by Daniel Jalkut at February 03, 2010 04:00 PM

Domain of the Bored

An introduction to Cocoa and Cocoa Touch

If you know someone who's recently taken up programming the Mac or the iPhone (or both), please give them one (or both) of these links:

As a frequent answerer of questions on Stack Overflow, I see certain patterns—not just frequently-asked questions, but also frequently-unasked questions: Things that are biting the questioner that they don't know about.

Sometimes they're thinking about things the wrong way (e.g., using property list objects where they should have a model). Sometimes there is a route to a solution (“my app is slow” “run Instruments”), but they don't know about that route. Often, they'll use wrong terms that are right on another platform (like “member variable”), like a speaker using their native language's pronunciation rules when speaking a foreign one.

To help people over these speed bumps, I've composed an introduction for new Cocoa and Cocoa Touch programmers. (Both of the above links redirect to it.)

If any part of it doesn't help them (i.e., is unclear or wrong), I'd appreciate it if you'd let me know, either here or by email.

by Peter Hosey at February 03, 2010 09:25 AM

Reunification

A common question from people new to Objective-C is “why do I have to separately alloc and init? Why can't I just call one thing and get a fully initialized object?”.

It's certainly not how other environments do it. Usually, you call one function or class method, and you get an object. Cocoa makes you send two messages: one to the class, then another to the fresh, uninitialized instance you got back. What does Cocoa know that those other environments don't?

There are two reasons why alloc and init are separate:

  • “NSResponder”* says that sometimes, NeXT wanted to initialize the same object multiple times.

    This is interesting, but horrifying to modern readers. Practically all init methods I've seen do not handle the case of initializing the already-initialized; they blindly assign newly created/retained objects to the ivars without checking for existing objects there.

    A bigger problem is when the init method releases the receiver and returns some other object; in the second message, the “other” object may in fact be the receiver (returned from the first message), so [self release] this time would be killing off an object that should stay alive. On the other hand, retaining the object before re-initializing it will create a leak if the object doesn't release itself. Unpredictable behavior is bad.

  • On the same Stack Overflow question, Darren points out that alloc is shorthand for allocWithZone:; if allocation and initialization were merged in Cocoa, then, to maintain the same functionality, every initializer would need to take a zone parameter, and optionally come in a flavor without one. You can imagine how a proliferation of initializers would ensue.

    This is essentially what the documentation says: “Separating allocation from initialization gives you individual control over each step so that each can be modified independently of the other.” I.e., both steps can be customized, so they must remain separate so that you can customize either or both.

So, there are two practical reasons why Cocoa's designers separated allocation from initialization.

But let's revisit this with modern eyes:

  • As I mentioned, in modern Cocoa, initializing an instance again is risky at best. In practice, I don't think anybody does it, and if anybody does, they probably feel guilty about it and mean to refactor that code “someday”.
  • Nobody uses zones anymore.

That blows those two reasons away.

So, let's imagine what life would be like if they had never existed in the first place, and allocation and initialization had remained one task:

+ (id) newWithFramistan:(Framistan *)framistan {
    id obj = [super new];
    if (obj) {
        obj->framistan = framistan;
    }
    return obj;
}

Right away, you can see several advantages:

  • We can name our local variable “framistan”, not “newFramistan” or anything like that.
  • No more assignment in condition (if ((self = …))).
  • No more assignment to self (which should make Wil Shipley happy).
  • Eliminates the problem of [super init] returning a different object, whereupon you would have to release the receiver. Since the receiver is the class, there is nothing for the upstream-initialized object to be different from. If the superclass wants to return an existing object, it can just do that.
  • Related to the first point, we no longer have a name conflict between instance variables and local (especially argument) variables. In init methods, we resolve this conflict with style rules, such as the aforementioned newFramistan for locals or m_framistan for instance variables; in this newWithFramistan: method, the conflict doesn't exist in the first place.
  • There is never an uninitialized object that the caller could leave lying around. We've all seen (or written) code like Foo *foo = [Foo alloc]; [foo init];; in this alternate universe, such faux pas are impossible.

There are trade-offs:

  • It's one line longer. (Depending on your employers' level of cluefulness, this may be a small advantage.)
  • Since you're not in an instance, you have to prefix every instance-variable access with obj->. I can see how this could get tedious; on the other hand, this is what prevents ivar-vs.-local name conflicts.
  • If you use object controllers that automatically prepare their content, they'll use alloc and init, bypassing this initializer. I've never used the automatic-content-preparation feature, so this doesn't affect me.
  • It'll be less than familiar to anybody who hasn't read this post, and it's certainly a change from currently-typical Cocoa code.
  • Doing this in a subclass of a class that has an unusual designated initializer, such as NSView with its initWithFrame:, could get tricky.

My opinion is mixed. On the one hand, real problems with the init way of doing things are rare for anyone who knows the ropes. On the other hand, it sure is more straightforward, isn't it?

What do you think?

* Presumably the same one most of us recognize as John C. Randolph, although there's no direct evidence of this on his SO profile.

by Peter Hosey at February 03, 2010 04:15 AM

February 02, 2010

waffle

Displays Meant

The most common reaction I’ve read about the iPad is this: a heavy, implicit sigh, and the words “it’s just a big iPod touch”.

Admittedly. And the car was just a lifeless, fast, metallic, thirsty horse. The computer was just a programmable calculator. The steam engine was just a more efficient engine. We can go on pithily summarizing every object we see, or, if we’re trying to gauge the potential of an item, we can actually try to gauge the potential of an item.

But my most common reaction to that doesn’t start with “admittedly”. It begins and ends with another sentence, not as pithy, but probably as accurate: What the hell is wrong with you?

The big secret to the iPhone is that it was an easy to use phone in the shape of The Thing From The Future. When Nokia mocked up their concept models every year during the 90’s and early 00’s, it came in one of two forms: something unbelievably contrived, or a big fucking display. The reason they did it is because the future has always been big fucking displays. Ever since we invented the pinhole cameras, but more intensively since we invented the modern monitor, our visions for the future have involved big fucking displays. Also, for some reason, pill food.

Now, pill food may not be a good idea, and likewise the value of big fucking displays is proportional to the sanity of its contents. But it’s becoming clear that a way as good as anything is a multi-touch interface. It’s not a secret that the iPhone can already do most of what the iPad can do. But it makes an enormous difference that a 9.7″ screen actually provides enough space for that sort of useful interface to exist.

People earlier and brighter than me have noted that a secondary, distinct lineage of GUIs have now suddenly appeared, and that a lot of cruft has been chucked in the process. (People who are me have noted that.) If you don’t recognize even the idea that such an interface could make inroads with the majority of people, the ones who either are “just” reasonably comfortable or not at all comfortable with computers as they stand, you must be trying very hard not to.

My point (and this is going to get self-referential) is this: if you’re going to make a point, make a point. Don’t just say “it’s just a big iPod touch”. I also think “it’s just a big iPod touch” and I’m clearly, probably, a bit more psyched than you. It stands to reason that you’ve iterated some facts while I’ve additionally formed an opinion. Movie critics don’t get away with simply concluding how “George Clooney is just like Tom Cruise, only older”. (He’s also better at acting and less of a dick.) Sports reporters don’t get away with noting that “Usain Bolt is just a guy, but Jamaican”. (He’s also the fastest guy in the world.)

Say “it’s just a big iPod touch; I wish it did more things that iPod touch didn’t”, and proceed to list these things. Multi-tasking may be one. Hell, “I just don’t like it” is mildly better. “I don’t see this working better for me” is probably what you’re trying to say. The iPad will continue to be “just a big iPod touch” for a long time to come. That’s how it’s built. I don’t think that’s your actual problem. Your disappointment tells me that you’d actually have liked it if it was also something else. I wonder what that something else is.

by Jesper at February 02, 2010 11:37 PM

Cocoa Samurai

The PubSub Framework: Using RSS Feeds in your App

The Project Page for this articles project is on github at http://github.com/Machx/FeedViewer you can grab the source code with git by entering the following command in terminal....git clone git://github.com/Machx/FeedViewer.gitThe PubSub Framework is one of those lesser known Frameworks that Apple introduced in Leopard. It has the ability to parse RSS & ATOM feeds and automatically generate KVO

by Colin Wheeler (noreply@blogger.com) at February 02, 2010 08:21 AM

Clickable Bliss

ProfitTrain tag line

In the spirit of the last post I want to talk about why I need to change the current ProfitTrain tag line. Currently on the product page it says “An invoice & accounting application for client-based businesses.” I wrote that tag line in a hurry when I was writing up the HTML. I remember showing a preview of the site to Daniel Jalkut and he commented how I should take it out. I never really followed up on that feedback but it’s clear to me now thats it’s not the right tag line.

ProfitTrain is not and will never be a proper accounting application and to call it such is disrespectful to the real accounting applications out there. This isn’t to say a small businesses couldn’t generate all the totals they need from ProfitTrain’s reporting system or exports but I think it’s only fair that we set expectations accordingly.

ProfitTrain is at its heart an invoice application. It provides various workflows to create them, to customize them, and to record their payment status.

I’m not sure what I’ll end up going with. If you have a suggestion let me know!

by Mike Zornek at February 02, 2010 01:52 AM

Feedback wanted for Tax Report

Today I’ve been working on adding a report to ProfitTrain that would allow users to easily tally up the taxes they have collected from clients. Sadly I’ve come up with a few edge cases that make the whole thing a mess and am debating how I should move forward.

To explain, the report system asks the user for an optional date range; if none is given we process all the the objects in the system. The first question when it comes to taxes is which objects should we consider, invoices or payment transactions?

In ProfitTrain’s other reports we calculate using the cash method of accounting, which in short means we don’t consider something income until we have gotten paid. Simply sending an invoice to a client does not affect your income.

With that understood the natural progression is to base this tax report on payment transactions. We haven’t “collected” any taxes until we actually got paid. For example, you invoice a client in December but he doesn’t pay it till January; when did you collect the taxes? In January.

This works well but falls apart when an invoice isn’t paid in full and/or involves more than one payment transaction. Let’s say you invoiced a client in November, he sends a very small payment in December which might not even cover all the taxes of the original invoice. He eventually pays the rest in January but when you did your end of year totals did you consider the taxes collected? When were they collected?

For a little while I considered the idea that if we received X percent of the total due we should match that percentage of the taxes. However this is even made more complicated since not every line item in a invoice is taxable.

Yikes. The whole thing is a bit of a mess and I’m curious how other people handle it. I myself never had to charge taxes when I was consulting and while I do collect some sales tax for web-purchased software it happens all at once and at the same time of the transaction.

My gut says I’m going to have to limit my reporting to tax totals requested on invoices send in a date range but I want to hear your thoughts. If you want to keep it private please send me an email.

by Mike Zornek at February 02, 2010 01:21 AM

February 01, 2010

waffle

Translation From PR-Speak to English of Selected Portions of Sony’s John Koller’s, Director of Hardware Marketing, Uh, Original Research

(See: Sony’s John Koller: “Apple’s entrance into gaming market drives consumers to PSP”.)

Apple’s entrance into the portable gaming space has been a net positive for Sony. When people want a deeper, richer console, they start playing on a PSP.

I am high as a kite.

by Jesper at February 01, 2010 09:59 PM

Surfin' Safari

Nate Chapin is now a WebKit reviewer!

Nate got his start in WebKit with helping to upstream Javascript bindings for the Chromium port into WebKit. During that work, he learned much about WebKit style as well as getting to know the bindings quite well. Since then, he continued to do a prodigious amount with the bindings and improved them in many ways. In addition, he also added noreferrer support and fixed bugs in a variety of areas such as the loader and plugin scripting.

Please join me in congratulating Nate on his reviewer status!

by David Levin at February 01, 2010 06:23 PM

January 31, 2010

Gus Mueller

Marc Cuban: A Simple Policy Guide for Job Growth

Marc Cuban: A Simple Policy Guide for Job Growth:

"The simplest way to create more jobs is to allow small business and entrepreneurs to spend less time and money on lawyers and accountants and redirect that intellectual and financial capital to the core competencies of their business.

...

Like the administration before it, the current administration seems to have no concept of what it takes to start, run and grow a small business. None."

I'd hire someone full time right now for Flying Meat, if the US had universal health insurance.

I've never understood why it's up to the employer to provide this benefit*. It drives me nuts. As an employer I'm not expected to pay for house, car, or flood insurance; why would I need to pay for health? Isn't it really up to the individual to know what their needs are, and not the company they work for (who is trying to be profitable)?

How many great companies are kept from being created, because someone has to stay at their current place of employment for fear of losing coverage for a sick relative, or themselves?

Uh. What a stupid, stupid mess.


*Yes, being a small business I have ways of not having to provide insurance. But I don't want to be a jerk either.

January 31, 2010 08:45 PM

Chris Sanders Original Art

Chris Sanders is selling some original artwork. It's a bit out of my price range, but I absolutely love his drawings and can't help but let everyone know. Make sure to check out his gallery while you're at his site.

January 31, 2010 08:25 PM

waffle

January 30, 2010

Cocoa Is My Girlfriend

Getting “Real Work” Done

I had to post a link to this one as well as Fraser does such a great job explaining why the iPad is so compelling . From Fraser’s post:

The tech industry will be in paroxysms of future shock for some time to come. Many will cling to their January-26th notions of what it takes to get “real work” done; cling to the idea that the computer-based part of it is the “real work.”

It’s not. The Real Work is not formatting the margins, installing the printer driver, uploading the document, finishing the PowerPoint slides, running the software update or reinstalling the OS.

The Real Work is teaching the child, healing the patient, selling the house, logging the road defects, fixing the car at the roadside, capturing the table’s order, designing the house and organizing the party.

Exactly! The iPad is genius and it will revolutionize not just books, magazines, etc., but it will revolutionize computing as we know it. I don’t know about you, but I’ve got the new SDK fired up and ready to start rocking some apps and it is a very exciting new platform!

by Matt Long at January 30, 2010 09:02 PM