Developer Experience: Native Applications
What I have noticed during my time as a mobile application developer, googling away for answers when I run into a weird bug, is that most resources out there just compare technologies – highlighting the pros and cons and providing quite objective information.
And while pros and cons are useful, I believe there is a much more human side to using this technology that isn’t explored often enough. More specifically, I am talking about the developer experience or DX.
How will these pros and cons impact my workflow as a developer?
What is the day-to-day workflow when (as in my case) undertaking an enterprise level project to deliver the same app for both native Android and iOS?
As a developer, I think it’s time we explore the more subjective side, dig deep into the human angle, and gain a better understanding of DX.
I am currently working on developing and delivering features for a native mobile application using Kotlin for Android and Swift for iOS. Drawing on this project, I will take you on a journey through my experience and highlight some of the interesting quirks and nuances.
The challenges of going mobile
For context, I started my career at Mudbath as a professional developer working on an e-commerce platform. This role really helped me get up and running with all of the industry-level standards, practices and terminology, especially coming straight out of university.
Going from a purely web development-based role to a predominantly mobile development role, felt very much like being thrown in the deep end for me and my newly-formed team.
The transition we experienced from web to mobile was quite similar to what you would expect when going from framework to framework in web. Each framework has its own unique challenges, architectures, ways to structure UI elements, styling, the list goes on. As a developer, you have to adapt and adopt a completely new way of working and solving problems.
Most web developers would agree that the ability to adapt and adopt is a core principle of being successful at what we do and a necessary skill if you intend to keep up with the very fast rate at which technology grows.
Another benefit of transitioning is it provides a whole new perspective on the customer experience and how technical problems, from common to complex, can be solved in a myriad of different ways. These insights help to make a frontend developer stronger and more empathetic to customer needs.
How do I run mobile applications locally?
Well luckily there are emulators.
I am using Android Studio and XCode as my development environments which provide emulators for most versions of Android and iOS.
iOS emulators and their integration with XCode is a lot better simply because there is a much smoother feedback loop during development.
Debugging any code change has one of the biggest impacts on my workflow. When it comes to debugging, if I’m using iOS emulators and want to set a breakpoint, I can do so freely and not have to worry about re-building the app again in a debug mode.
Sadly, this is not the case for Android emulators and Android studio.
Every time I want to test a tiny fix or use the debug mode, the app has to be rebuilt. This rebuild means downtime which is not the best for DX. Even the smallest amount of downtime is enough to disrupt the feedback loop. Debugging can disrupt my train of thought or flow, and slows me down.
Adapt to the CI/CD software lifecycle
Continuous integration and continuous delivery (CI/CD) and version control, while not mobile development-specific, actually has a massive impact on DX.
I am working on large codebases that are constantly having code go through the pipelines and that means sometimes things break. I actually think I spend an almost equal amount of time on tasks like making sure I am up-to-date with the main branch, as I do fixing failed jobs in pipelines and getting merge/pull requests ready.
Arguably that is where most of the development happens. It’s where your code, whether it be a new component or a bug fix, gets integrated into the main branch of the codebase that eventually goes to production.
How code fixes, pull requests and merging impacts DX
I have adopted the mindset that your responsibilities don’t stop when your pull request gets merged. There is more work to be done after you have merged that new component, or that bug where the call state wasn’t updating. This extra work is crucial, especially on larger codebases, and it impacts your tasks and you.
Your time estimate might need to be adjusted to accommodate this or your entire priorities might need to shift because tests are failing in the pipelines. As the developer, this could mean context switching or suddenly pivoting to a new task which I have learnt can sometimes make or break your workflow.
Understanding the Impact of language
Alright, let’s jump into something a bit more meaty. Let’s look at the programming languages that drive mobile apps, Kotlin and Swift.
The predecessors to these languages are Java and Objective C respectively. I can’t comment on Objective C, but Kotlin feels so much nicer to use compared to Java.
There is a strong sense of comfort and familiarity when I use Kotlin. I remember from my university days, writing getters and setters and all these classes that represent the data more than the actual logic that drives the application.
Kotlin’s type and null safety feature set really enables a developer to get right into the nitty gritty logic without all the ceremony that comes with Java, and in some cases just extra boilerplate-like code, for example, ‘if statements’ to check or guard if a value is null at the start of a function.
It pays to know your jargon
The programming language your code is written in really effects its readability and is another interesting piece of the developer workflow that affects DX.
The keywords and the language really change the way you view your code and even talk about it to your teammates. Some words have very specific meanings and connotations to different people.
As an example, Kotlin chose 'when' as the keyword for switch statements. When I see this keyword, it changes how I view the logic it encapsulates. It says to me that when these conditions or expressions are true, here are the branches or paths I want to execute.
To me, the word 'switch' has the connotation of switching or toggling between different states or conditions.
Let’s take an example from Swift. The keyword 'guard' is used when you have an expression that you need to be true, for the rest of the logic in a function or code block to execute correctly, otherwise exit the function.
'Guard' is such a strong word and really signifies to you, and more importantly, to other developers reading your code, the critical nature of that expression and the connection it has to the logic in the rest of the function.
With these two examples it’s clear that the language and choice of words we use to write our code, how we work through logical problems and even how we communicate our code or logic to others, can really have an impact on the day-to-day DX.
If you would like to see more examples or just more Kotlin or Swift, Kyle Ohanian did a great job at capturing the subtleties of these languages in his article Swift and Kotlin: The Subtle Differences
Jump head-first into mobile app development
By sharing our experiences, we can all learn and grow. In this case, I hope my experience has given you a window into my challenges and transformations, the more human side of software, and the impact these technologies have on product, users and the software developers who build them.
Maybe I have given you a new perspective on your work, piqued your curiosity or even better, inspired you to give mobile development a go. To that, I say great, good luck, go get em!
If I have scared you away, I encourage you to keep looking around, do some more research, get a mentor… and just give it a go. Start on something small and manageable – learning new things is the key to growth – these technologies may surprise you.
Go big. Go bold.