I build a thing. Again.
Chapter 1 — The thing.
It’s called Futurospective and it’s most likely going to be useless for you, but it’s an experiment for me. Basically it lets you record message that will be available to yourself in the future (like a timecapsule).
Why? Well, I tend to always write bucket lists on pieces of paper and lose them soon after. Sometimes I find an old one and this happens:
“Wow, I forgot about that.” —Me, reading bucket list in old notebook.
So I decided to try something. What would happen if I were to use a better medium (my phone) to record my current thoughts and make them available to me in the future.
It would be video only to maximise awkwardness, and I could chose to record something that would pop up in 3 or 6 months and I could tell my future self to not forget some very important stuff. Exhibit A below.
“Hey Sten, your second baby should be born by now and you’re probably sleep deprived. It’s gonna be alright, just drink lots of water and stop watching Netflix. Also be super kind to N. (When is the last time you bought her flowers?) Also don’t forget to give T. lots of cuddles.” — Me, recording a time capsule to future self in 3 months.
Anyway, you get the gist of it. And you too can install and use the app if you have an Android phone (I’m waiting for Apple to approve the iOS version). But I also built this app because I wanted to get a better understanding of React Native (RN)and this is what I’m going to talk about in this post: 38 days of building software.
Chapter 2 — About me
Before I dive into the lessons learned I feel like we should get to know each other better. Or at least it’d be worth telling a bit about my background so that the rest of the post makes more sense.
- I dare say that I’ve got some pretty good experience working with teams to build stuff as I spent 6 years at Atlassian as a Product Manager in Dev Tools (Bitbucket, Bamboo, FishEye / Crucible) — this will be relevant to my comments on managing stories and time.
- I wasn’t full time on this until August 1st so take 37 days with a grain of salt. This may explain some of the grinding happening at the beginning of the project.
- Prior to this project I built a couple other RN apps but it was more copy/paste/assemble code rather than having a good understanding of what was going on.
- I’ve got a 20 months old baby boy. He’s very cute 👶🏼. And a great climber too 😨.
So, this is the experience of an average developer who’s quite familiar with building software.
Chapter 3 — App architecture
Let’s talk about the application itself.
For the MVP I kept the application quite simple: no user account, all the data is saved on the phone, no sync with a remote server. From a technical perspective it’s a plain app that lets you record with the camera and notifies you from time to time to let you know that a video is available.
- Built with React Native v0.46.4 and React v16.0.0-alpha.12.
- Records video with React Native Camera.
- Plays video with React Native Video.
- Using Realm to store data.
- Sending push notifications with React Native Push Notification.
- Vector icons provided React Native Vector Icons.
- Sending usage analytics to Google via React Native Google Analytics Bridge.
Futurospective is by no means a complex application, however it wasn’t that easy to get there. And this is why I believe it’s worth writing about that little journey so that others can benefit from my experience.
I’ve also made the code open source so feel free to have a look at the source and make contributions.
Chapter 4 — The good, the bad, the ugly of React Native
React Native is awesome! I’ve been seriously impressed with how far it got since the last time I had a look at it (October 2016).
The exact same codebase is used to produce both the Android and iOS applications while using complex components such as the camera and push notifications.
The other issue is not exclusive to RN, but more an issue with the JS community and the pace of innovation there. It can be sometimes challenging to read code on the web if you haven’t kept up with the latest evolution of JS.
As said above I’ve been a Product Manager for the past 6 years and while I was quite aware of the new global trends in software development I was only keeping a loose interest in JS best practices — learning new things when glancing at our front-end code.
So at the beginning it would take me a bit of time to parse code written in sample repos, Stackoverflow or in tutorials because it was never the same structure.
I need to reiterate here that I really love React Native and I think it’s a game changer for people like me, allowing to see ideas going live in a matter of days, and being able to reach both Android and iOS users easily. So there’s no hate here — none. But there are some stuff that are really hard.
It’s probably me but I haven’t figured out what’s the best way to do end-to-end testing for my application. There are great guides out there for snapshot testing but I couldn’t really use it as RN 0.47 uses an alpha version of React (as I’m writing this) and it doesn’t work with Enzyme, a library required by most of these testing guides.
Everything was good until I started using the camera. The iOS simulator doesn’t let you use the camera so I had to test on the devices themselves to understand what was going on. That lengthens the feedback loop a lot when coding.
Then I installed Realm to store data and run into other sorts of issues as Realm would not work with Remote Debugging on. So sometimes I had to connect my laptop wifi to my Android phone as an access point to be able to see the RN logs.
Publishing the app.
RN and RN documentation is awesome to get you started but not so much at helping you publish your application to the Android Play Store and Apple App Store.
To be faire this is because publishing apps on stores is a really sad process, especially on Apple. It’s a real paradox to see that UX and design are now a huge part of creating apps — but the very tools that help you deliver a better experience to your customers have some of the worst UX out there.
Chapter 5 — Some lessons learned, some tips
This is going to be messy. Some of the things I want to write about are about React Native itself, but some others are more generic advice about coding a project by yourself.
Chapter 5.1 — Start with user stories
It’s very tempting at the beginning of a project to jump straight in the code. We talk so much about how stories, boards and planning for teams that we sometimes forget that even individuals can benefit from it.
The board that I’m using is public and I try my best to write stories that embody user behaviours rather than being specific about buttons, UX, or implementation details. Of course there are a few exception where I stuffed up but believe me when I say that it was much easier to work when I had well detailed issues to work with.
Chapter 5.2 —Check what version of React is used
I’m sure that the RN team had a lot of good reasons but the fact that React Native 0.46+ is relying on a alpha version of React (16.0.0-alpha.12) has caused me a lot of grief.
It began when I struggled a couple of days to implement automated testing with Enzyme. At first I thought that I was missing something, that once again I failed to understand how RN worked and that I must have misconfigured something. Then I discovered that it wasn’t me, it was an issue with breaking changes between React 15 and React 16. Then I thought I fixed it. Then I gave up on automated testing.
From that point on I always had to double check when I was running into a bug. Was it me? Was it the library? Dilemma, dilemma… After a while you get familiar with the stack trace and can guess what’s what but in the beginning I was pulling my hair.
Chapter 5.3 — KISS, don’t optimize early
If, like me, you’re new(ish) to the whole React/Redux thing and you also have to get your JS knowledge up to date then take it slowly.
I read a lot of guides and repos to understand how to best structure my application:
- Facebook F8app
- Organizing a React Native project
- 11 mistakes I made during React Native / Redux development
More often than not the code I was reading was one of an application already in a fairly advanced state and I spent a lot of time trying to get my head around multiple different patterns and directory structure for my reducers, actions, config, etc…
Everything went much faster when I started to keep the code of my reducers, actions, etc in a single file and wait to feel comfortable before splitting everything in multiple files.
If you look at the tree of the src/ directory today (August 18th) you will see something far more complex than how the code was at the beginning of the month.
The lesson learned here for me was to realize that looking on the web for examples would 80% of the time show me a structure that was for people that were already getting it.
I stopped trying to overthink stuff, and focused my efforts on making my code clear and clean so that I could easily refactor it later.
Chapter 5.4 — Read Redux documentation in full
That’s most likely obvious to you and to most people but I went a bit cowboy, thinking that I’d get it by trying.
Redux has a great website with clear documentation and a very good example to illustrate how it works. You’ll save a lot of time by doing nothing but reading it all.
Chapter 5.5 — Use static type checking and linting early
This is a follow up on 5.3 above. As I’ve repeated many times I don’t have any test on the app — not because I don’t want to, but because of broken dependencies. On top of that manual testing is also tedious due to the use of native components and libraries that don’t play too well with remote debugging on Chrome.
So, fairly early in the project I decided to adopt Flow for static type checking and ESLint as a linter. Chances are that you won’t see the benefits at the beginning if you’re not familiar with strong-typing. It’ll feel a bit heavy handed to annotate all your variables, and you might struggle with some edge cases. But soon after you’ll reap the rewards as you start refactoring your code.
I’m not sure which guide I followed but this one will help you setup ESLint highlighting in Sublime 3: http://jonathancreamer.com/setup-eslint-with-es6-in-sublime-text/.
Linting will also help you keep your code clean as it can quickly identify unused code that can be removed.
Chapter 5.6 — Commit early, and often
I’ve been in situations where I’ve done a bunch of small changes, forgot to commit and then something breaks/toddler needs attention/<insert distraction here>.
This is super painful because I lose track of what’s been done as my files have multiple unrelated changes and it can take a significant effort to understand what I was trying to do.
Now I commit really often because I don’t trust myself anymore. And sometimes I write fairly long commit messages even though I’m the only dev.
Writing long messages has 2 great benefits:
- It helps me assess what I’ve done and what’s left to do — instead of keeping it all in my head it gives me clarity to write it down in a commit.
- It gives me confidence that I’ll be able to get back on the project even if I need to put it on a long break.
Chapter 5.7 — Test on both devices early, and often
React Native is really good at providing the same behaviour on Android and iOS from the same codebase. However there are some minor differences that can be a bit tricky to solve so make sure that you regularly try both devices whenever you complete a significant milestone, or after installing a new library.
For instance (as far as I remember) I couldn’t debug remotely with Chrome using my iPhone with Realm DB but I could do so with Android by using my phone as an access point. It would suck a lot to go really far down the implementation on one device and then realize that a library is not compatible with the other type of OS.
Chapter 5.8 — React Native Camera issues
- You won’t be able to use the simulator to test. You need to test it on your mobile.
- It’ll require some mocking with Jest (but I don’t have tests so can’t give you more info)
- Make sure that you have the right permissions set in your info.plist to be able to use the microphone.
- I remember struggling to get audio. I was setting up captureAudio=true in the <Camera /> component but I also had to add audio: true in the camera.capture() options.
Chapter 5.9 — Realm issues
Realm is amazing and great to use, however it’ll give you debugging headaches as it prevents remote debugging from working when testing on devices.
I’ve said that a few times in this post but I managed to work around this by using my Android phone as an access point for my laptop. It seemed to solve the remote debugging issue and then later on I did a mix of using react-native log-<platform> and switching between platform.
Chapter 5.10 — Publishing to the App Stores
First, chances are that you’ll need a splash screen and icon. Spencer Carli has written a great tutorial to add a splash screen to a RN app. I’d recommend being super careful with this and to upload images to your Images.xcassets one by one while double-checking the sizes. There’s an excellent Stackoverflow answer that might save you hours if you’re struggling with this.
Second, if you have never published an app to the app store then brace yourself and grab a drink. Everything until now would have been a breeze.
I’d recommend starting with the Play Store as it’s an order of magnitude easier than publishing on Apple App Store and the approval process is also faster.
Chapter 6 — Open source all the things
Far out that was long. Thanks for making it to here.
I’ve decided to make the app open source because I’ve benefited greatly from a lot of free things that I’ve been built by others. So it’s my turn to give back and while I don’t think that many people will find it useful I’m hoping that some will benefit from looking at the code to see how some stuff are done.
Please don’t hesitate to ask me any question about anything.
- The website: https://futurospective.bitbucket.io
- The source: https://bitbucket.org/futurospective/futurospective-mobile
- The Trello board: https://trello.com/b/DUJyeAIF/futurospective-planning
I’ll try to write more stuff about specific dev issues in the future.
PS: You probably found some typos but I have to go pick up T. at school. I’ll proof read later.