Thoughts on Flutter vs. Native App Development
During the last 10+ years that I’ve built mobile applications, there have been many different cross-platform or even “no-code” solutions to build mobile apps. React Native, Appcelerator Titanium, Adobe Cordova, Ionic, Xamarin come to mind. I have built production apps with the first two, so I have extensive experience with cross-platform systems from the past.
Now, there’s a new kid on the block by Google, called Flutter. Recently I have dug into this technology a bit deeper and I must say, I’m pleasantly surprised. Flutter is a really nice technology that enables developers to build apps for different platforms. It’s declarative way of writing user interfaces and a hot reload functionality make app building fast and convenient for the developers. Compiled apps perform rather well under the thumbs of users.
Developer community seems to be growing quickly and Flutter evangelists are emerging.
I’ve also noticed that Flutter and Dart expertise has become quite sought after in the recent year or so in the job market.
All this suggests Flutter is the way of the future for mobile app development. This might very well be the case. However, many cross-platform solutions have already tried to become dominant with this approach, but have failed.
In this article I’ll try to point out the main reason, why under current circumstances cross-platform systems can not compete with native app development approach.
First of all, let’s see, why cross-platform approach is so appealing.
Why is cross-platform?
We’re living in an age of two strong competing mobile platforms – Android, developed by Google and iOS, developed by Apple.
Android apps are built natively using Java and/or Kotlin programming languages. iOS apps can be built with Objective-C and/or Swift languages.
When building an app natively, with a desire to nail both platforms, one has to actually program two apps using their dedicated languages. There are very few programmers who can code natively for both systems, so app producer will have to hire at least two people to launch their app(s). This is where cross-platform development comes in.
One programming language needed.
Cross-platform solutions enable developers build software from one codebase targeting many different operating systems.
Build once, deploy everywhere
With cross-platform systems you can build an app core that will be used for both iOS and Android without coding duplication necessary. As both of the platforms are somewhat different, you can additionally write platform specific code on top of the core as well.
When done, the system will compile an app from the high level source code and will translate the code to platform specific code that is readable and executable by the target operating system.
What’s the reality?
From the looks of it, cross-platform solution seems to be a really smart idea, doesn’t it? Producers can hire people with skills in only one language. Less people needed, means that app development is cheaper and faster.
In reality however, these “magic” solutions do not seem to be holding up and many development companies have noticed that during the years a cross-platform development will become even more expensive to feature-develop and bugfix than their native counterparts.
It ends up being more expensive
In practice, many companies start with cross-platform approach, launch their apps, and then in time (2-3 years) will start planning strategies to redo their apps in native technologies. Some of the reasons for that are as follows:
- technical debt. It’ll be hard to find people who want to touch the code for further development
- performance problems. As there’s more code to compute through, app performance is decreased.
- long compile times. Because of interpreters and underlaying large libraries, the compile times for the app are increased significantly.
- very specific system for coding. As time goes by, the third party becomes slower to update it’s libraries
- some bugs become impossible fix due to another set of bugs in the underlaying library
- specific device capabilities lack support. The system doesn’t or is slow to support all technologies introduced to modern devices. Especially when new devices are introduced.
These reasons make further development, keeping up with operating system updates and bugfixes much more expensive than they should be.
What seemed to be an easy way out, will actually swallow more time and money than expected. Probably even more than it would if native technologies would have been used
Why cross-platform solutions can’t surpass native mobile development?
In its essence, the goal of computer programming is to control complexity. It means that the goal of a software engineer is to figure out the most logical and simple way to make software do what users want.
Actually not only users, but also other developers who have to work with the same codebase simultaneously or after him.
With that being said, it’s a logical conclusion, the the less building blocks a software application has, the less complex it is.
With cross-platform it’s easy to do simple things, but very very hard to do complicated things.
So let’s imagine building blocks of both, native and cross-platform app from a birds-eye view:
- The device. This is the hardware that an app will need to operate. Either an iPhone, iPad, Samsung phone, or other tablet. Nowadays Mac computers, AppleTV and Android TV boxes have been thrown to the mix.
- The operating system. This is either iOS or Android. It’s a software that is making device do what apps ask it to. Be it display colors and characters on the screen, or exchange data via bluetooth or wifi, or even locate the phone itself using a gps antenna.
- Software application. This is the actual app that is being programmed by an app developer. To ease up app development, several libraries can be used (either from the operating system, or third party developed).
Native app developer will have to deal with 3 main layers – the device, operating system and the app itself.
Cross platform app
- Operating system
- Cross platform library. This is usually something that translates one programming language to native machine code that an operating system can understand.
- Software app code. In cross-platform approach one programming language is used to write the app. On the case of Flutter it is Dart programming language. Here as well, external libraries can be used to make app development easier.
More architectural layers and more code
So as you see from previous simplified description, cross-platform development has one extra layer to handle. And this layer is by all means not trivial. It’s a big chunk of code containing interpreters and tools that translate common code into different native code readable by the target operating system.
Cross-platform developer has to deal with one more layer – the cross-platform library which interprets code for each platform.
Coming back to this complexity issue, the extra layer can and will increase complexity for the whole application.
As an example, what If a bug appears in your app? Is it a bug in your app code, in underlaying library (aka Flutter), or is it an operating system bug? For specific problems like this, a developer will have to start looking in several places.
Another example. When an operating system update comes along. Developers will have to update the operating system, then the underlaying library and if needed, also their app code.
There can be several other scenarios, but I hope you already get my reasoning. The less building blocks of a software application, the better.
Keep it simple!
The more building blocks, the more can go wrong.
In conclusion, because of architectural reasons, cross-platform development can never be up to par with native app development. No matter how perfect the interpreting layer is. It’ll still be more code and more logic to compute. This results to less performant and lower quality apps for end users.
What about Flutter?
In case of Flutter. It seems to be the best cross-platform solution currently available. I have tested it out quite a bit. It is convenient and productive to build apps in Dart declaratively and hot reload is performing better than SwiftUI counterpart. Also the performance of Flutter apps is quite good, compared to other cross-platform solutions.
Another good argument is that a heavyweight company is behind the solution. This will hopefully ensure that it won’t get discontinued any time soon and new operating system and device innovation will be supported for time to come.
The problem still persists
The underlaying architectural problem still exist in case of Flutter as well. It’s still an extra layer of code and more code cannot make software run better.
One might argue, that it compiles Dart code to native components and hence is fast. But then there’s this interpreter problem again, as some bunch of logic that converts Dart to native items. This will in turn create an overhead when building and compiling a Flutter app and we’re in the same spot again, about too many building blocks for an app.
I can easily see, that Flutter will work for simpler short-term campaign apps. But if a lasting software solution needs to be built, then native is and will be the way to go for future to come.
I do see the appeal and the need for a working cross-platform development solution. It would be a big win for the developers as well as software users. Apps would work consistently and exactly the same in each platform and device.
I imagine. This would be possible, if Apple and Google (owners of iOS and Android) would start to cooperate in a very deep level and unify the coding language (and software development kits) used to target their operating systems. Which in turn means, that interpreting layer could be left out from the architecture.
Then and only then, we could see a cross-platform app performing the same as native app currently does.