subscribe via RSS

  • The fast road to unit tests with Xcode

    Supposedly Xcode has unit test support. I've never seen that work for more than two Xcode revisions. So I've come up with a minimal unit test scheme that works reliably.

    1) Add a "command line tool" target (Foundation application, C++ application, whatever makes sense). Put your test code in its main.m or whatever. After each test, print out a line starting with "error: " if the test failed. If you want to be able to see the successes as well, start them with "note: ". Keep a counter of failed tests (e.g. in a global). Use the number as the app's return value of your main().

    2) Add a "Run Shell Script" build phase to this target, at the very end. Set it to run ${TARGET_BUILD_DIR}/${PRODUCT_NAME}. Yes, that's right, we make it build the unit test app, then immediately run it. Xcode will see the "error: " and "note: " lines and format them correctly, including making the build fail.

    3) Optionally, if you want these tests to run with every build, make that command line tool target a dependency of your main app, so it runs before every build. Otherwise, just make sure your build tester regularly builds this test target.

    4) Add a preprocessor switch to the tests that lets you change all "error:" lines into "warning:" instead. Otherwise, when a test fails, you won't be able to run it in the debugger to see what's actually going wrong.

  • How to write a compiler

    A bytecode interpreter feeding instructions through it.Since there isn't that much beginner info out there about this topic, here's a very rough run down of what I know about the basics of writing your own compiler, in particular about how the CPU works and how to generate code for it.

    CPU/bytecode interpreter

    A bytecode interpreter works just like a CPU, the difference being that it is in software, while the CPU is actual hardware. So all a fake or real CPU does is take a list of instructions and fetch them one by one.

    To properly do that, there is one variable (in a real CPU, this is a register) that contains the position of the current instruction. This is called the program counter or PC for short, and is basically just the memory address of whatever command it is to execute.

    Once an instruction finishes, the CPU adds to the PC to make the pointer point at the next instruction (or in the case of a conditional or loop, it rewinds the PC back to the start of the loop, or jumps over the 'else' section, or whatever.

    So it's fairly easy to create a bytecode interpreter. It's just a loop:

  • Cocoa: String comparisons and the optimizer

    Woman in front of a mirrorA while ago, a friend came to me with this bit of code:

    NSString *a = @"X";
  • The universal catch-all singleton

    Personified application delegate creating objects by cracking eggsOne bad habit I see time and time again is filling up your application delegate with junk that has no business being in there.

    Avoid putting stuff in your app delegate.

    What is the application delegate?

    By definition, the application delegate is a controller. Most model classes are standard Apple classes. Those that aren't are slightly smarter collections of these classes. Most view classes just display the model and forward a few IBActions to the controller in a dynamic way, so are inherently reusable as well (even if not always the particular arrangement of their instances).

    The controllers, on the other hand, aren't really reusable. They glue all this stuff together. They're what makes your application your application, along maybe with a few bindings. So, again by definition, the application delegate is the least reusable part of an application. It's the part that kicks everything off, creates all the other controllers and has them load the model and views.

    Reusability is best!

    The whole point behind OOP was to reduce bugs, speed up development, and help structure your code by keeping it grouped in reusable components. The best way to maintain this separation of components and permit re-using parts of it in different projects, is to keep the boundaries between components (e.g. objects) clean and distinct.

    Objects have a clear hierarchy. The top creates objects lower down and gives it the information they need to operate correctly for your application. Nobody reaches up the hierarchy, except maybe to notify whoever created it of occurrences in the form of delegate messages. That way, the more application-specific your code gets, the fewer other objects know about it. The further down you get, the more reusable.

    Moving operations or instance variables that are shared by several objects in your application into the application delegate, and having other objects reach straight up through NSApplication.sharedApplication.delegate to get at it, goes head-on against this desire, and turns your carefully separated code into an inseparable glob of molten sludge. Suddenly *everybody* includes the most application-specific header your application contains.

    Don't lie to yourself

    The application delegate is one of the singletons every application contains. Its name is misleading and fuzzy. If you see it as a place to hold code "relevant to the application as a whole", there is pretty much nothing that is off-topic for it. It is the universal, catch-all singleton.

    So why not be honest to yourself: Whenever you add code to the application delegate, and you're not just doing it to react to a delegate method from NSApplication and create a controller to perform the actual action in response, what you are really doing is create a singleton.

    As we all know, singletons have a use, but having many singletons is a code smell. So avoid them if you can, but if you feel you can't, be honest to yourself and actually make it a separate singleton (or find one whose purpose these operations fit).

    Just say no to the application delegate as the universal singleton.

    Update: If this hasn't convinced you, here's another blogger with a more CoreData-centric discussion of the issue, coming to the same conclusion: Don't abuse the app delegate.

  • What a block really is

    BlocksLegoBrickAfter quite a while of thinking that Objective-C blocks did some mean magic on the stack, it simply took me seriously using C++'s lambdas (their implementation of the concept) that I realized what blocks are.

    Effectively, a block is simply a declaration of a class, plus an instantiation of one instance of that class, hidden under syntactic sugar. Don't believe me? Well, let's have a look at C++ lambdas to clear things up: