So I officially have RCFC 1.0 released (the phone app and the Python library). I’m really happy with how it turned out, and I wanted to share some of the lessons I learned along the way.
Lesson #0: Know your reasons for working on the side project
It is very important to be honest with yourself before you work on a project. Why do you wan to work on it? There are many motivators, be it money, fame, or experience, but be clear with yourself. For me, I wanted to see if I could solve a problem, but I treated this as a learning project. It was okay if I failed. I wasn’t planning on making money with it. I also wanted to see if I could build a reusable framework that others could learn from. I wanted to know how to build a phone app. I also was working on learning circuit design, and I needed a motivation to learn. This is why I worked on RCFC.
Additionally, recognize your constraints. You will not have a lot of time to work on a side project. So I wanted to put in some upfront effort to minimize ongoing maintenance. With RCFC, that meant that in order to update functionality, I only had to write a Python function, not update a web framework or phone app (Hooray open closed principle).
Lesson #1: Do your side projects in super small increments (you will get distracted)
Life gets in the way. Families, illnesses, work, other projects, community involvement; we don’t live in a vacuum. So continue to be honest with yourself and recognize that you can’t just hammer out your side project in one caffeine-fueled burst. Put in reasonable milestones along the way. For RCFC, first I wanted to build a circuit that could be controlled manually. Then, I wanted a web framework and to release my Python package. Finally I wanted the phone app. Now that I have that skeleton, it’s small feature request after small feature request.
The software engineers in the room are nodding, because this is the core of agile methodologies. Build small slices of value, and iterate upon that. I was able to run some ideas through my primary customer (my family), without spending large time up front. I could also constantly validate my progress along the way, which we will touch upon later. I could give up at any time, and know that I still had achieved something.
Lesson #2: It’s okay to get stuck, just keep asking for help.
I got stuck plenty of times on this project. I was new to circuit design, so I had no idea how to boost the range of my circuit from 2 feet to 12 feet. I didn’t know how to release a python package. I didn’t know how to write a phone app. I didn’t know how to do a lot of it. Don’t let that daunt you. Ask friends or co-workers. Ask Google. Get on forums or a programming Reddit. People are generally eager to help.
Only through perseverance will you get the answers you need. And only then will you grow. It’s also okay if you don’t fully understand things at the end either (I still have questions on my circuit design). You’ll have challenges to overcome, but not backing down from a challenge is one of the best skills to have in software engineering.
Lesson #3: Don’t do more work than you have to.
When I was working on RCFC, I knew I didn’t want to learn the inner workings of a web framework. I didn’t want to learn how to program my own IR receiver. I didn’t want to be bogged down from all the bells and whistles of a phone app. So I looked for ways to build upon the work of others. This was a learning project, but I wasn’t aiming to learn the world. So I used Bottle, a well known Python web framework. I used an IR receiver module and LIRC for the Raspberry Pi. I used Ionic to make phone app development feel natural and intuitive.
This doesn’t mean I won’t learn those other skills; now I just have a starting point to dive in from. Make your workflow simple, and only add complexity where you need to. Otherwise it is far too overwhelming to continue on. Also seek out the tools that feel easy. Ionic was one of the most pleasant developer experiences I had in a long time, and it was a complete reversal from working with Android Studio.
Lesson #4: If you see an idea you like, feel free to use it
It’s no secret that RCFC is heavily influenced off of the Bottle/Flask API. This is completely intentional. First, it provides a simple model to follow and guide design choices. Secondly, it is familiar to other people as well. I’m not saying to blatantly copy or steal, but ask yourself why you like certain things, and evaluate if they work for you. The simplicity of a decorated function, combined with the reduced overhead it provides, made a fantastic choice for RCFC.
Lesson #5: Design your user interface first (README-Driven Development)
When working on RCFC, I wanted it to be easy to use. I’ve really become a fan of README-driven development as of late, where you write your User Guide / README before you ever touch the user interface of your code. This gives you a chance to evaluate the simplicity, the intuitiveness, and the design of your API, before you write an ounce of code. It guides the choices you make through the rest of the codebase. This means that most decisions are framed in the vision of the core user interface, which also helps in maintainability. When understanding software structure, it is easiest to start from the UI and work your way inwards to observe flow, and if the code mirrors that intentional design, it is a much lower hurdle people have to understand your project.
Lesson #6: Provide ways to continuously evaluate the progress of your project
Before I ever had the phone app, I had a demo server that could hook up to RCFC applications and provide a simple web UI. It’s ugly, it’s compact, but it provided an early way for me to validate my assumptions about the project’s architecture. Even though this web UI is not the intended consumption piece, it gave me a way to test the application, while decoupling it from the actual phone application development. Fast feedback loops are important, and you don’t ever want to delay evaluation of what you are doing (see small increments).
This is another lesson I’m going to take with me to the workplace. All too often, we leave out debugging tools, diagnostics, telemetry, and other operational instruments in our code. We often suffer as problems arise too. Give yourself a window into your application, and use the information you gain to re-architect as needed.
Lesson #7: Continuously test your project
Most people who know me know that I’m a big fan of testing. I strongly believe in the benefits of unit testing, integration testing, acceptances testing, and just about every other testing stage out there. It’s so easy to skip out on tests for side projects. However, things like TDD aren’t a testing methodology; they are a design methodology that aid in refactoring. In the short lifetime of my project, I have already done a decent refactor, and unit tests were there to provide a safety net. I didn’t think I’d break them, but I did, and I’m glad they were there.
Also, one of the first things I did was set up a CI project under Travis, to make sure that my Python code could work with the nightly build of Python, in addition to 3.6. This actually caught a bug in my setuptools installation, and it let me know of problems before I ever deployed. I still need to put the phone app under CI, but because that contains some secrets (such as APK signing keys), I need to run that CI on a local server.
Lesson #8: Learn only one new thing at a time
I forget where I read it (maybe something from Pragmatic Programmers), but to paraphrase “Either build something you know in a new language, or build something new in a familiar language). I didn’t listen to this advice, and I paid for it early on. I tried to learn the Android development environment at the same time as learning the Kotlin language. I was quickly overwhelmed. I was facing a wall of XML, SDK function calls, and a whole new syntax. I couldn’t tell where my errors where, and it made it very frustrating.
I decided to back off eventually, and rather than moving to Java, I tried out Ionic. Ionic dealt with Angular and TypeScript, and I had played with those before. They also had a much smaller learning curve. I was able to build some simple web applications to learn that environment, and then I could apply that to phone applications. A project is a giant puzzle, and you can’t just solve it all at once. Find the first piece to lay down, and build off there.
Lesson #9: Automate the repetitive tasks early
You will work on your side project sporadically. This is just the truth of life. You will forget things in between working sessions. Automate whenever you can, because this serves as a way to document the workflows you adopted.
Here’s the code I have to run every time I build an APK to deploy to Google Play:
rm platforms/android/build/outputs/apk/*.apk ionic cordova build android --prod --release $JAVA_HOME/bin/jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore $1 platforms/android/build/outputs/apk/android-release-unsigned.apk my-alias $ANDROID_HOME/build-tools/27.0.3/zipalign -v 4 platforms/android/build/outputs/apk/android-release-unsigned.apk platforms/android/build/outputs/apk/RCFC.apk $ANDROID_HOME/build-tools/27.0.3/apksigner verify platforms/android/build/outputs/apk/RCFC.apk
There was no way I was remembering that every time I had to build an APK. So as soon as I figured out what I had to do, I put it into a BASH script. I used it no fewer than 8 times over the next two weeks, as I made errors and needed to redeploy. I cut down on the time I needed to learn (and relearn) these workflows. Automate what you can early, as you will almost always need to do it a gain.
Almost all of these tips I can apply to any project, but they are just as critical as a side project. If you don’t have some discipline while working on your side project, you reinforce that it is okay to revert to some bad practices, and that can leak into your professional life. You will also pay some price (as those good practices you are omitting are good for a reason), so I encourage you to treat your side projects like work projects, and keep these tips in mind.