On Null Objects

I’ve said before, NSNull is an anti-pattern. It’s nice that we have the nil object, which allows us to have a stand-in for any object that doesn’t do anything. Unfortunately, it’s not a universal stand-in. You can’t add nil to a collection. You can add +[NSNull null] to a collection, but you can’t use that as a placeholder for other objects.

In either of these cases, you end up needing to warty your code. Either when you are building the collection, you must test for and handle trying to add nil. Or when you are reading the collection, you must test for and handle trying to use NSNull.

What would be nice is if we could easily define empty implementations of protocols. These would combine the two null implementations described above, along with more awesomeness:

  • Like nil, they provide default implementations of any method in the protocol.
  • Like NSNull, they can be used in collection classes.
  • Unlike both, they conform to the protocol for which you created them.

Then you can use these instances with aplomb, without your client code needing to work around their existence.

You’d use them like this:

        id <NSCacheDelegate> emptyCacheDelegate = [NullProtocol nullFor: @protocol(NSCacheDelegate)];
        NSArray *delegates = @[emptyCacheDelegate];

The nullFor: method would look to see whether you’ve previously created a Null Object for the specified protocol. Because they all do the same thing, it could use Flyweight instances.

+ (id)nullFor: (Protocol *)protocol
{
    NSString *className = [NSString stringWithFormat: @"Null%s", protocol_getName(protocol)];
    Class NullClass = NSClassFromString(className);
    NullProtocol *nullObject = objc_getAssociatedObject(NullClass, "instance");

If you don’t have one, then the method would create a new class pair, add this protocol to the class and instantiate it.

    if (nullObject == nil)
    {
        NullClass = objc_allocateClassPair(self, [className UTF8String], 0);
        class_addProtocol(NullClass, protocol);
        objc_registerClassPair(NullClass);
        nullObject = [NullClass new];
        nullObject->_protocol = protocol;
        objc_setAssociatedObject(NullClass, "instance", nullObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return nullObject;
}

The object could then use the standard message-forwarding technique to let nil handle all the messages from the protocol.

BOOL isNullMethodDescription(struct objc_method_description description)
{
    return (description.name == NULL && description.types == NULL);
}

- (struct objc_method_description)methodDescriptionForSelector: (SEL)aSelector inProtocol: (Protocol *)protocol
{
    //required methods
    struct objc_method_description description = protocol_getMethodDescription(protocol, aSelector, YES, YES);
    if (isNullMethodDescription(description))
    {
        //optional methods
        description = protocol_getMethodDescription(protocol, aSelector, NO, YES);
    }
    //look in the super-protocols
    if (isNullMethodDescription(description))
    {
        unsigned int protocolCount = 0;
        Protocol * __unsafe_unretained *protocols = protocol_copyProtocolList(protocol, &protocolCount);
        if (protocols == NULL)
        {
            return description;
        }
        unsigned int protocolCursor = 0;
        for (protocolCursor = 0; protocolCursor < protocolCount; protocolCursor++)
        {
            Protocol *thisProtocol = protocols[protocolCursor];
            description = [self methodDescriptionForSelector: aSelector inProtocol: thisProtocol];
            if (!isNullMethodDescription(description)) break;
        }
        free(protocols);
    }
    return description;
}

- (struct objc_method_description)methodDescriptionForSelector: (SEL)aSelector
{
    return [self methodDescriptionForSelector: aSelector inProtocol: _protocol];
}

- (BOOL)respondsToSelector:(SEL)aSelector
{
    struct objc_method_description description = [self methodDescriptionForSelector: aSelector];
    return !(isNullMethodDescription(description));
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    NSMethodSignature *superResult = [super methodSignatureForSelector: aSelector];
    if (superResult) return superResult;
    struct objc_method_description description = [self methodDescriptionForSelector: aSelector];
    return [NSMethodSignature signatureWithObjCTypes: description.types];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    [anInvocation invokeWithTarget: nil];
}

Oh wait, that all exists.

Posted in code-level, OOP, software-engineering | 3 Comments

Illuminative-C

In addition to being a mildly accomplished software engineer, I’ve done some studying and armchair research in the field of ancient languages and palaeography. What happens if we smoosh those fields together?

In a very slight way, art historian and fellow Oxenafordisc Dr. Janina Ramirez did that in her series on Illuminations: the Private Lives of Medieval Kings (erm, Kings and Ælfgifu). In the series she showed off many manuscripts in the British Library collection, but when she went out in the field she took an iPad. It turns out that the BL isn’t too hot on letting you run around with their thousand-year-old kidskin.

You already know my opinion on our digital heritage. This puts it into stark relief: in one hundred years’ time, barring some epic fire in London (those never happen), the BL and its collection will still be there. Will it still be possible to even launch the iPad app she was using? I very much doubt it.

How about if we put the same effort into storing our source code as the scriptoria did into storing their indentures and gospels? Well, I sharpened a goose feather and had a go at just that (warning: very much draft document impending).

Example 2-1 from PCAS

What you see up there is the first sample code in Professional Cocoa Application Security – Listing 2-1. Ignore the fact that you don’t recognise all the letter shapes: things have changed over the centuries. There were a few contortions required to get the source code to work in manuscript form: let me show you them.

First is that in the hand in which I wrote the source, some of the characters needed for Objective-C source code don’t exist. Like ‘v’. I used the fact that u and v are actually the same letter to get around that. Punctuation was harder: I went for roughly accurate rendering, with a single misplaced comma to suggest that the scribe didn’t really understand punctuation.

When it came to comments, I decided they have the same meaning as the gloss in the Lindisfarne Gospels – rendering the difficult language required by the church^Wcompiler into plain English. I therefore roughly scratched them in smaller text with different ink, letting them flow around the code as if they’d been written later. I also put in a few Old English spellings – though again not consistently[*].

The return value posed some difficulty, because we didn’t borrow 0 from the Middle East until a few centuries after the time this script is mimicking. I realised that if a scribe were to illuminate any part of a C function, it’d probably be the return value because that’s the consistent and – from the perspective of the rest of the code – important part. Thus the 0 is highly decorated, with six legs in the fashion of a bug :-).

Bugs hark back to the days of illuminated manuscripts anyway. Any good scribe would know that a mistake in the text was the fault of Titivillus, not of the scribe. Just as those bugs aren’t my fault. Honest.

[*] Next time you want to get angry at a teenager, remember that the work “ask” was once “acsian” with the s on the end, and think about which one of you is bastardising our language.

Posted in advancement of the self, books, code-level, documentation, PCAS, software-engineering, UI | Comments Off on Illuminative-C

On community

This is a post that had been boiling for a while; I talked a little about the topic when I was in Appsterdam earlier this year, and had a few more thoughts which were completely supplanted and rearranged by watching iOSDevUK. I threw away my earlier draft; you’re about to read something different. Where you see “we”, “us” or “our community” you should probably take it to mean Cocoa programmers, though read on to find out why “us” doesn’t always make sense.

Acknowledgements

So many people have contributed to this, by saying things that I agree with, by saying things that I disagree with, by organising conferences, or in other ways. I’ve tried to cite where appropriate but I’ve probably missed someone somewhere. Sorry :-(.

Introduction

This article is more the presentation of a problem and some thoughts about it than an attempt to argue in favour of a particular solution. I’ll investigate what it means to be in “the Cocoa programming community”, beginning with whether or not Apple is in a community of its own devising. I’ll ask whether there’s room for more collaboration in the community, and whether the community of Cocoa programmers encompasses all Cocoa programmers. Finally, I’ll notice that these are questions as yet unanswered, and explore what the solutions and non-solutions might be.

On Apple and the community

This is the bit that I’d done most work on already, as it was the topic of my Appsterdam talk. The summary of that talk is pretty much the same as Dave’s working-with-Apple pro tip in his iOSDevUK talk. As his was more succinct, I’ll use that version:

Apple is people too. Don’t be a dick.

(I’m a fan of people not being dicks.)

The thing is that as Scotty said, the community wins when all of its members win. But he also said that Apple isn’t in the community, so don’t they obviate themselves from this relationship?

Well, no. If we look at the community that most of the people reading this post – and that most of the people at iOSDevUK – consider themselves a member of, it’s the community of iOS app makers. It happens that all of these people depend on the same thing: on iOS. Being nice to Apple and helping them just makes good business sense. If you’re not helping Apple to win, they might decide to help you lose.

On a related subject: for Apple to win, it’s not necessary for anyone else to lose. In fact, I’m not the first person to say this. I’m stealing from a man who was, at the time this quote was coined, freshly CEO after having been a management consultant at Apple:

We have to let go of this notion that for Apple to win, Microsoft has to lose. We have to embrace a notion that for Apple to win, Apple has to do a really good job. And if others are going to help us that’s great, because we need all the help we can get, and if we screw up and we don’t do a good job, it’s not somebody else’s fault, it’s our fault.

So Microsoft, Windows 8 and Windows Phone 8 don’t have to lose. Google and Android don’t have to lose. Enterprise Java programmers don’t have to lose. Your competitors don’t have to lose. The team in Apple that make that thing that just crashed don’t have to lose.

On that last note, Apple is the biggest company in the world and you’re supplying one or a handful of 600,000 or so different replaceable components that helps them make a trivial fraction of their income. So if the choice you give them is “do what I need or I’ll stop working with you”, they’ll pick option 2. “Fix Radar or GTFO”? It’s cheaper and easier for Apple to GTFO.

That’s not to say the best strategy is always to do whatever Apple want. Well, actually it probably is in the short term, but Apple is real people and real people benefit from constructive feedback too.

Just who is “them”, anyway?

Around the time that I started to be a proper software writing person, there was a strong division in Mac development. The side I was in (and I was young, opinionated, easily led, and was definitely in this faction) was the Yellow Box. We knew that the correct way to write software for the Mac was to use the Foundation and AppKit APIs via the Objective-C or Java languages.

We also knew that the other people, the Blue Boxers who were using libraries compatible with Mac OS 8 and the C or C++ languages, were grey-bearded dinosaurs who didn’t get it.

This sounds crazy now, right? Should I also point out that I wrote a Carbon app, just to make it sound a little crazier?

That’s because it is crazy. Somehow those of us who had chosen a different programming language knew that we were better at writing software; much better than those clowns who just made the most successful office suite ever, the most successful picture editing app ever, or the most successful video player ever. Because we’d taken advice on how to write software from a company that was 90 days away from bankruptcy and had proven incapable of executing on software development, we were awesome and the people who were making the shittons of money on the most popular software of all time were clueless idiots.

But what about the people who were writing Mac software with WXWindows (which included myself), or RealBASIC, or the PerlObjCBridge (which also included me)? Where did those fit in this dichotomy? Or the people over on Windows (me again) or Solaris (yup, me here)?

The definition of “us” and “them” is meaningless. It needs to be, in order to remain fluid enough that a new “them” can always be found. Looking through my little corner of history, I can see a few other distinctions that have come and gone over time. CodeWarrior vs Project Builder. Mach-O vs CFM. iPhone vs Android. Windows vs Mac. UNIX vs VMS. BSD vs System V. KDE vs GNOME. Java vs Objective-C. Browser vs native. BitKeeper vs Monotone. Dots vs brackets.

Let’s look in more detail at the Windows vs Mac distinction. If you cast your mind back, you’ll recall that around 2000 it was much easier to make money on Windows. People who were in the Mac camp made hand-waving references to technical superiority, or better user interfaces, or breaking the Microsoft hegemony, or not needing to be super-rich. Many of those Mac developers are now iPhone developers. In the iOS vs Android distinction, iOS developers readily point to the larger amount of money that’s available in making iOS apps…wait.

O(community)

The community contribution fraction

As Scotty said, an important role in a community is that of the reader/consumer/learner, the people who take and use the information that’s shared through the community. Indeed in any community this is likely to be the largest share of the community’s population; the people who produce and share the information are also making use of it too.

The thing is, that means that there are many people who are making use of those great ideas, synthesising them, and making even new and better ideas. And we’re not finding out about them. Essentially there is more knowledge than there is opportunity to share knowledge.

It’d be great to have some way to make it super-easy for everyone who was involved in “the community” to contribute, even if it’s just to add a single thought or idea to the pool. As Scotty said, there’s no way you can force people to contribute, and that’s not even desirable as it’s a great way to put people off talking to you ever again.

So you can’t hold a gun up to people and force them to tell you a fact about Objective-C. You can ensure everyone knows what forms of contribution take place; perhaps they’ll find something that’s easier than they thought or something they’ll enjoy. Perhaps they’ll give it a go, and enjoy it.

Face to face

Conferences are definitely not that simple way for everybody to contribute. Conferences are great, though as I’ve said before there aren’t enough seats for them to have a wide direct impact on the community. Tech conferences will never be a base for broad participation, both due to finite size (even WWDC comprises less than one percent of registered developers on the platforms) and limited scope for contribution – particularly the bias toward contributors with “prior”.

One “fix” to scale up the conference is to run the conference all year long. This allows people who don’t like the idea of being trapped in a convention with the same 200 people for a week the option to dip in and out as they see fit. It gives far more opportunity for contribution – because there are many more occasions on which contribution is needed. On the other hand, part of the point of a conference is that the attendees are all at the same place at the same time, so there’s definitely some trade off to be had.

Conferences and Appsterdams alike lead to face-to-face collaboration; the most awesomest flavour of collaboration there is. In return, they require (like Cocoaheads, NSCoder or whatever you call your pub/café meet) that you have the ability to get to the venue. This can call for anything from a walk down the street via a couple of ten-hour flights to relocating yourself and your family.

Smaller-scale chances for face to face interaction exist: one-on-few training courses and one-on-one mentoring and apprenticeships. These are nearly, but not quite, one-way flows of information and ideas from the trainer or sensei to the students or proteges. There are opportunities to make mentoring a small part of your professional life so it doesn’t seem to require a huge time investment.

Training courses, on the other hand, do. Investment by the trainer, who must develop a course, teach it, respond to feedback, react to technology changes and so on. Investment by the trainees, who must spend an amount of time and money attending the course, then doing any follow-up exercises or exams. They’re great ways to quickly get up to speed with a technology by immersing yourselves in them, but no-one is ever going to answer the question “how can I easily contribute to my community?” with “run a training course”.

Teaching at a distance

A lower barrier to entry is found by decoupling the information from the person presenting the information. For as long as there has been tech there have been tech books; it’s easy (if you have $10-$50) to have a book automatically delivered to your house or reader and start absorbing its facts. For published books, there’s a high probability that the content has been proofread and technically reviewed and therefore says something a bit accurate in a recognisable language.

On the other hand, there are very few “timeless” books about technology. Publisher schedules introduce some delay between finishing a manuscript and having something to sell, further reducing any potential shelf life. If you’re in the world of Apple development and planning to say anything about, for example, Objective-C or Xcode, you’re looking at a book that will last a couple of months before being out of date.

Writing a book, then, takes a long time which already might be a blocker to contribution for a lot of people. There’s also the limitation on who will even be invited to contribute: the finite number of publishers out there will preferentially select for established community members and people who have demonstrated an ability to write. It’s easier to market books that way.

The way to avoid all of that hassle is to write a blog (hello!). You get to write things without having to be selected by some commissioning editor. Conversely, you aren’t slowed down by the hassles of having people help you make the thing you write better, either—unless you choose to seek that help.

You then need to find somebody to read your blog. This is hard.

Stats for this blog: most pages have only ever been read a couple of hundred times.

If someone else already has an audience, you can take advantage of that. Jeff Atwood previously wrote about using stack overflow as a blog, where you’d get great reach because they bring their audience. Of course, another thing you can do on stack overflow is answer questions from other people: so that quick answer you contribute is actually solving someone’s problem.

This is, in my opinion, the hallowed middle ground between books (slow, static, hard to get into, with a wide reach) and blogs (fast, reactive, easy to pick up, hard to get discovered). Self-publishing a book is a lot like spending ages writing a long blog post. On the other hand, contributing to a community resource like a Q and A site or a wiki means only writing the bit of the book that you’re best placed to contribute. It also means sharing the work of ensuring correctness and value among the whole contributor base.

Our community / People with ideas ≪ 1

Whatever your definition of “the community”: the iOS developer community, the object-oriented programming community, the developer community—there are many more people who aren’t in that community. But they still have things to say that could be interesting and help us see what we do in different ways.

I’m not so sure that there are people out there doing what we do who don’t even passively engage with the rest of the community. Maybe there are, maybe there are lots. But I’m sure most people have at least read a book, or done a search that ended up at a mailing list post or blog entry. Very few people will never have used community-supplied resources; although it’s possible that there are programmers out there who’ve learned everything they know from first party documentation.

What I am sure of is that if you’re an Objective-C developer building mobile apps and you only listen to other Objective-C developers building mobile apps, you’re missing out on the information and ideas you could be taking from everyone else. Dave Addey told us to go and visit museums and art galleries to get inspiration, but that’s not all there is to it. Talk to someone doing Objective-C in a different context. Talk to someone doing Java, or Clojure. Talk to business people, or artists, or musicians. Break out of the echo chamber, and find out whether what other people are doing could be applied to what you’re doing.

Conclusions

As promised, there aren’t really any conclusions here. It’s more a collection of my own thoughts dumped out from brain to MarsEdit in order to let me make sense of them, and to stop me having to think about them at bedtime.

What’s clear is that there are a load of different ways for people to contribute to a community. Consumption of other people’s thoughts, advice and ideas is itself a very beneficial service as it’s how new ideas get synthesised, how new practices are formed and how the community collectively improves its output. It would be even better if what those people were doing were also made available and shared with the rest of us, to achieve an exponential growth in experience and advancement across the whole community.

But that’s not guaranteed to happen. The best thing to do is not to try driving people to contribute, but to give them so many opportunities to do so that, at some point, someone in the community will be in the position that sharing something is really easy and they choose to do so.

Other techniques to improve the number of ideas you get from the community are to be less adversarial in your definition of community, and more broad in your inclusion. The “community of people making iOS apps with Objective-C” is small, the “community of people making things” is universal.

Posted in AAPL, advancement of the self, books, Business, iDeveloper.TV, iPhone, Mac, NSConf, OOP, Responsibility, software-engineering, Talk, WebObjects | Comments Off on On community

Password checking with CommonCrypto

I previously described a system for storing and checking credentials on Mac OS and iOS based on using many rounds of a hashing function to generate a key from the password. Time has moved on, and Apple has extended the CommonCrypto library to provide a simple, standard and supported way of doing this. If this is still a problem you need to solve, you should look at doing it this way instead of following the earlier post.

We’re going to use a key-stretching function called PBKDF2 to make an encryption key of a standard length. This key probably will be much longer than the user’s password. However, it can’t possibly be any more random: it must be deterministically derived from that password so we’re stuck with the same amount of randomness that this password contains. A good key-stretching function should “smooth out” the randomness from the initial password, so that you can’t guess anything about the password given the function’s output.

We’re then going to use this key to calculate an HMAC of some known data. An HMAC is a bit like a digital signature, in that it depends both on the key used and the input data. We’ll store the HMAC but not the password and not the key derived from the password. Whenever the password is needed in the future, it must be provided by a user and cannot be derived from any of the data in the app.

The idea, then, is that when you set a new password, the app calculates this key, uses that to calculate an HMAC and stores the HMAC. When you try to use the app, you present a password, from which the app generates a key and an HMAC of the same data. If this HMAC matches the one that was previously calculated, the same keys were used, which (hopefully) means that the same password was supplied.

The faster you scream, the slower we go.

One of the problems that a key-stretching function must address is that computers are really, really fast. Normally computers being really, really fast is a benefit, but the faster it is to compute all of the above stuff the more guesses an attacker can try at the password in some amount of time. We therefore want to make this function slow enough that brute force attacks are limited, but not so slow that people get frustrated with the app’s performance.

PBKDF2 has a tuneable parameter – the number of rounds of a hashing function it uses internally to stretch the key. With CommonCrypto you can ask for a number of rounds that will result in the function taking (approximately) a certain amount of time to work on a password of a certain length.

Requirements for the rounds parameter

  • The number of rounds used when checking a password should be the same as the number used when generating the stored HMAC, otherwise the keys generated won’t match.
  • The above means that you need to choose a single value to use across app installs and hardware – unless you’re happy with losing access to all user data when a customer upgrades their iPad.
  • You will want to revise this parameter upwards as faster hardware becomes available. This conflicts with the first requirement: you’ll need a fallback mechanism to try the same password with different “versions” of your rounds parameter so that you can upgrade users’ credentials with your app.

With those in mind, you can construct an algorithm to choose a tuning parameter based on this call:

        const uint32_t oneSecond = 1000;
         rounds = CCCalibratePBKDF(kCCPBKDF2,
                                   predictedPasswordLength,
                                   predictedSaltLength,
                                   kCCPRFHmacAlgSHA256,
                                   kCCKeySizeAES128,
                                   oneSecond);

You can probably know what length of salt you’ll use: salt should be a block of random data that you supply, that is used as additional input to the key-stretching function. If two different users supply the same password, the salt stops the function from generating the same output. You probably can’t know what length of password users will use, but you can guess based on experience, data and knowledge of any password strength rules incorporated into your app.

Notice that you should derive this rounds property on the target hardware. The number of rounds that take a second to run through on your brand new iMac will take significantly longer on your customer’s iPhone 3GS.

Generating the HMAC data

Both storing and checking passwords use the same internal function:

- (NSData *)authenticationDataForPassword: (NSString *)password salt: (NSData *)salt rounds: (uint) rounds
{
    const NSString *plainData = @"Fuzzy Aliens";
    uint8_t key[kCCKeySizeAES128] = {0};
    int keyDerivationResult = CCKeyDerivationPBKDF(kCCPBKDF2,
                                                   [password UTF8String],
                                                   [password lengthOfBytesUsingEncoding: NSUTF8StringEncoding],
                                                   [salt bytes],
                                                   [salt length],
                                                   kCCPRFHmacAlgSHA256,
                                                   rounds,
                                                   key,
                                                   kCCKeySizeAES128);
    if (keyDerivationResult == kCCParamError) {
        //you shouldn't get here with the parameters as above
        return nil;
    }
    uint8_t hmac[CC_SHA256_DIGEST_LENGTH] = {0};
    CCHmac(kCCHmacAlgSHA256,
           key,
           kCCKeySizeAES128,
           [plainData UTF8String],
           [plainData lengthOfBytesUsingEncoding: NSUTF8StringEncoding],
           hmac);
    NSData *hmacData = [NSData dataWithBytes: hmac length: CC_SHA256_DIGEST_LENGTH];
    return hmacData;
}

Storing credentials for a new password simply involves generating a salt, computing the authentication data then writing it somewhere:

- (void)setPassword: (NSString *)password
{
    //generate a random salt…

    //do any checking (on complexity, or whether the passwords entered in two fields match)…

    NSData *hmacData = [self authenticationDataForPassword: password salt: salt rounds: [self roundsForKeyDerivation]];
    //store the HMAC and the salt, perhaps by concatenating them and putting them in the keychain…

}

Then testing the credentials involves applying the generation function to the password guess, and comparing the result with what you previously stored:

- (BOOL)checkPassword: (NSString *)password
{
    //recover the HMAC and the salt from wherever you stored them…

    NSData *guessedHmac = [self authenticationDataForPassword: password salt: salt rounds: [self roundsForKeyDerivation]];
    return [guessedHmac isEqualToData: hmacData];
}

Conclusion

If you can avoid storing a password in your app, even in the keychain, you should; there’s then a much reduced chance that the password can be recovered from the app by an attacker. Deriving a key from the password using PBKDF2 then testing whether you can use that key to obtain a known cryptographic result obviates the need to store the password itself. Mac OS X and iOS provide an easy way to use PBKDF2 in the CommonCrypto library.

The key derived from the password could even be used to protect the content in the app, so none of the documents are available without the password being presented. Doing this offers additional confidentiality over simply using the password for access control. Building a useful protocol around this key requires key wrapping, the subject of a future post.

Posted in Authentication, code-level, Crypto, password | 1 Comment

Sound bites considered harmful

Knuth said:

premature optimization is the root of all evil.

Only, what he actually said was:

There is no doubt that the grail of efficiency leads to abuse. Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.

Yet we should not pass up our opportunities in that critical 3%. A good programmer will not be lulled into complacency by such reasoning, he will be wise to look carefully at the critical code; but only after that code has been identified. It is often a mistake to make a priori judgments about what parts of a program are really critical, since the universal experience of programmers who have been using measurement tools has been that their intuitive guesses fail. After working with such tools for seven years, I’ve become convinced that all compilers written from now on should be designed to provide all programmers with feedback indicating what parts of their programs are costing the most; indeed, this feedback should be supplied automatically unless it has been specifically turned off.

In that context, the quote takes on a very different meaning.

Posted in software-engineering | 1 Comment

How people learn

Don’t you hate those times when you go to a talk or article that says “you should be doing this”, but then doesn’t explain how to do that?

I just wrote one. In “Coding. Standards.” I explained that what software engineers should do is to learn and analyse from all their experiences and interactions. But how do you do that? How does learning work?

The model of learning that I know best is the Kolb learning cycle, which I was taught when I was in management training. Yes – the reason I wear my hair this long is to stop it going pointy. David Kolb published this model in the 1980s, it’s been augmented and adapted since then but is still approximately as written. Having said that, some neuroscientists dispute the validity of this and other models of learning.

Kolb says that there are four distinct processes in learning:

  • Concrete Experience: actually doing a thing.
  • Reflective Observation: analysing how you (or someone else) did a thing.
  • Abstract Conceptualisation: building a model of how things should be done.
  • Active Experimentation: just playing with the plasticine and seeing what comes out.

Not everybody goes through all of the items in the cycle, but most people start out somewhere and progress through at least a couple of the points, probably in the order presented (acknowledging that as a cycle it should be, well, cyclic). The four examples he gave corresponded to four “corners” of the cycle:

  • Diverging: concentrates on concrete experience and reflective observation. Tries something out, and decides how it could be adapted.
  • Assimilating: focuses on observation and conceptualisation. Sees how different examples might fit a common pattern.
  • Converging: conceptualisation and experimentation. Try to build a mental model from theory and then put it into practice.
  • Accommodating: experimentation and experience. Hands-on trying things out and deciding which ones work.

This gives you a starting point for working out how you learn, and what materials best support your style: there are many blog posts and conference talks based on personal experience, which fit the “reflective observation” category. Technical books tend to be more abstract, and fit conceptual learning. Training courses often bridge conceptualisation and experimentation.

It also gives you a way to understand why some people don’t like your good-faith attempts to help them. “RTFM” works for those people who want to build a conceptual model, but not for everybody else. Similarly, those people saying “please give me the codes” may be people who learn by abstracting from examples. You can’t hate people just for learning in a different way.

Posted in advancement of the self, books, Talk | Comments Off on How people learn

Coding. Standards.

I just realised that this month marks the 10th anniversary of my first payment for writing software (on, of all the weird things to be writing software on in 2002, a NeXTstation)! What have I learned from those ten years? What advice would I give to someone who wants to do this stuff for at least 10 years?

Programming is the easy bit.

Well, comparatively. There are hard bits in programming, and every few years a new paradigm comes along that means you have to unlearn whatever it was you were doing and learn something else to do anyway. So learning programming is never done, but still programming is easier than:

  • estimating. The one project I’ve worked on that finished on its planned completion date only did so by accident.
  • getting any kind of agreement out of two or more people.
  • accepting that the other person isn’t a dick, but has different goals and problems than you.
  • objectively evaluating your own work.
  • objectively assessing someone else’s evaluation of your work.
  • stopping programming when you’re done.

You always need to be learning.

You can’t compete on price in the software market, because there’s always some student somewhere who’s willing to do the same work for free. It was Mike who first taught me that. You have to compete on quality, which means you need to strive to improve your own quality. Because other people are too, so you need to run just to stand still.

There are various ways to learn, and they’re not mutually exclusive. A combination of books/articles, experimentation, and discussion with peers is valuable. If your town has an Appsterdam or a CocoaHeads, get along and say hello.

You probably don’t want to be doing this in 10 years.

I was actually a UNIX programmer a decade ago (well, I was mainly a student). Then I was a barman, then sysadmin, then a Linux server application programmer, then a Mac app programmer, then a contract Mac programmer, then a Java app programmer, then a security consultant, then an iOS app programmer. There’s only a small probability that I’ll be an iOS app programmer in 10 years.

This world moves really quickly. Ten years ago, the iPod was a new and relatively risky proposition. Macs used PowerPC CPUs. Windows XP was the new hotness, and .NET was just about to appear – meanwhile Mac OS X was a sluggish amalgam of NeXT, Java and legacy code. Java, by the way, was run by a now-defunct company called Sun Microsystems, which was trying to work out how to survive the dot-com crash.

Speaking of the dot-com crash, it seems highly likely that within the next decade we’ll see the dot-app crash. App downloads are worth $0.18¢ each, but an app costs $200k – apparently it’s hard work. That means you’ve got to either get yourself into the long tail value-wise (i.e. have a very good app that people will pay for), or you’ve got to find a million users for version 1.0.

For everyone else, the market isn’t worth staying in long-term. The market will bore of brochureware apps, only a few high-value brands will be able to support unprofitable vanity apps, and VCs will realise that throwing their money after an app with no profit strategy is the same as throwing their money after a website with no profit strategy.

It’s likely that at least one of the companies that’s big in the current software world – Microsoft, Apple, Oracle, Google and the like – will be big in the software world of 2022. It’s also likely that there’ll be some new comers that change things completely: Facebook and Twitter didn’t exist ten years ago, and neither did Android, Inc. Sometimes companies that seem to be in an interminable tailspin – like Apple – turn themselves around and become successful.

Learn more than one thing

This is related, in part, to what came above: the thing you’re using right now may not exist, or may be hard to get work in, in a few years’ time. On the other hand, some things seem to outlive the cockroaches: C – and by extension, languages that can link somewhat seamlessly with C like C++, Fortran and so on – have been going on forever. It can be hard to predict which of these camps your favourite tech sits in, so learning more than one thing keeps you employable.

More than that, if your technology of choice comes from a single supplier (e.g. Microsoft, Apple, Embarcadero) then diversification just makes good business sense. This particularly applies in the age of the app store where that sole supplier can also be your sole vendor – you don’t want to sign your entire business’s value over to one other company.

Learning another thing makes you better at the first thing

This is another reason why diversifying your technology portfolio is beneficial. Many of the changes I’ve made recently in the way I write object-oriented software come from talking to Clojure programmers.

The more different things you know, the more connections you’ll be able to make between them. The more you’ll be able to critically analyse one technology, beyond what the vendor tells you. And the more you’ll be able to understand other new things and incorporate them into your Weltanschauung.

Conclusion

My summary could be “learn whatever you can: you never know which bits you need”. Or it could be “don’t rely on your supplier to solve all of your problems”.

I think it’s actually going to be: analyse everything. Reflect on your work: what went well? What didn’t? Could you have done things better? If you don’t think you could have, then you’re probably wrong: what would you need to know to identify the bit that actually could’ve gone better?

But know when to stop, too. Analysis paralysis is as much of a problem as going in blind. At some point, you need to suck it up and move on. Trading these two things against each other is the real difficulty in software engineering.

Posted in advancement of the self, Business, code-level, OOP, software-engineering | 2 Comments

Objective-C literals and subscripts

If you’re using clang from their website instead of sticking with Apple’s release, you get support for Objective-C literals and object subscripting. I thought I’d take the BrowseOverflow app and apply this new syntax to it. Notice that the code below doesn’t match what’s in github, which still works with currently-released versions of Xcode and their compilers.

Indexed/Keyed subscripting: we’ve seen this before

Using the syntax described above, you can subscript into an object using something that looks like the traditional C square bracket notation. If you use an integer, you get indexed subscripting:

        Answer *thisAnswer = question.answers[indexPath.row];

If you use an object, you get keyed subscripting:

            NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithCapacity: 1];
            if (localError != nil) {
                userInfo[NSUnderlyingErrorKey] = localError;
            }

This is something that’s been available in many languages before. Smalltalk (from which Objective-C derives) had a well-defined subscripting syntax across all objects, using at: and set:at:. C++ permits classes to supply the operator[]() method to use C-style index subscripting just as Objective-C does.

An aside in defence of operator overloading

If you look at traditional Objective-C syntax, you can see that (roughly speaking, and anyone who points out the edge case isn’t my friend) there are the things in square brackets that are objects and messages, and the things without square brackets are primitive types. There are two different worlds, and never the twain shall meet.

But actually, we’ve learned that encapsulation is good, and that allowing people to concisely express their intent is better than making them deal with our implementation details. Therefore we want to integrate our data types in the language. We want to tell people “add this thing to the other thing”, not “you need to call this function with these parameters which will add the things”.

Providing custom implementations of the standard operators is the best way of doing that. Yes, it hides what’s happening: that’s the point. Yes, it can be abused: the entire software industry is based on a foundation that makes it possible to write bad software. If you want to take away tools that can be used to introduce bugs, you need to take away everyone’s compilers and interpreters.

An aside on the aside about Objective-C operator overloading

So far, Objective-C objects can provide custom implementations of two C operators: the field access operator . used for type safe property access, and the subscript operator [] used as we saw before I digressed.

The reason subscript overloading works in ObjC is that it’s illegal to apply arithmetic operations to object pointers. In C, foo[bar] is just a fancy way of writing *(foo+bar) (which is why bar[foo] also works). If you’re not allowed to apply the [] operator to an id, then you know something else must be happening: i.e. you know that the object subscript behaviour is required.

Well the fact that you can’t do pointer arithmetic on an id means that you could also, for example, check for illegal use of the + operator and call -objectByAddingObject:.

Back to the point: boxing done well.

Many languages make some attempt to “box” primitive types like numbers in high-level value types like number objects. This often causes problems: for example in Java, which has both automatic boxing and method overloading, I could do this:

public void foo(int x) { … }
public void foo(Java.lang.Integer x) {…}

foo(3);

It’s not clear whether 3 refers to the primitive type or to the object type, and therefore it’s not clear which method will get called.

The same problem could have been encountered in ObjC: does foo[3] refer to indexed subscripting or to keyed subscripting using an NSNumber instance?

Thankfully whoever designed the Objective-C boxing behaviour decided it must always be explicit. You can get a number like this:

- (void)browseOverflowViewControllerTests_viewDidAppear: (BOOL)animated {
    NSNumber *parameter = @(animated);
    objc_setAssociatedObject(self, viewDidAppearKey, parameter, OBJC_ASSOCIATION_RETAIN);
}

but otherwise numbers will always be treated as numbers, not as objects.

When it all gets a bit much

You’ve got two seconds, the house is on fire, what does this line do?

    NSString *questionBody = [parsedObject[@"questions"] lastObject][@"body"];

It can be a bit hard to read that, and to pick out which brackets go with messages and which go with subscripts. I can imagine the sort of people who like to issue pronouncements on whether to use the dot operator to access properties will love the new subscripting syntax.

Posted in code-level, OOP | 2 Comments

Supporting both ARC and MRC build settings

Let’s face it, people don’t read `README`s. If you write library code that people are going to use in their own projects, you can’t rely on that bit at the bottom of the documentation that tells people to do -fobjc-arc on your files that they drop into your project. You can rely on all the issues that get reported about memory leaks :-).

The actual solution

Your project should build a library (static by necessity on iPhone, there are other options on the Mac) so developers can just add that one library target as a build dependency, and drop the headers into their own projects.

The result is that now your memory management is hidden behind the object boundary and the naming conventions of your methods. You should probably still be using manual reference counting if you want people who’ve already written apps to be able to link against your code without problems, because there are still apps out there that target versions of iOS that can’t link ARCified objects. Regardless, whether an app is ARCified or not it will be able to link your library.

The other solution

Sometimes you find code that developers are supposed to integrate by dropping the source files into their targets. This is worse than providing a static library: now you’ve made the developer care about the internals of your code – the compiler flags you need to set become something they have to deal with in their target’s build settings. This includes the setting for whether automatic reference counting is enabled.

…unless you support both possibilities. I’ve used the macros defined below to use the same code with both automatic and manual reference counting compiler settings. This code included Core Foundation bridged objects, so this isn’t just “the trivial case” (whatever that is).

#if __has_feature(objc_arc)
# define FZARelease(obj)
# define FZAAutorelease(obj) (obj)
# define FZARetain(obj) (obj)
#else
# define FZARelease(obj) [(obj) release]
# define FZAAutorelease(obj) [(obj) autorelease]
# define FZARetain(obj) [(obj) retain]
#endif

Objective-C garbage collection

I haven’t had a need to test how that interacts with garbage collection, or build code that works in all three environments. However, if you already wrote your code to support (rather than require) GC, and you don’t rely on CFMakeCollectable, this collection of macros at least won’t make anything worse.

Posted in Uncategorized | 2 Comments

App security consultancy from your favourite boffin

I’m very excited to soon be joining the ranks of Agant Ltd, working on some great apps with an awesome team of people. I’ll be bringing with me my favourite title, Smartphone Security Boffin. Any development team can benefit from a security boffin, but I’m also very excited to be in product development with the people who make some of the best products on the market.

There’s another side to all of this: once again can security boffinry be at your disposal. I’ll be available on a consultancy basis to help out with your application security and privacy issues. If you’re unsure how to do SSL right in your iOS app, are having difficulty getting your Mac software to behave in the App Store sandbox, or need help to identify the security pain points in your application’s design or code, I can lend a hand.

Of course, it’s not just about technology. The best way to help your developers get security right is to help your developers to help themselves. When I’ve done security training for developers before I’ve seen those flashes of enlightenment when delegates realise how the issues relate to their own work; the hasty notes of class or method names to look into back at the desk; the excited discusses in the breaks. Security training for iOS app developers is great for the people, great for the product – and, of course, something I can help out with.

To check availability and book some time (which will be no earlier than July), drop me a line on the twitters or at graham@agant.com.

Posted in Business, ssl, threatmodel | Comments Off on App security consultancy from your favourite boffin