Sunday, July 26, 2009

Lessons learned from IPod Development

A timeline with a new library and language


Learning a language like Objective-C and the iPhone SDK is very time consuming. Doing this at the same time where a professor is expecting you to produce a vague product (read: no concrete requirements), and expect to be confused. That's not to say it wasn't a very effective learning experience.

Challenges


Learning a library and developing a product at the same time is not an efficient process. Your designs are colored by your understanding of the previous libraries and languages you have worked with--not the current one you need to develop with.

This boils down into two categories of challenges:

Identifying constraints


What can the library not do? Is there functionality from other libraries I would use and isn't available from the current library? What alternatives are there with the library I'm using now?

Identifying capabilities


What things can the library make easier for me? These are much harder to discover as they lurk in hundreds of html docs or deep in information-light tutorials. Ofter there are constraints which are only imaginary because the library offers the functionality you want, you just don't know about it yet.

Inaccurate (Imaginary) Constraints and Capabilities


Working in an unfamiliar language with an unfamiliar library easily lends itself to inaccurate assessments of the tool's constraints or capabilities. There might not even be an analogous construct, such as moving from Python to C and expecting duck typing. The tool might offer new constructs to use such as going from C++ to Ruby and not knowing about mixins, an example of inaccurate constraints.

Since the cost of changes in software grows exponentially as the project progresses, continuing under flawed assumptions of constraints and capabilities often makes it cheaper in time and effort to redesign and rebuild from scratch.

Conclusions


Know when to start over and redesign


This is may be the more painful of the two lessons. Abandoning a program and retooling it from scratch is a hard prospect when facing approaching deadlines. This can be important to realize during design and further emphasize the need for clearly defined subsystems and packages and components with minimal interdependencies as a levee against cascading changes in a redesign.

Abstractions and a levelizable design will act as firebreaks when you rip out part of the system after finding several capabilities you didn't know the library had.

Writing for a new library is liberating when you expect to throw your code away, but don't get careless. Rewriting something is a lot easier when it is hidden behind an abstraction and the fewer dependencies on a component means less code to change if that component gets modified significantly.

Rewrite may not mean "full rewrite" if you watch and reduce the number of places you're depending on that new library. Of course you're sunk if the new tool is a new language.

Learn your environment


Learning about the environment is especially important if you are to make a product out of it quickly from management. You should treat the task of learning about your environment as requirements analysis for the NEXT iteration of th eprogram. This goes back to the previous conclusion, that you should expect to do a redesign.

Trying out things in a test (or sandbox, whatever term you prefer) is especially important to learn how to apply new concepts in the domain. Using a separate project for this work is key so you don't screw up prototype code with experimentation. To a certain extent the current prototype is experimentation code, but it is something to show your boss and should be treated as production-level code.

The faster you learn the capabilities of the new tool, the fewer redesigns you will need to do because of a lack of understanding about the project's domain. As your progress there will be less work needed to identify constraints and capabilities of the new tool. It is suggested that you spend much more time in the beginning doing many small sandbox projects to learn about various aspects of the environment, before you begin any project level code.

More work on the front end of the project in sandbox work means less program guts to destroy and better assumptions when work starts on the real program. If a task is annoying or common to deal with, you might be operating under undiscovered capabilities of the tool.