Posts in Work methods (22)
As an app developer, a question you are very used to hearing is "how much does it cost to make an app". It's also a question you quickly learn to dread. Why? Because providing an accurate fixed price for designing and developing a mobile app is next-to-impossible. Worse, comparing fixed-price quotes from different companies is misleading. In this article I'll explain some of the reasons why, and some better ways of pricing and organizing app development that we've found.
There are too many unknowns
How much an app costs depends on a large number of factors, many of which are unknown at the start of the project. We can try to minimize these unknown factors. We will always clarify which platforms and OSes it makes sense to support, what screen sizes, what features are essential and what are "nice-to-have". It's much harder to figure out how many iterations it will take to make a game fun, or to make a logic screen intuitive to use, or how long a vague feature like "add sharing" will take. Developers have to add in extra "padding" to cope with unexpected additions that occur as a normal part of development.
Changing your mind should be expected
When making an app, changing your mind is good. Iterating on an idea as it undergoes design and development leads to a far better outcome. But if the scope has already been precisely defined in the contract, this may not be possible. As of 2014, the app industry is rapidly changing. A business model which worked six months ago may not fit user's needs or market trends any more. To keep ahead of the game, you need to be willing to change things, and to pivot on your original vision.
All developers are not alike.
A popular metaphor is to compare asking how much it costs to make an app with how much it costs to make a car. A car could be very cheap, if it is simple, mass-produced and uses low-quality components. Or it could be complex, hand-crafted, unique and incredibly expensive.
If you give the same request to multiple developers and get very different pricing, what does that really mean? Why is this developer so much cheaper? Are they low-quality? Why is this developer so expensive? Did they misunderstand the scope of the project? As a client, how can you be expected to tell?
Apps are never "done"
The car metaphor has another problem. Because if you're building a car, you generally reach a point where the car is "finished". With apps, it's not so simple. It's important to get real users using your app as early as possible. So you typically want to do a "minimal viable product" release as soon as you can, and development work should not stop when you reach your v1 release.
As soon as people get their hands on your app, you'll get user feedback you want to incorporate into your app. There's always new features to add that didn't make it into the first version. You might even need to "pivot" how the app works, or change the business model from paid to freemium.
Even if it's not visible to the end-user, you may need to add analytics, email reports or dashboards to keep track of how people are using the app. The app needs to be marketed, perhaps ported to another platform. If you burnt all your budget developing v1, you are in trouble!
Fixed price projects: riskier than they appear
So, to summarize, the disadvantages with fixed-price contracts include:
- • It's hard to know in advance how much work an app will take
- • Developers often "pad" their quotations to account for unknown issues
- • Different developers will have different standards, so comparing quotes is hard
- • It's difficult to add in extra functionality, reorder or change functionality once the contract is signed
- • It suggests that there is a cut-off date where the project is "done", which is not realistic or recommended for most apps
At ReignDesign, we've recently started taking a more "agile" approach to estimating projects. Agile Development started in the software world, where it describes a way of planning software development projects which embraces the frequent changes that occur, rather than fighting them.
A backlog of features
The "user stories" to be performed are arranged in a backlog, which the product owner or client helps to reorder into a priority list. When new stories (things you want the app to do) are added, they are simply slotted into the backlog in the appropriate place. The developers then work down the list in order, in a series of typically 2-week long "sprints" they commit to completing the items on the backlog.
Applying agile to project planning
It turns out what works well for development can also work well for pricing of a project. Once we move away from a fixed-price model, the question is not "how much would it cost to develop this app", but "how much can I commit to developing this app, per month". When we move to a "agile retainer" style model of project pricing, the typical issues of project planning are turned on their head.
First we recommend a monthly budget to the client, based on their needs, the complexity of the project, and approximate dates for releases. We ensure the budget is sustainable, to make sure the client can afford to keep working on the app for at least several months after launch.
We then calculate how much work the developers and designers will do each month for that budget. This will allow us to estimate delivery dates for different stories, but these are advisory only. If it turns out we complete tasks faster than expected (in agile-speak, our "velocity" increases), we may be able to deliver features earlier. If the client requests certain extra features be added urgently, other items will get pushed down the backlog and delivered later.
Overall, an agile approach allows the client and the app developer to work in a way where their goals are aligned, and much better reflects the actual effort involved in creating and sustaining an amazing product on the App Store.
But, does it work in practice?
That's the theory: but does it actually work in practice? I asked two of our recent clients their thoughts on the agile retainer method.
We've been working with KindyNow for the last six months. KindyNow is a mobile app for childcare centres in Australia.
Parents who use the app can notify their daycare centre of last minute cancellations, immediately triggering an opening for other parents wishing to book the same space. We built the first version of the app on a fixed-price model but then switched to a retainer, which has allowed us to develop features in a faster and more flexible manner.
Here's Sean Collins, CEO of KindyNow: "Technology developments evolve at a greater rate than you will anticipate. Having a fixed fee each month allows us to prioritize and manage the work flow coming in. We can focus our attention on the right projects each month without being hit with constant quotes for specific jobs. The fact is by the time the first version is built you’ll have so many new ideas that your fee structure needs to allow for this constant evolution."
We've also been working with Peter Stoyles of Tasklinks, building a new version of their productivity tool from the ground up.
We discussed several methods of collaboration with Tasklinks, and decided that an agile retainer was the most effective way of building this app.
Peter: "Initially we were focused on getting a set price for the scope of work required, as the customer you feel safer that costs won't spiral and you have some budget security. The agile retainer model flies in the face of this conventional thinking but there are clear benefits. The first benefit is the retainer gives you a clear project outline, you can see the work in progress and are constantly in contact with the development it is no longer a remote process. The second benefit is as the app develops you can change the build feature priorities. This gives you more control over the development and can allow you to adapt quickly to market changes and user feedback.
To our surprise and to the credit of ReignDesign the development process has actually been ahead of schedule and we are now in a position to develop and include more features ahead of our target release date. It is very important that you work with good developers such as ReignDesign who have a good understanding of your expectations and can guide you through the development process, with that in mind I would recommend the agile retainer."
App: Sparrow (desktop) / (iPhone)
Price: $10.99 (desktop) / $2.99 (iPhone)
Why we like it: Light email client with a polished and very compact twitter-app-looking interface. It integrates with dropbox allowing you to automatically upload attachments just by drag-&-drop on the email body. The attachment then is replaced with the dropbox download link.
It's common to use a centralised "Constants" class where you gather together lots of constants for your app. For example, in Objective-C you'll often have a big file Constants.h full of lines like this.
- #define DEBUG_MODE NO
- #define APP_URL @"http://itunes.com/apps/mycoolapp"
- #define CHARACTER_ANIMATION_TIME 2.0f
- #define FOOTER_IMAGE @"mycoolapp-footer.png"
- #define FONT @"Helvetica-Bold"
Don't do this.
1. It increases compile times significantly. Because lots of other classes depend on Constants.h (it's common to include it in the .pch header file so all files have access to it), any small change to Constants.h means that every class in your application will need to be recompiled. And ironically, during development at least, constants are often variable
2. It makes unit testing more complex, adds additional dependencies and discourages re-use. Because many classes depend on Constants.h, its harder to test them in isolation. Moreover, you can't easily transfer classes between projects, without manually checking which parts of Constants.h needs to be copied too.
Instead, it's much better to place constants in the class which they are used in. If you have a true need for a global constant, but it is for a value which you might want to frequently change during development (such as the DEBUG_MODE boolean above), consider using a macro to load the value from a config file, for example you could define a key in the Info.plist:
- #define DEBUG_MODE ([[[[NSBundle mainBundle] infoDictionary] objectForKey:@"APP_MODE"] isEqualToString:@"DEBUG"])
Next time you need to transfer a file between computers and are about to reach for a USB flash drive, think about the following two cases. If either of them matches, you have an alternative! As icing on the cake, you can use either method whether you are on a Linux, Mac, or Windows-based system.