I suspect one of my limitations as a programmer is that I don’t hack. I don’t beat away at something until it works. I read things, and I reason about it, and I write a lot of tests.
This makes me very effective on platforms I’m familiar with, but I worry I’m as a result not as effective when I’m picking new things up as someone who will just hack away. I’m searching for the moment when things start to make sense.
I’ve done some Android over the past few years. I really wanted to learn it, but when I started working on it, it really wasn’t that fun. It was an over-engineered codebase, and as I tried to find my way in it, the feedback I got in code review was often of the “I would have done it differently” variety. Often that way didn’t even work, so that was… rewarding.
The first breakthrough was that a lot of stuff is just more work than iOS. For instance, if you want to take a photo on iOS you just like… launch the camera and implement the delegate.
If you want to take a photo on Android, you mount the hard drive, allocate space for the photo, launch the intent, and handle it returning. I always thought managing hardware and memory was a job for the Operating System, but what do I know about Operating System design, anyway.
Aside: as I learned this lesson one of the guys I worked with told me that I must be wrong about how annoying it is to take a photo on Android. Then – once I had got it working – sent me a code review of his from a previous project and said (I paraphrase) “that is the right way to do it actually, because that’s how I did it too”.
So I returned to Android this year with a degree of trepidation. I really wanted to be better at it, but based on what I’d learned so far about it, mainly I was happy in Java and I’d learned maybe how not to do some things, but as I’ve commented before, that doesn’t always teach you that much.
Last week was the ~2nd week this year where I was able to focus on Android and things finally started to click. It was so exciting, because now I feel like I can pick up small bugs here and there, whereas before I felt I needed minimum 2 days to make progress. It’s like going from navigating with a compass to having a compass AND a (slightly fuzzy) map.
The big thing that clicked was understanding the ways in which the platform encourages bad design.
On iOS, that thing is mixing View Code and Control Code. The more tools I add to my arsenal to handle that, the better architected my iOS apps became. There’s another area of mixing model and persistence code. Really on iOS the design problem is mixing things that would be better separated. Learn that, make an effort to keep things apart, and everything seems more possible.
On Android things are very separated. This is not a problem you run into. The view is defined in xml. Any background processing work needs to live in a “service”. In fact on Android separation of things goes so far the other way, that the problem is state. When you rotate your phone, the activity gets recreated. So if you have anything with state, you need to save that state. If you have anything that might be happening in the background, you need to handle getting the same service.
- I don’t even know how you would get a stateful Android app working without Dependency Injection (luckily I had Chiu-Ki to help me with this, because it’s tricky).
- This encourages the use of Singletons (ai!) because it’s an easy way to make sure you get the same service when the phone is rotated.
- Automated dependency injection is nice and good for testing, but it can allow you to have very complex object relationships. I don’t see it as some panacea for good design, more as a something that obfuscates bizarre things you have done.
This is an app I’ve been porting over from iOS and it’s fascinating to me what’s different. Some things were easier, and some things were harder. But, Android makes a lot more sense, and I got things working enough to send out a beta, so that is exciting.