This is quick tutorial showing how to get started with F* in Objective-C. F* is a proposed meta-pattern for application development (see here for related documents)
You can check out the sample project from SVN:
Setting up your project
- Open XCode.
- Go to File > New Project
- Select ‘Empty Application’.
- In Product Name, I input FStarExample.
- I put my projects under my experiments/ folder. XCode will create a folder for our project.
Arranging the sample project
I like to have ‘headroom’ in my projects. The initial project structure looks like this:
- FStarExample (project node)
- FStarExample (source location)
- FStarExampleTests (for unit testing)
- Frameworks (libraries required by the iOS SDK)
- Products (build output)
I regroup all items, so that it looks like this:
- FStarExample (project node)
- source (custom group)
- tests (previously, ‘FStarExampleTests’)
- FStarExample-Prefix.pch (digged up from ‘Supporting Files’ I just like to keep this one ‘visible’)
- FStarExample (still the app delegate)
Keep in mind that XCode groups are just a convenient way to… group files. For better and for worse, grouping is irrelevant to the underlying file structure.
Setting up an F* instance
Under source I create the following structure:
The Facade will be used to instantiate all the features we use in our application. The Dispatcher provides the basis for gluing features together. Feature is the base class for all application features.
Note: XCode doesn’t encourage physical groupings (putting source files in separate folders – it is needless to say possible but doesn’t flow smoothly) so I’ll be content with XCode groups.
Creating a feature
To create a feature named foo, follow the steps:
- create a group named foo
- create a subclass of Feature, Foo inside group foo.
- foo overrides setup in Feature.
- import the feature class from Facade and add an entry to initFeatures.
The sample project illustrates the above steps.
The dispatcher mediates communication between features via events. In the provided example:
- Foo registers with the dispatcher to receive an event x. registration happens within the setup method. (While setup is running, nothing warrants that all features are already initialized so while it’s okay to register for events, it is not okay to dispatch.
- After all features are setup, the start method is called on each feature, at which point Bar dispatches the event.
- We need to import the feature class
- The feature class needs to be instantiated and added to the feature list.
When I use F*, I tend two follow a 3 step cycle.
During the ‘inductive phase’, I try to focus exclusively on the problem I am solving. If I feel my feature requires external input (or a signal), I design notifications without worrying about the source of such notifications.
This approach becomes important over time because it allows solving the problem at hand without burdening ourselves with the growing ‘mass of code’ that the project generates. For me this inductive phase is similar to ‘starting a new project’. Surely most programmers have noticed that they feel dynamic and fresh at the beginning of a new project?
During the testing phase, notifications can be used to write acceptance tests – test the feature in isolation.
During the integration phase, I make sure that the notifications the feature relies on are actually satisfied.