Saturday, 28 November 2015

The Art of Estimation

TL;DR - Estimating software is hard, to be reasonably accurate it is best to split the requirements in very small stories, and naturally experience does help
Estimation in the software environment is more an art than a science. In most cases anything that is estimated takes longer than originally planned. There are generally two outcomes; the deadline is moved and the budget is increased or the scope is reduced. Software estimation is a huge subject, so I only intend to explain some ideas that have helped me throughout the projects I've been involved in.
Naturally, somebody that has already done a similar task before will be able to provide a better estimate. For example, specifically to iOS/Mac development, the setting up of a CoreData stack will usually be more accurately estimated by a senior developer as opposed to a junior developer. However, by being meticulous about estimates a reasonable level of accuracy can be achieved.

Importance of requirements

Before estimating software, it is good too start with very high-level epic stories. An epic story is a high-level requirement, for example, in a recipe app, one of the epics would be to be able to show the details of a recipe (i.e. ingredients, steps, summary and so forth). When defining this it's important to focus on the most valuable ones firsts. This is easier said that done as Oscar Wilde said "Nowadays people know the price of everything and the value of nothing.”. One you have your epics, then you can work your way down to individuals stories and the small tasks necessary to complete the story. 
Requirements and estimation are tightly linked, naturally if the requirements change so will the estimates. Growing requirements lead to scope-creep and will make your project fail if they are not controlled. Hence, unstable requirements lead to poor estimates. This tends to occur when the value of what we are building is not clear.

Keep estimations small

The bigger the task the harder it's to estimate. The reason for this is that variables, edge-cases and requirements are too many to get a real grasp of. As a rule of thumb if a task is estimated to take more that two days, it should be broken down to a simpler form. As an oversimplified example, it is harder to estimate a task that is:
  • Load the recipe data onto the app
Than these tasks:
  • Define and document the specification of the data
  • Create a model representing a recipe
  • Define relevant images for a recipe
  • Parse JSON (or relevant data type) and map it to the create model
  • Write unit tests to prove that the JSON has been parsed correctly into the models
By keeping estimates small and concise, it's easy to compare the result of how long something was estimated to take and how long it took. This is key to fine tune the ability to estimate small tasks in the future.

Dealing with the unknown

Sometimes we need to estimate something that we have never done before. You may think that if the implementation of a task is unknown we should give a very high estimate. However, "Work expands so as to fill the time available for its completion" as defined by Parkinson's law. Among other things, this suggests that overestimating is not the solution since the task will just take longer without necessarily adding more value.
In this case, it's best not to give an estimate as the time you think it will take will be as good as throwing a dice. Therefore, for these stories it's best to spend a small amount doing a spike. A spike is about spending a small amount of time to investigate the unknown before estimating the story. For example, before implementing a new SDK or library, it can be used in a sample project for one or two days to know how it works. This will give you much more information to later provide a more accurate estimate.

Conclusion

Requirements will change over time as discussed previously. Hence, it's important to understand and plan for high-level estimates to change as the project evolves. Naturally, the allowance for changes will depend on your time and budget constraints.
Underestimating leads to low team moral, increased costs, more bugs and ultimately projects failing. On the other hand, overestimating will mean that the relationship between the value of a project and the cost will be diminished as a lot of time will be spent procrastinating.

Saturday, 21 November 2015

Designing reusable components

TL;DR Plan the different part of your projects before you start coding. Try and separate implementation details from the general requirements of your project.
When working on a project, it's always tempting to start coding immediately. While we might tell ourselves that this code is only a prototype and can later be thrown away, it seldom happens. Temporary solutions have the bad habit of becoming permanent. To make matters worse, we usually feel time pressures that hinder our ability to plan and spend time thinking about what we need to do. 
In the new few weeks we're going to publish a series of blog posts exploring different aspects of project organisation and management such as:
  • Designing before coding
  • Developing reusable components
  • How to produce estimates
The objective of this article is to briefly go through the design of a generic component. By design we mean the work that is done before the actual coding. We use the term component to refer to a small part of a larger project. We will illustrate what is being discussed with a real component that I developed recently: the onboarding process of a mobile app.

Capturing requirements

The traditional software development process seems to imply that there is a magical way to know what our client might want. That it's only a matter of sitting down and writing down all of these requirements before we start with development. The reality is far from that.
Requirements will change as the project is developed because in many instances your client or customer doesn't really know what they want or it's not possible to know at such an early stage. At this stage we should therefore aim to get a general picture of what we're trying to produce before we write any code. 

High-level requirements

We should start with the high-level requirements, that is requirements that are not specific to any design or implementation. This means asking questions like:
  • What is our component supposed to do?
  • Who will be using it?
  • Where will it be used?
  • What is our preferred outcome?
Brainstorming our ideas can be the right approach to capture as much information as possible.
In the mobile onboarding example, after brainstorming our diagram could look like this: 

In our onboarding example the requirements could be the following:
  • Introduce the user to a new app
  • For mobile phone and tablet users
  • Delight the user
  • Indicate possible actions that can be performed
  • Easy to read instructions

Implementation specific requirements

After we've gathered our high-level requirements, we might concentrate on implementation-specific ones, which will usually stem from the high level requirements. We might ask ourselves questions such as:
  • What screen sizes will it support?
  • Will it have text or images?
  • Will there be animatations?
  • Will there be buttons or other UI components?
  • Should we use a table, a grid, or some other layout?
During this phase, I find it quite useful to do pencil drawings about what the component might look like (or diagrams if it's an internal component without a UI).
A basic diagram used for reasoning about the onboarding component could look like this: 

So, going back to our onboarding example, these might be some of the implementation-specific requirements:
  • Must have a full-screen background image
  • Must use pages to support multiple instructions
  • There should be animations or effects when we change a page (for example a parallax effect)
  • There should be a clear header plus a longer body copy
  • It should be possible to have a button on every page that can be linked to an action

Designing

By now we should have as good as an idea as we can about the generic component we're designing. It's therefore a good time to start doing some visual prototyping that we can later on use for development. Through this process we might also discover more requirements as well. There are many tools out there for rapid prototyping, some more sophisticated than others. I've used Sketch because it's easy to use and one can look at the design in the target device quite easily. Use whatever you feel more comfortable. 
Onboarding example design prototype:

Through this iterative process you'll end up with a design to implement as well as attributes that might need to be easily changeable to make your component generic. In our onboarding example, we decided that the following attributes should be customizable: 
  • Button placement
  • Fonts
  • Background image
  • Animation speed
  • Corner radius of body copy box
  • Line width of body copy box
  • Border colour
  • Text aligment (justified, centred)
  • Logo image
Even if you think that some of this attributes might seldom be changed, it's better to code in a way that they're customizable so there's more flexibility in adjusting the component's design when it's actually implemented. There's nothing more irritating than having to rewrite parts of your code because your customer or design team want the component to do something else. The later in a project that one needs to make changes, the more painful they can be.

Conclusion

The basic idea is to try and spend some time thinking about your component or project in a general way, before writing any code. This is likely to save you time and effort in the long run, as well as produce more generic code that can be reused in future projects.

Saturday, 14 November 2015

The state of the tvOS App Store

TL;DR - The tvOS App Store is a bit too light on features and discoverability is very poor meaning that it is very unlikely that even your mother will download your app

Discoverability

After uploading two very simple no thrills games Helicopter [1] and Ping Pong Arcade [2] for tvOS and looking into the tvOS App Store for 2 weeks we have found that discoverability is very poor in its current state. 
As a user it's hard to find relevant apps to you and as a developer it's hard to target specific users to your app. Currently depending on which country you are on you'll see between 3 and 5 tabs; Featured, Purchased and Search, and optionally depending on your country Top Charts and Categories. For example, the UK store does not currently have a categories section.
This will get better as Apple is adding various category sections and rankings as more apps come to the store. This is slowly being introduced because of the lack of tvOS apps out there. If you feel like exploring what tvOS apps are out there, you are out of luck.
Searching the tvOS App Store is quite a painful experience (quite literally). Siri dictation cannot be used for searching and it does not look like 3rd party external keyboards are compatible with the latest Apple TV. Currently, the only way to search is by using the Apple TV Remote with the displayed keyboard. This is indeed an annoying limitation of the Apple TV (Apple Support CommunitiesMacRumors forum). On the bright side given the lack of apps in the store only typing a few letters will generally find you what you need.
Given the current state, if you want to get a descent number of downloads (either paid or free) you need to be featured, so users can easily find your app.

Featured section (UK store)

iOS and tvOS apps can share the same bundle ID, meaning that a user that downloads your app on the iOS App Store will see it on the purchased section of the tvOS App Store. Depending on your business model it may make sense to have the same bundle ID for your iOS and tvOS. This way there is a better chance you'll get users downloading your tvOS app since it will be more visible to them as there is a dedicated Purchased section.

Limited deep linking to your app

As far as I know, the only way to link to your app is from another tvOS App. For example:
if let appStoreURL = NSURL(string: "https://itunes.apple.com/uk/app/helicopter/id1047310922?mt=8") {
      UIApplication.sharedApplication().openURL(appStoreURL)
}
Within iOS there are numerous ways of doing this; links on websites, mobile ads, emails, SMS and so forth. At the moment it's hard to picture how deep linking would work on the Apple TV but I'm sure this will be solved in the coming months since tvOS is still very new.

App previews are limited

After a great adventure, a user has finally found your app (whoohoo!). However, this is only half the battle won, now you have to do everything in your power to convince them to actually download your app. Even though the design of an app page is nice(-ish), it's interesting that there are no app preview videos. This feels like something that is distinctly missing, specially considering this feature is available in the iOS App Store.

Helicopter

Ping Pong Arcade


Only a star rating from 1 to 5 is allowed, no actual reviews. This does make sense when you understand how painful it's to write using the Apple TV remote. However, as a user it's hard to be convinced to download an app after seeing just a star rating. To be honest even if the user could write reviews, there is a pretty good chance that they will end up writing something short using monosyllabic words.
At the moment there are no analytics to know how many people actually reach your app preview page as it's the case of the iOS App Store. This makes it very hard to know if people can't find your app or they find it but don't download it.

Conclusion

The tvOS store feels very limited, frankly it looks like it's a beta version. It's hard to find the apps you are looking for and explore what is out there. Should you invest time/money in a tvOS app? If you intend to make money out of it and you don't have a huge (and I do mean huge) pile of cash for marketing then probably hold fire for now until the tvOS App Store develops into something more user friendly.
If you are not looking to make money, you should absolutely develop for tvOS. The development is very similar to iOS and it's a good learning experience. The platform is different enough that you will think about UI/UX in a different way. Having been developing for tvOS since September I can see that the Apple TV has a huge potential but currently only big players can reach users given the current state of the tvOS Store.

Footnotes

Saturday, 7 November 2015

Storing your data on tvOS, part 2: CloudKit

cloudkit-post In the first part of this series about data storage on tvOS, we've discussed using NSUserDefaults and iCloud KVS on tvOS. Today we're going to go through a very brief introduction of CloudKit. As we discussed before, the Apple TV has rather limited local storage space. If you plan to store a significant amount of data (according to our Apple overloards that means more than 1 MB) you might want to check out CloudKit. The information about CloudKit is not tvOS-specific, so it should still be useful to you if you're working on an iOS or Mac app.
The idea of this post is to briefly describe CloudKit's main features and workflow so you can then go on your merry way and try it out.

So what is CloudKit and why use it?

CloudKit is a BaaS (Backend as a service, like Parse) managed by Apple. It's easy to use an low cost relative to other options. Just for being a rockstar member of Apple's developer programme you get for free:
  • 10 Gb Asset storage
  • 100MB database
  • 2GB Data transfer
  • 40 requests per second
In the likely event that your app is an overnight success, you can go and purchase more storage to cover your ever-growing needs.
It's worth mentioning here that CloudKit does not make use of any of the user's iCloud storage. In a sense, it's separate from iCloud. It only uses the user's existing credentials for authentication.

Getting started

Naturally, you first need to enable the CloudKit entitlement on your project. Go to the target preferences and click on the 'capabilities' tab. Turn on iCloud and then select CloudKit.
This will create a default container for you as well. You might be wondering, what the heck is a container?! Well, a container keeps your app's records on the server. It's essentially a grouping of databases. You might have there a public database that is shared and a private one which is user-specific for example.

The CloudKit dashboard

The dashboard is where you'll be creating the records that your app will be using. You can click 'CloudKit Dashboard' in the capabilities pane to go straight to it.
You'll see 'Record Types', 'Security Roles' and 'Subscription Types'. In this post we will only deal with record types. If you've used other BaaS before you might be familiar with these concepts. If not, you can think of a record like a model class in your app. Essentially, a record type is a set of fields of various attributes. A record is an instance of a record type.
For example, if we had a phone book app, we might have a record type called entry that contains the fields name, address and phone number.
To create a new record type, select 'Record Types' under 'Schema' and then press the '+' button.

Public and Private zones

CloudKit supports both private and public zones so you can have data that is in common to all users of your app as well as private data that is user-specific. When you create a new record, you can decide if it will be used for public data or private data by adding it to the corresponding section. For example, if we want to add a new phone book entry to our public data (let's imagine this is a corporate phonebook so it must be available to all) we can follow the following steps:
  1. Go to the default zone under public data
  2. Make sure that the Entry entity is selected
  3. Press the '+' button
  4. Fill in the fields for the new record and press save

A whistlestop tour of CloudKit's API

There are various ways of accessing records in CloudKit. The two main ways of doing so are: 1. Fetching individual records by record ID 2. Using a query with a predicate to get a list of records

Fetching records by identifier

  1. In order to fetch records, we must first retrieve the public database in our container. In our case we're using the default container.
  2. We need to create a CKRecordID object with our record name.
  3. We then call the fetchRecordWithID: method with our CKRecordID object.
//1
let publicDatabase = CKContainer.defaultContainer().publicCloudDatabase
//2
let phoneEntryID = CKRecordID(recordName: "9f922b1c-7bd2-4550-b63d-342918a55230")
//3
publicDatabase.fetchRecordWithID(phoneEntryID) { record, error in

    guard error == nil else 
        return
    }
    print(record)
}
 

Fetching records by prediate

Fetching by predicate is very similar to fetching by identifier. The main difference being that we must create an NSPredicate object that we can then use with a CKQuery object. We then use our query object to peform a query on our database.
let publicDatabase = CKContainer.defaultContainer().publicCloudDatabase
let predicate = NSPredicate(format: "phone = %@", "12341234")
let query = CKQuery(recordType: "Entry", predicate: predicate)
publicDatabase.performQuery(query, inZoneWithID: nil) {
    recordsArray, error in
    
    guard let records = recordsArray else {
        return
    }
    
    for record in records {
        print(record)
    }
            
}

Saving and creating records programatically

Downloading data is all well and good, but what if you wanted your app to update the fetched records and send the changes back to CloudKit? Luckily for you, this is quite easy to achieve.
Each record is represented by a CKRecord object. It has the standard methods setObject:ForKey:, objectForKey, allKeys and changedKeys, you can use to update or add new fields. Once you're done with your changes you simple call saveRecord:completionHandler: on your CKDatabase object. If you've retrieved the record previously, any changes will update the version stored on CloudKit. If you've create a new record, a new entry will be created instead.
Interestingly enough, if you set values for keys that were not originally defined in your entry, they will be added to your entry by CloudKit. This is a nice and easy way to change an Entity without having to go through CloudKit's dashboard.
If this is all clear as mud, don't worry, we'll look at a simple example of creating a new entry in our ficticious phone book:
//1
let publicDatabase = CKContainer.defaultContainer().publicCloudDatabase
//2
let newRecord = CKRecord(recordType: "Entry")
newRecord.setObject("Sherlock Holmes", forKey: "name")
newRecord.setObject("21B Baker Street, London", forKey: "address")
newRecord.setObject("123456789", forKey: "phone")
newRecord.setObject("Consulting Detective", forKey: "job")

//3
publicDatabase.saveRecord(newRecord) {
    savedRecord, error in
    
    print(savedRecord)
    
}
  1. First we retrieve the database, in our case this is just the public database in the default container.
  2. We create a new CKRecord of type Entity and set the values for all the keys. Note that we've added a new key we hadn't defined in CloudKit's dashboard, that of "Private Detective".
  3. We save our new record, and if all goes well the callback will return the saved record.
We can now see our new record on CloudKit's Dashboard together with its new field, which is now available to all Entry objects.

Final words

We've barely touched the surface here. Think of this post as just the tip of the iceberg. As you can imagine, CloudKit has various notifcations so you can keep track of changes that happen in the cloud. CloudKit is packed with a vast array of features to do with security, multiple user roles and so on. Furthermore, 'CloudKit JS' provides a javascript API in case you need to use CloudKit from your webserver for example.
The idea of this tutorial is to show you the basic workflow so you can decide if CloudKit is useful for you. The bottom line is that CloudKit is a sophisticated BaaS run by Apple. If your app is exclusive for tvOS or iOS devices and it requires a fair amount of storage in the cloud, then you should definately check CloudKit out.