How to approach complex programming problems
Some tips and approaches how to tackle difficult problems. Including examples from my Chill Zones app.
In this post I would like to present some tips about how to "attack" complex problems. Maybe when you have a cool idea for an app but it seems way too complicated and you don't know where to start.
I am going to use my app Chill Zones thorough this post as an example. To hopefully better illustrate my points.
Start: can it be done?
When I got the idea for Chill Zones I knew I wanted a way to play custom screensavers on Apple TV. This was inspired by the tens of apps for fireplaces and aquariums and I thought people would welcome the option to create their own. Because I did some small stuff with tvOS (the OS of Apple TV) in the past, I knew there is no local storage for the videos. So they would need to be streamed somehow. I considered building my own backend but that would be time consuming and the amount of space could be costly in itself. Then I remembered CloudKit framework.
So the question "can it be done" slowly became "can it be done using CloudKit?". I never really worked with CloudKit that much before and had no idea how to connect iOS and tvOS apps. But I also knew that some worked this way and based on that it seemed it should work.
Tip: I really encourage you to open Apple Documentation and just browse around and see what stuff is available. Give it at least 30 minutes. The point is not to learn anything specific but to have broad overview of the APIs available for you to use. For example you may discover that there is
PDFKit framework which makes displaying, rendering or even editing PDFs pretty easy compared to doing this manually. Or you may stumble upon
QuickLook framework which has ready-made controller to preview various types of files. And lots more stuff to solve various common problems.
Start with small part of the core functionality
When I started working on Chill Zones, I knew that eventually the iOS app will have a way for users to import videos, possibly edit them, they will be shown in table view etc. But I also knew that I already know how to implement these. So I skipped this, added demo video straight to my project and started working on uploading it to iCloud with CloudKit. The rest could wait.
After successful upload to iCloud (validated with the CloudKit Dashboard), I could move to tvOS version. Once again, I skipped the UI part and started implementing code to read stuff from CloudKit. I also found out that playing video straight from iCloud URL does not work, so I used available cache directory and that was it.
This was the first prototype. It had no UI, the code wasn't polished, but the core of my idea has been implemented and I knew that it could be done and I can invest time to build the UI and all the extra stuff needed. Starting with the most difficult part can seem daunting but it also lowers the risk that you spend too much time on an idea that can turn out to be too complicated for just a hobby app and then you risk throwing away fully working UI.
Split things into small chunks
Playing user videos from iCloud in a smooth loop sounds like hard task and it is. However if you split it into smaller parts: Letting user select a video, uploading video to iCloud, loading video from iCloud and finally playing this video and implementing looping, then it does not seem that hard and if you get stuck implementing one thing, you can move to another.
This is another approach I tend to use and that is to develop these parts separately. So for example when figuring how to upload video to iCloud, it does not make sense to implement the selection from library and then have to select video each time you test your code. If you have demo video in your project, you can just load it like regular file and try upload that. The user selected video will work almost the same later once you have the parts finished and can tie them together.
I tend to use to-do manager a lot (I have Things 3 which is wonderful) and these small parts are great to-dos, that can be done in reasonable time and checking them off will give you boost to continue. Or at least for me it does 🙂
Is something really difficult? Think whether you can avoid it
For example, when I started Chill Zones I knew that since the videos will be played in a loop I need a way to make the transition smoother otherwise even with steady hands there is visible "jerk" when the video finishes and starts playing again. At first I started digging into
AVFoundation and experimented with creating custom cross-fade effect to smooth the looping.
This was really difficult. So I started thinking about ways to avoid it and realized that I can "simulate" this cross-fade effects with two video players on Apple TV. This also had the benefit that I would not in any way edit user's video and can tweak this smoothing in updates. Whereas if I used the editing approach, any subsequent updates would not apply to already uploaded video or require extra work.
Don't be afraid to reduce scope
Coming up with new ideas what features to build is easier than actually thinking them really through and building them. If you feel like you are getting overwhelmed, try cutting out features that are not the core of the app. You may discover that they aren't needed at all. In some cases you can wait and see whether users will ask for them. There is a popular quote about shipping software and it is something along the lines that if you aren't embarrassed by the first version of your app then you waited too long to release it.
For example, I created iPad version of my document scanner app Scan it a few months after releasing an iPhone version. I created new main screen and had no idea how to smoothly incorporate search feature into the tablet UI. So I didn't and I am waiting to see whether people miss it.
Thanks for reading! I don't have any kind of analytics so I have no idea how many people read this. If you like the post, you can let me know over at Twitter.
Do you have your own tips? Let me know!