This will hopefully give you and me a better understanding at which technologies should be use for different projects. For niche use cases, you may obviously prefer different tech. Small, medium, and large project sizes refer to tens, hundreds, and thousands of lines of code respectively.
Here are the best programming languages for each field; if multiple languages are listed, they are equally good.
- Servers: Kotlin
- Web frontends: Kotlin, ReasonML, TypeScript
- Android apps: Kotlin
- Apple's platforms: Swift
- Cross-platform mobile: Kotlin (by sharing business logic), C# (Xamarin)
- AI: Python
- Video games: C# (Unity), C++ (Unreal)
- System software: Rust
- Cross-platform desktop apps: Kotlin (through TornadoFX)
- Native Windows desktop apps: C#
This table helps choose which language you should go with for frontend web apps based on your project's size.
|Project size||Styling langauge||Scripting language|
- Although they don't force you to use particular libraries, they do a great job of telling you what you might need before you hit a pain point and wonder if there's a better way.
- They give you every tool you'll practically need, regardless of whether you'll use it or not.
- They take a long time to learn.
- They get outdated every few years. The same can be said for any programming tool. It doesn't matter too much since the concepts learnt carry on to the next framework.
- Libraries take a negligible amount of time to learn in comparison to a framework, and are a lot easier to migrate to or away from. Although libraries allow for greater flexibility in how your project is built, they have less integration with the other components in your system as a whole.
Here's a look at the top frameworks.
- React is good for medium and large projects, and is my personal preference over the other options.
Vue is good for medium and large projects. It has a significantly smaller ecosystem than React (the Vue point this out themselves), and has significantly less support (e.g., ReasonML and Kotlin have official React wrappers for them, but not a Vue one). Unlike React, which leans on the leaner side
no pun intended, Vue has a lot of built-in components.
- Svelte is best suited for medium projects.
Frameworks have components for each of the following concepts. Concepts having standalone libraries to address their pain points have the best libary linked to them.
- Ready-made components refer to components such as buttons which are styled out-of-the-box. You can use a library such as Material Components.
HTML templating refers to easily creating DOM nodes in JS. You cannot directly create HTML elements by using an expression such as
const avatar = '<button><img src="img.png"</button>'because they are prone to injection attacks, and are difficult to maintain. You can use a library such as lit-html for this.
- Custom element creation is the creation of web components. You can use a library such as LitElement to rid their creation of boilerplate, etc.
Data binding is the boilerplate-free way of mirroring data between the DOM and the program. Sans data binding, you have to use the following pattern far too often whenever you're presenting dynamic data.
<input type="button" id="clicker"> Clicks: <span id="clicks"></span> <script> let count = 0; document.querySelector('#clicker').addEventListener( 'click', () => document.querySelector('#clicks').textContent = ++clicks ); </script>
Data binding rids us of this unmaintainable code by directly embedding the variables in the template. It does this by combining individual components' template and script code in the same file. Since data binding requires control over multiple files (languages), it is limited to frameworks. Although there were attempts to create standalone data binding libraries, those were quickly deprecated since they ended up being really bad versions of Vue.js.
State management gives you a high level way of manipulating what your web app looks like at any given point in time. You can think about state as your computer's desktop - with just a glance, you can easily see the current battery level, wi-fi connectivity, and which applications are open. Libraries such as Redux help deal with this.
Where possible, generate code using tools such as Google Sites.
Remember that there are other other tools, such as testing and routing, which frameworks provide that aren't listed here. Such tools haven't been listed since half the reason frameworks provide them in the first place is because their custom setups require custom tooling to work with existing ecosystems and concepts. That is not to say that they are without their merits. Such tools are useful in their own way as well, but their benefits are only visible in larger projects, whereas smaller projects are more likely than not to be negatively impacted under their weight.
In general, you should use fewer tools the smaller your project is. Only in larger projects do libraries such as Redux actually improve (rather than worsen) code maintainability. Larger projects will benefit from frameworks even though new standards are always coming out (e.g., built-in custom element creation via web components). This is because new standards take time to get approved, consistently implemented, and lack the support larger projects require. Although smaller projects will be benefit from directly leveraging native standards when they come out, the boilerplate they usually require is very visibly felt in larger ones, and hence the lifetime for a framework's use in larger projects is substantially longer than that of smaller projects.
Here's a table showcasing which technologies are overkill for different sized projects. ✅, ➖, and ❌ refer to should use, doesn't matter (i.e., it's worth using if you already know it, but doesn't matter enough to learn it if you don't), and shouldn't use respectively.
|Project size||Ready-made components||HTML templating||Custom element creation||Data binding||State management||Framework|
Since OSes such as Firefox OS and Windows 10 Mobile come and go in a matter of years (and are hardly used while they're there), we'll only consider Android and iOS.
Here is every way you can make a mobile app. When I use the word native, I mean that it's been created using the officially recommended technologies (e.g., using Swift on iOS).
This is a great choice since you'll already be using Kotlin for Android development. Besides being able to leverage an excellent language and ecosystem for your business logic, you'll also be able to share the same code on other platforms such as the server side.
Xamarin allows you to share business logic while using first-party tooling to build separate UIs for different platforms. It deploys to Android, iOS, and UWP. They also allow you to access any native API using a consistent interface through their official C# wrappers which are available within a few days of new features being released on their respective platforms. Of course, certain aspects such as your app's size and native tooling will be less than optimal. You should use Xamarin if you have the resources for C# and Xamarin, but not Kotlin and Swift. Xamarin will obviously require you to know a certain amount of platform specifics, but the learning curve is relatively low. When I say using Kotlin, I mean using it to write not only the native Android UI, but the shared business logic as well.
This is great if you don't have the resources to share business logic in Kotlin, but have the resources to natively build and maintain the app on two different platforms.
This is great if the vast majority of your target audience uses Android, and you're short on resources.
This is great if the vast majority of your target audience uses iOS, and you're short on resources.
Flutter is seriously lacking in both the UI and business logic aspects, and will clearly not improve noticably in the foreseeable future. It requires you to be an expert in platform specifics. Unlike Xamarin which provides C# wrappers and official documentation for each platform's API, Flutter requires you to have advanced knowledge of not only its own framework, but the platforms as well. Since you'll have to write native code for even the most trivial aspects of your application, you'll have to be an expert in Kotlin, Swift, Android documentation, iOS documentation, Android project structures, iOS project structures, Android tooling (you'll need to learn and configure complex plaform-specific build systems such as Gradle yourself since you'll need to download the relevant official or third-party libraries), and iOS tooling. Clearly, Flutter falsely advertises that it speeds up app development time while helping you build a better app. The opposite is true. Flutter takes significantly longer to write an app than building it natively in Android and iOS. And after all that extra effort in learning a third platform (Dart, Flutter, and the relevant tooling), you end up with a significantly worse app (which includes pseudo-native UI components and a bloated app size).
- The idea is to share the business logic in Dart. Dart has a pathetic ecosystem, and its features are significantly worse than the platform-natives (i.e., Kotlin and Swift).
- Unlike in Xamarin where the UI must be written twice for each platform, Flutter allows you to share common UI code. However, this causes the UI to strongly disagree with the most basic principles on the other platform. Android's Material Design has a strong contrast with iOS's Cupertino in everything from gestures and animations, to layouts and widgets. You might think this a nonissue if you were to simply write the UI once for each platform. However, this is not the case. Even basic apps which make no use of remotely platform-specific components (e.g., HTTP API calls, camera access), the app will refuse to run on iOS without even giving an error message. There are many other issues Flutter has with the most basic of UI requirements which you will easily find searching on communities like Reddit.
- Unlike Xamarin, you must use native code for platform APIs. Even though websites can natively access trivial components such as the camera and microphone, Flutter simply cannot. What's worse is that even platform-specific software components such as notifications require native code, and they lack official- or community-created plugins, so you'll have to write them yourself.
This was never a good choice, and is now a bad one considering that you can use Kotlin instead. C/C++ are primitive languages which require a relatively steeper learning curve, require libraries for the most basic of operations, and mandate that the native code calling it create wrappers in order to use them. For these reasons and more, companies such as Dropbox and Slack have emigrated from this approach.
Hybrid (e.g., React Native, Ionic) apps make use of web standards to create cross-platform apps. These solutions are only adopted because they have a smaller learning curve if you already know frontend web development. Otherwise, they scale poorly because they cannot access native platform features (e.g., AR), and have a seriously lacking ecosystem. The ecosystem will never improve because web technologies were meant to be used on..the web (surprise, surprise), and there are too many hybrid toolchains at any given time (e.g., Angular). Web technologies were not meant for mobile development, and hence perform poorly at it; you shouldn't use a language meant for DOM manipulation in the browser. As with any technology significantly worse than the one meant for the task at hand, but are adopted for its unworthy slightly lower learning curve, learning the recommended technology scales much better (e.g., Udacity and Airbnb emigrated from Reach Native).
This is an easy choice without the demerits of a hybrid app approach. Since this is a regular website, it will run on desktops (via a browser) as well, and the lack of a platform-conforming UI is a nonissue. Of course, it will be used less due to the lacking UX (compared to native apps), and you won't be able to access any nontrivial platform features (the web only grants access to small platform components such as the camera, not the full filesystem or notification bar).
Websites are not meant to be used as mobile apps. They are even worse than hybrid apps since the UI is completely non-native, and they lack any tooling whatsoever. Your entire development time will go into using an ecosystem which wasn't designed for the task at hand, all while gaining access to zero new platform features (when compared to a non-PWA website). The technologies behind PWAs such as caching are excellent for websites, but do not make it anywhere near a good fit for a mobile app present on the user's home screen. The only use case for building a PWA is if you want to distribute an app on iOS, but don't have the resources (e.g., money, hardware, skills, time) for it. In this case, you should be building a mobile-friendly website, and using the PWA feature as an easier way to launch the website. PWAs will never be a subsitute, not even a poor one, for mobile app development.