Stub driven mobile app development
For the last month I’ve been developing an app that relies heavily on a server-side API. The whole process was a mess. This is what a typical morning looked like: I would start working on a feature in the UI, realise I have a bug in my network layer, patch it up, continue working on the feature, realise there’s data I need that’s not in the server response, tell the backend guy it’s missing, have lunch, then forget what I was doing because I’m working on five things at once! That is no way to live.
So I got an idea. Why not just make a stub backend. That is, make a fake version of the service your app relies on, before you even start working on a single feature. If your app relies on some sort of server-side API to fetch data, write a class that will give you stub data. Make that class implement an interface, and then make the rest of your app talk to the interface.
I probably spent about 20% of my development time of this app going trough the whole flow of the app until I get to the point I want to test, just because that’s the way our backend is set up. Had I worked with dummy data and stubs from the beginning, I would have been able to test each part of the app separately and have complete control over the whole process.
Overhead doesn’t always mean slower. Construction workers working on your building would sure as hell have a harder time without their scaffolding. In this case, the (usually small) time it takes to write a dummy network service is minimal compared to the amount of time you’ll be waiting for your backend team to fix a server-side bug.
A programmer coding at full throttle is keeping zillions of things in their head at once: everything from names of variables, data structures, important APIs, the names of utility functions that they wrote and call a lot, even the name of the subdirectory where they store their source code. If you send that programmer to Crete for a three week vacation, they will forget it all. — Joel Spolsky
This is a real thing. It means that humans are more efficient at working on one thing at a time because it takes us time to get used to new ways of thinking. Constantly switching from working in your network layer to writing a new feature in the view layer means you’re always in that ‘getting started’ phase.
Define functionality early on
Crash Early — A dead program normally does a lot less damage than a crippled one. — The Pragmatic Programmer
This is a popular saying in programming. But it doesn’t apply to just design — it also applies to the whole development process. You want to define your architecture as early as possible. And then, no matter how good you are, you will have made a ton of mistakes. This is why you start with a stub and make your app around it. This will show you the shortcomings of the way you’ve designed your app early on, and give you the opportunity for very easy change.
If you set up your architecture correctly, (layers decoupled from one-another and using interfaces for communication) your app won’t actually care whether it’s the server or a class from its own bundle supplying the data. So, your backend team can work on their end, and you can work on yours, and when it comes time you just join forces.
Makes you think of future changes
Software development is a whole series of changes. The whole point of using an SVN is to track changes. So, you want to make changes as easy and painless as possible. Using stubs will force you to design your architecture in a way where you can change the underlying model and network service without having to change your UI layer. This will make your life a lot easier down the line.
Sets you up for UI testing
UI testing is a huge pain in the ass. But it’s also a huge lifesaver. Using stubs will make your UI tests run much faster, and you’ll have much more control over them.
- Make an interface (protocol) that the object (only one object) that will talk to the server should implement.
- Make an implementation for the happy path (return dummy data, process requests with the correct response, etc.)
- Make an implementation for the sad path (return no data, junk, incorrect responses, etc.)
- Create your app. Never talk to the implementations above directly, always use the interface.
- Switch between the happy and sad implementations to check if your app handles both correctly.
- When you’re done with the app, create your real network service.
- Wohoo! 🎊
Enjoy your stress-free development process!