Friday, 27 November 2009

I should be available again soon

For anyone that has been trying to contact me recently, I'm sorry I have not been available. A colicky baby girl, other family issues, and a dead MacBook pro have meant I have been unable to work or even keep up-to-date with new emails.

My MacBook pro repair should be complete any day now, and I'll be able to catch up with everything soon.

Mike

Monday, 31 August 2009

Crazy and cool javascript one-liner

Paste this into your non-IE browser address bar and hit enter:

javascript:document.designMode="on";void(0);

An editable webpage!

Tuesday, 11 August 2009

UITextField fuzzy/blurred text

I just solved a very obscure bug where the text in a UITextField can be rendered with a slight blur/anti-aliasing effect. The text will appear crisp when it becomes the first responder, then return to being blurred when it loses focus:

Example of blurred text

I found a number of references to this bug through Google, but everybody worked around it by playing with font sizes. After much hunting I found this thread that says anti-aliasing is applied when a view's frame contains fractional pixel values, e.g. if you calculate its size or position as a fraction of the super view.

Sure enough, casting the CGRect values to (int) for the view's frame worked perfectly. So as an example, if you wanted your text field to be centered vertically in the superview, you should use an (int) cast like this:

textFieldWidth = 300;
textFieldHeight = 31;
offsetX = 0;
offsetY = (superview.bounds.size.height - textFieldHeight) / 2;

textField.frame = CGRectMake((int) offsetX,
                             (int) offsetY,
                             (int) textFieldWidth,
                             (int) textFieldHeight);

Unfortunately, if you are trying to use UITextFields inside table view cells, you have no control over the parent cell's frame, so you might find this fix doesn't work for you if the parent view has fractional values in its frame.

Also see the post on stackoverflow.com.

Friday, 31 July 2009

Retain and Release rules in Objective-C

I've seen lots of people asking questions about how to manage memory properly in Objective-C so I thought I'd list out some of the rules I follow when developing for the iPhone.

Objective-C is interesting because it introduces a few additional gotchas when compared to traditional C. In C, you write free() when you write malloc() and that's pretty much it. In Objective-C it's easy to forget things. So here are the rules I try to follow:

  • When adding a new member variable to a class, add a call to release in your dealloc method as your immediate next action.

  • When assigning to a member variable outside of init* or loadView etc. release it first. If you are assigning in a setter method, check the new value for equality first.

  • When releaseing a member variable outside of dealloc, immediately assign a new value, or nil.

  • When you type alloc for a local variable, immediately add the appropriate release or autorelease code. Prefer autorelease.

  • Move your dealloc method to immediately below your @synthesize lines. This reminds you to check your release calls and you can easily see any missing ones.

  • If you implement your own NSAutoReleasePool block, wrap it in a @try...@finally:

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    @try {
            // do stuff here
    
    } @finally {
            [pool release];
    }
    
  • If you implement a delegate property, don't retain the delegate. See this excellent post on how to avoid retain cycles (circular references): Rules to avoid retain cycles.

Saturday, 4 July 2009

Problem with using Audio Service system sounds for playing sounds.

A lot of people are recommending using AudioServicesCreateSystemSoundID for playing short sounds on the iPhone. I think even the official SDK documentation recommends this for sounds that are just a few seconds long.

There are a couple of problems with this that you might want to consider:

  1. You cannot control the volume of the sound. As far as I can tell there is no function in the API to let you do this.
  2. When you have your phone set to vibrate, the sounds will not play, even when headphones are plugged in. This is in contrast to using AVAudioPlayer and the like which will play sounds through the headphones in vibrate mode.

So I guess using the AudioServicesCreateSystemSoundID approach only really applies for 'alert' sounds or sounds that are not crucial to your app.

Friday, 3 July 2009

Thunderfly in my LCD

It was an interesting moment when I went to squash the Thunderfly on my LCD, only to find that the little critter was BEHIND the display. Now the curse-ed thing has gone and died right in the middle of it and won't budge.

A google search shows I'm not alone with this problem, but there isn't much I can do. I don't want to take the display apart because I don't even know if I can access the corpse, and tapping the screen isn't helping.

Even worse, now there's one inside my laptop's display too. Apparently they are attracted by the light so I've turned on a lamp on my desk to try and keep them away.

Wednesday, 24 June 2009

Improve iPhone flip transition performance

If you've tried animating a UIView onto the screen using UIViewAnimationTransitionFlipFromLeft or UIViewAnimationTransitionFlipFromRight you may have noticed a slight lag in the first animation. The obvious way to implement a flip transition is with code like the following:

- (void)showFlipView {
    UIView *parentView = self.view;

    self.flipViewController.view.frame = parentView.bounds;

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft
                           forView:parentView
                             cache:YES];

    [UIView setAnimationDuration:1];
    [parentView addSubview:self.flipViewController.view];
    [UIView commitAnimations];
}

One explanation for the lag you sometimes see is that views are lazy loaded, and the delay is caused by the flip view being loaded. But even if you force the view to be loaded by accessing the controller's view property this lag can still manifest.

One way I found to stop this lag is to add the flip view to the parent view when the parent view loads, and set its hidden value to YES. Then when you want to animate it in, you set hidden to NO:


- (void)viewDidLoad {
    [super viewDidLoad];

    // ...

    self.flipViewController.view.hidden = YES;
    [self.view addSubview:self.flipViewController.view];
}

- (void)showFlipView {
    UIView *parentView = self.view;

    self.flipViewController.view.frame = parentView.bounds;

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft
                           forView:parentView
                             cache:YES];

    [UIView setAnimationDuration:1];
    self.flipViewController.view.hidden = NO;
    [UIView commitAnimations];
}

Thursday, 11 June 2009

XCode trailing whitespace

For all the other trailing-whitespace-haters out there, if you would like to remove trailing whitespace from all the files in your XCode project, do a global search replace (Shift+⌘+F) for the following regular expression:

[ \t]+$

In older versions of XCode you have to select all the results before hitting "Replace".

UIWebView doesn't open target="_blank" links.

If you are using UIImageView to display external webpages, you may come across an issue where certain links don't fire UIWebViewNavigationTypeLinkClicked events. This happens when the link has the target="_blank" attribute.

To work around this problem you can inject some javascript after the page load to remove this attribute from all the links:

- (void)webViewDidFinishLoad:(UIWebView *)webView {
        NSString *js = @"\
        var d = document.getElementsByTagName('a');\
        for (var i = 0; i < d.length; i++) {\
            if (d[i].getAttribute('target') == '_blank') {\
                d[i].removeAttribute('target');\
            }\
        }\
        ";

        [webView stringByEvaluatingJavaScriptFromString:js];
}

Tuesday, 26 May 2009

Some things will never change...

¶¶¶¶¶¶¶¶¶¶5. Results

It's 2009 and people still can't do page breaks in Word. Of course, this isn't their fault, it's a usability issue: how do you tell the user that they should insert a page break instead of just hitting return 20 times? It's a tough problem.

Thursday, 30 April 2009

Moving to Germany

Well, it looks like I'm going to be a father, so I'll be moving to Germany next week to be with my girlfriend. This is for the long term, and I shall be working from home doing freelance software development. I hope I can make this work.

Tuesday, 10 February 2009

C ain't so bad

I've been catching up with the Stackoverflow podcast recently, and the usual conversation about C and whether a developer should learn it came up a few times.

Instead of telling you why you should or should not learn C, I'm going to talk about the observations I've made while programming in it. It really isn't as bad as people make out.

I've entered an interesting stage in my evolution as a programmer... after 6 months of Java at my previous employer, and seeing how far OOP can be taken, I decided to get back to my roots and work on some C projects in my spare time.

Abstract types and OOP

One of the first things you need to understand when coding C is the importance of the typedef keyword. When I first learnt C I must have been around 14, and at that time typedef was just a useful way of creating aliases in code. Instead of writing struct foo all over the place, I could just write Foo. Neat.

But now, with everything I've learnt about abstraction and types over the years, I realize the power this keyword has. With typedef I can create abstract types, and as long as everybody follows the rules, these abstractions are just as solid as in any other language:

typedef struct {
        llist_t** buckets;
        size_t capacity;
        size_t size;

        /* ... */

} hashmap_t;

I've just created an abstract hashmap type. And whatever is inside that struct must not be touched by anybody, except for the functions that operate on that type.

Sure, somebody could access these members, but that's breaking the rules, and there are rules in every language. In C you don't touch the members of a typedef. Got it?

So now I have this type, and I can operate on it with the functions provided:

hashmap_t* hashmap;

hashmap = hashmap_create(&hash_fp, &key_compare_fp);
hashmap_put(hashmap, L"key", L"value");

/* ... */

hashmap_destroy(hashmap);

This is perfectly abstract, and the implementation details are just as hidden as in any other language. I can see the members of the typedef, but I can see the members of a C++ or Java class too. So what are we missing as far as OOP goes?

OOP is not abstraction or information hiding. It's not even associating types with the methods that operate on them... there's not much difference between writing this:

byte[] a = myStream.read(512);

...and writing this:

byte_vector_t* a = stream_read(my_stream, 512);

stream_read() can only be used on a stream_t. So why do we need to bundle them together? It basically amounts to a syntactic difference. And with the C way of doing things, we get mixins for free.

So take away all these things, and we are left with the essence of what OOP is: inheritance and polymorphism. OK, so we've learnt nothing, except that C has all the power for creating abstract types that other languages have.

Oh, and no, I do not think implementing polymorphism in C is a good idea!

Productivity

This is one topic where I have to agree with the anti-C folks. In C, you have to build your entire world before you can get anything done. Take my current pet project as an example. In the past few days I've created the following types:

llist_t          /* linked-list, naturally */
hashmap_t
string_t         /* Every C programmer will end up writing a string type */
stringbuilder_t
stream_t         /* Simple stream type allowing multiple
                    backend implementations. */

bytestream       /* implements stream_t */
filestream       /* implements stream_t */
tcpsocket_t
tcpsocket_stream /* implements stream_t */
udpsocket_t
thread_t

I've also written functions for logging, utf8 encoding/decoding, and a whole host of other basic requirements... and I'm still not done. This is quite a lot of work, especially if you want to build robust and well-tested code.

I could use libraries for this functionality, but the fact remains that you don't get this as standard. I also think C programmers don't trust other programmers' code, even their own code from a few years ago. This means rewriting your own personal C library every 3 years.

Resource management

Every C programmer will create memory leaks. Every C programmer will corrupt the heap or stack. Every C programmer will forget to call close() on something they open()'d. This means hours of frustrated debugging and lost time.

Even if they don't screw up, there is significant overhead in writing open/close create/destroy type code in the first place. Not to mention it's ugly as hell.

I would kill puppies to get better resource management in C. I'm not talking about garbage collection here, but at least some sort of stack-based destructor support so we can do RAII.

Polish

It will take you 3x as long to do anything in C as it will in a higher level language with good libraries. This means you don't have as much time to add polish to your program because you are still trying to get the damned thing to work correctly.

You can get a polished product in C, but it will take you longer. And your competitor who has written the same application in C# for the .NET platform will have V2.0 out before you've even finished your new localization library.

It makes me wonder... maybe this is why so much open source software sucks. A lot of it is written in C, and it's just harder to get a decent product at the end. With Java and NetBeans I can drag and drop buttons onto a form, and spend 20 minutes making the interface look perfect. In C I have to hand-code the pixel values and recompile before I can see how it looks. It's not hard to see which version will be better.

A few plus points

Everybody who has written C will remember with pain the hours spent hunting down a memory corruption bug. You know you've screwed up when you see 'impossible' behaviour and random crashes which mysteriously disappear when you add some trace statements.

But searching for these mistakes develops your skills of debugging. You are forced to think things through logically, and narrow down the possible locations for the bug. You become a master of printf debugging which is still an essential skill, even in today's world of interactive debuggers.

I spoke about how you have to build your own world in C. But this is also a good thing. You learn so much from implementing things yourself, whether it's just a hash table, or some HTTP handling code for your file download library. You end up with a broad knowledge of different protocols and algorithms, which puts you on a totally different level to the kind of programmers that stick with their Java or .NET libraries.

Jeff Atwood has written about this very same topic in Don't Reinvent The Wheel, Unless You Plan on Learning More About Wheels. Just because it's been done before, or there is a library for it, does not mean it's wrong to implement it yourself. The learning experience alone justifies the effort.

Another thing I like about C is that it is possible to write cross-platform code. The standard library doesn't give you much, but it's easy to write your own cross-platform types for threads, sockets, file system interaction, etc. So you get cross-platform code, with the leanness and speed of C.

The next stage for me

So that's what I think about C, but the question of productivity is still strong in my mind. I think the next stage for me is to say goodbye to the build-your-own-world philosophy and really immerse myself in the maximum-productivity space for a while.

It's strange though, I feel a slight apprehension when I picture myself seated in the world of high-level .NET or Java programming. There are people that naturally stay at the low levels, writing operating systems and low level APIs, or compilers and runtimes for new languages. Maybe that's where I belong.

Meh, I'll just get back to building my world. It's fun.

Saturday, 31 January 2009

You have subscribed to "."

You have subscribed to "."

Come on Google, you can do better than this, surely?

Source code managers (and why Visual SourceSafe isn't one)

I'm sure every programmer's blog has an entry on source code control, but this one has been lying in wait for some time now, so it's about time I got it out into the world.

This started as a pitch to my manager, and I may be preaching to the choir a bit, but hopefully this post will sum up the main reasons for SourceSafe failing as an SCM.

The bit with the big statements

Source code control is one of the most important aspects of the software development process. It is the very interface through which we develop and change our code.

A source control system's central role is to allow and accommodate changes to a software project. It needs to encourage programmers to make changes, both large and small, without hindering them in any way.

If a project's source control system is substandard, the project is substandard. The code will not be changed in the ways that it needs to be changed, and the programmers will not be working to their full potential.

Visual SourceSafe is not a professional source code control system. If you want to be serious about developing software, you should not be using SourceSafe.

When I say "Visual SourceSafe" I am specifically talking about this atrocity:

About box: Microsoft Visual SourceSafe Explorer - 32-bit. Copyright (c) 1992 - 1996

That's right folks, this '95 era software is still being used to develop software. Trust me, I lived through it and have survived to tell the tale.

Source control has evolved a great deal in the last thirteen frickin' years, and I believe that SourceSafe's problems fundamentally undermine the software development process. SourceSafe is the bane of any programmer's existence.

The reason people still use it comes down to ignorance. Ignorance of how much better things can be. SourceSafe is not a tool used by professionals, it is a tool used by people that don't know any better.

Jeff Atwood of codinghorror.com writes:

The more customers I visit, and the more developers I talk to, the more I believe that SourceSafe poisons the minds of software developers.

Poison is exactly what it is, and I'm going to explain why.

The fundamentals

From a developer's perspective, source code control is about one thing: editing files. It's as simple as that. An SCM (Source code manager) can provide revision histories, diffing, merging and branching, but the primary goal is to let you edit your files.

In any SCM, changing files under source control should be no harder than changing ordinary files (i.e. files not under source control).

If I'm browsing through a file and I notice a spelling error in a variable's name, I should be able to make the correction right there and then, save the file, and be done with it. Just like I would if the file weren't under source control.

If there is anything else I have to do, I am being hindered by the source control system. And if I am being hindered from making changes, I am less likely to make them. Suddenly, making changes has become a chore. That spelling error has changed from an oh, I'll just fix that now issue to a forget it, it's not that important anyway issue. This is a serious problem, and it only gets worse when the 'quick fix' becomes a multi-file refactoring to improve the design of some component.

Of course an SCM will usually have an additional commit step after editing a file, but what's important is the moment of editing itself. If there is anything getting between you and making that edit, then the source control system has failed.

This same rule applies to renaming or moving files and directories. To rename a file that is outside source control, I might type mv old_file new_file in a terminal, or right-click Rename from Explorer. Renaming a file under source control should be just as easy (although the steps might be slightly different, e.g. svn mv instead of mv).

The ability to trivially rename and move files is essential when it comes to coding. If I can't easily rename a class or reorganize files into a sane directory structure, then I'm just not going to bother. The code base will suffer as a result.

SourceSafe makes it hard to edit files in many ways, the most important of which are:

  1. Read-only files.
  2. Explicit and exclusive checkouts.
  3. Poor renaming and moving support for files and directories.

Read-only files

Buffer is read-only: main.c

When I Get latest version... on a project in Source Safe, all the files are made read-only by default. This is an instant barrier. In order to make that spelling correction, I have to switch to SourceSafe, check the file out (and if someone else has checked it out, forget it), reload the file so my editor realizes it's no longer read-only, and then finally I can make this damned change.

With something like Subversion or Git, I just make the change. Right there and then, I edit the file and save it. Job done.

The point here is that a good source control system should allow checking a project out as a fully writable local copy. A developer should not have to explicitly check files out to edit them, because then editing files is harder than it is without source control. Source control should be transparent when it comes to editing the files themselves.

Explicit and exclusive checkouts

SourceSafe is designed to be used with exclusive checkouts. This means if somebody else has a file checked out, you cannot edit it. Although SourceSafe supports concurrent checkouts, nobody uses them. It just isn't designed to be used in this way.

The problems with exclusive checkouts are obvious. If I need to make a change to a file that somebody else has checked out, I have to wait for them to finish their work. This wait can often take days.

Even worse, if I'm working on a feature that requires this change, I am forced to make local edits to continue my work, and then manually merge these changes later on when the file is available.

To make local edits you have to override the read-only attribute to modify the file. When the file becomes available for checkout, you must make a copy of your edits, check the file out (overwriting your current version), and manually merge these changes back in because SourceSafe cannot do this. This is Elm Street material, people.

The only conceivable argument against concurrent editing (which I have heard being used) is merge conflicts. This argument is 100% B.S. (Bull Shit). Merge conflicts are a total non-issue. Even when you do encounter a merge conflict with another developer, it's a simple matter of choosing which change you want to keep. Sure there can be more difficult conflicts to resolve, but this is a rare occurance and can always be worked through.

Is Linux is developed with exclusive check outs? Or Windows? No, they aren't. Because merge conflicts are a non-issue, even with hundreds/thousands of developers. The benefits of concurrent editing far out-weigh any issues caused by merge conflicts.

Poor renaming and moving support

Renaming and moving files is another area where SourceSafe fails miserably. You cannot move or rename files as part of a commit. Instead you have to directly rename/move the file within the database file system (or whatever the hell it uses as a back-end).

This means at the point after performing the rename, all your code is broken because the source files haven't been updated to reflect the change. Cue frantic editing and checking in to fix the code before anyone does a Get latest version...

But wait, what's this? When I've finished doing the rename, if another developer updates their local copy of the source, the old files will still be left where they are, hiding errors with the rename! The word 'clusterfuck' comes to mind...

Another bug with renaming: if your rename only changes the case of the filename, when another developer updates their local copy, this rename will be ignored. Headaches ensue, and you're left with totally inconsistent filenames as a result. People just don't want to deal with SourceSafe's problems.

I'm weeping just thinking about it. My God, how did they get it so wrong?

Source safe causes nothing but pain and hindrance when performing even the most basic of tasks.

And another thing:

Checkbox: Destroy permanently

Destroy permanently!? What the hell is this doing in a source code manager? Epic fail.

Freedom and experimentation

If a developer wants to do a large experimental refactoring of some core module, how can he go about this? He can't check out files because he instantly blocks anybody else from working on them. He can't make local edits because it's impossible to manage. Creating a branch in SourceSafe is a major operation, and he probably has to go to his boss to get it done. He's not going to bother.

Experimentation and freedom are very important for developers. They should be able to refactor, or prototype, or just play around without checking out files.

In my own experience, when checking out files to experiment, I always felt like Big Brother (my boss) was watching me because everyone could see which files I was working on. I should be able to create a private branch where I can work on anything I like, away from prying eyes.

A good SCM needs to encourage experimentation, and give developers the freedom and privacy to work on features without blocking others. SourceSafe fails in this regard.

Corruption

Most discussions about SourceSafe will bring up the issue of database corruption. This article describes the topic in more detail, but I can assure you this happens. The SourceSafe database for the project I was working on was corrupt. If I tried to get a history that went back over 2 years, SourceSafe bugged out and left this message:

Version not found.

Files and histories were gone. This is scary stuff.

To summarize

The core point I'm trying to get across is that an SCM needs to make it easy to change code. If developers have to jump through hoops to do basic tasks, they aren't going to get done.

As soon as code is added to Sourcesafe, there is an immediate staticness to it. It's hard to rename or move things around. Exclusive checkouts make it difficult to make large changes to the code, or to experiment/prototype.

When I started a new project at my previous job, I put off adding the code to SourceSafe for as long as possible because it would make it harder to edit the code! This is a fundamental issue. With other SCMs, you just edit your code. Simple. No manual checkouts, no read-only files. It's easy to rename and move things. Concurrent edits are merged trivially.

The fact that SourceSafe makes things harder is ridiculous. Developers need to be using tools that help, not hinder. SourceSafe hinders in many ways.

These issues I've discussed were reflected in the code I worked with. The code base consisted of messy file names with inconsistent casing, huge monolithic files that needed to be split up but weren't, and developers like me that where totally discouraged from doing any kind of refactoring or redesign.

And this my dear readers, is why Visual SourceSafe is poison.

Links

Wednesday, 28 January 2009

Thistles... everywhere

So I just got my Macbook Pro FedEx'd to New Zealand, where I am currently a Willing Worker On Organic Farms (WWOOF). This means I've been milking cows, weighing lambs, weeding organic carrots, grubbing out lots (and lots) of thistles, and generally helping out on organic farms in exchange for good food and a bed to sleep in.

I'm 10 months in, and this has been a really great experience for me. Over the past few years I spent all my time on the computer, and I kind of lost touch with reality. I lost the balance between computer time and outside-world time.

I was stuck in a hole, so I quit my job and headed to the other side of the world.

Doing some good honest work outside has done wonders for my spirit. I've met a beautiful girl who I will spend the rest of my life with, and some day we will own some land of our own to continue the lifestyle we've experienced here in New Zealand.

Being away from the computer for so long has left part of my mind a bit... hungry. I started getting some serious programming pangs a couple of months back, and I was forced to write a wallpaper changer in html/javascript that ran on a Windows 98 machine as an ActiveDesktop object. I felt dirty, but it satisfied some primal instinct inside me. I realized I have a fundamental need to code.

Around the same time I started thinking about my previous employer, and the problems I saw there with respect to the software development process. My brain went into overdrive and I couldn't stop thinking about source control, bug tracking, user testing, and everything in between.

So I started writing again, and managed to fill over 20 pages of A4 with notes and thoughts about software development. In the long term I want to improve my writing and maybe even come up with some interesting and thought-provoking ideas. I plan on using this blog to accomplish this.

A picture of me