In this section, we will explore the general background we need to properly introduce the FMX framework. Delphi is a longevous environment and it existed way before the FMX framework. We need to delve a bit into the roots of the Delphi tool to understand FMX in a better way.
When I was still a teenager, Delphi was the best development environment to build Microsoft Windows applications. I had some Turbo Pascal background knowledge and someone told me to give Borland Delphi a try in order to easily get into visual application development. That was during the time of Windows 95 and the world, from an IT point of view, was much simpler than today. DOS and Windows had a very large share of personal computer coverage. The remaining part of the world was running Linux or Macintosh but with a limited share and only in very specific contexts. Even though the mainframe (such as IBM AS400) was still a thing, business companies were mostly running Windows.
Given that I had limited DOS programming knowledge, I spent a lot of time learning how to build a Windows GUI application and also experimented with other languages (such as Visual Basic, Java, and Visual C++) but Delphi has been my favorite right from the start.
The ability to easily build beautiful Windows applications through a designer is still a great plus and I really think this has been one of the key factors of Delphi's success. The following screenshot shows the Delphi 10.4.1 Sydney splash-screen:
Apart from the convenient GUI Rapid Application Development (RAD) approach, built into an effective IDE, Object Pascal was a great language showcasing full Object-Oriented Programming (OOP) support, great C compatibility (perfect for Windows API calls), and featuring a very fast compiler. Generated applications also had outstanding runtime performances.
Looking at Delphi as a whole product, what surfaces is a fantastic tool, capable of letting developers focus on their application code while building fast, good-looking, modern applications – a shiny gem to easily deliver proper and curated GUI applications for the Microsoft Windows platform. In other words, the product performed very well by being more abstracted than raw C/C++ programming and proving to be way more powerful than Visual Basic (just to cite two of the biggest Delphi competitors over time).
This has been possible thanks to a framework shipped with the product: the Visual Component Library (VCL). It acted as a sort of abstraction over the standard Windows controls, wrapping them in a more suitable and easy-to-use programming interface. A big difference with respect to other products has been that all this provided the ability to go back to being low-level and interact with the primitive control whenever needed.
Using the VCL was convenient and the library naturally evolved over two decades (at least!) of development by covering more and more Windows features and capabilities. Every Delphi developer felt at home while dealing with VCL components and most applications never needed to breach into low-level code. This meant higher productivity for the developer and I myself have seen several projects started with other technologies then being abandoned due to running over time for the project execution. Developer teams struggled to deliver functionalities in years while the same project revamped with Delphi came to a successful conclusion within months.
Today, the general scenario is much more complex than what it looked like in the late 1990s. We have seen the rise of mobile platforms and at the time I am writing this, a mobile Operating System (OS) (that is, Android) is now the most used OS worldwide. Also, the desktop platforms scene has seen some changes and now Apple’s Mac OS X (aka macOS) has much more widespread adoption than before (even if this is not equally true in every part of the world). Linux somewhat lost the race for desktop user adoption (I am not considering Android as a Linux family member, even though it is Linux kernel-based) but got a relevant position as a server-side platform (driving the web, one could say).
In the following graph, you can see OS distribution over time (period starting January 2009 to January 2020 – data source: https://gs.statcounter.com):
From the preceding graph, it is easy to spot the decline of Windows (the dominant platform from 2009 up to 2017) and the corresponding rise of Android (with it overtaking around 2018).
Generally speaking, today, multi-tier architectures have become the de facto standard for real projects that have to deal with a (possibly high) number of heterogeneous clients and need to provide users with proper interfaces in very different scenarios (desktop, mobile, web platforms across different device families). Due to this fact, it's more and more challenging to see applications as single projects, built for a specific platform (as it was for decades). The availability of an application across multiple platforms has become a very demanding feature (it has almost become an intrinsic standard requirement).
To build and maintain multiple (one per supported platform) development projects, just to deliver the same functionalities to all involved final users, is costly from several points of view. It is hard because developers will have to learn platform-specific behaviors, technologies, APIs, programming languages and deployment toolchains. This requires several different, demanding skills. It will likely mean more than a single development team will be required to accomplish the mission. This also quickly leads to maintainability issues over time, with a huge impact on the total cost and time-to-market of the product you are building. Even if building a specific application for each platform sounds too expensive, the other option (to build a single cross-platform application) has to address some not so evident issues.
First of all, nobody really wants to have a cross-platform application framework that only enables the developer to rely on the common shared part of all platforms. Obviously, this approach (the greatest common divisor) would fall short as platforms are diverging in terms of functionalities and even those capabilities available on all platforms usually have some interface/implementation details that make them hard (or expensive/inefficient) to abstract.
At the same time, nobody needs a framework that is a composition of specific functionalities gathered from all supported platforms as this would result in something actually enabling developers to build applications relying on all functionalities of all platforms but forcing them to write different code (in the same language, though) for each platform (that is, the general problem the framework has been built to solve).
The solution (as often happens) is something in between these two opposites. FireMonkey is in a nice spot, thanks to its mixed strategy. Being a sort of compromise, it goes without saying that this also translates into a list of related strengths and weaknesses.
In the following screenshot, you can see the Delphi IDE while designing a multi-platform application. The Android style is selected for use in the form designer, an iOS style preview is available through the Multi-Device Preview window (docked into the IDE on the right side) and an instance of the application is running on the Windows platform, just in front of the IDE itself—three styles visible at the same time, one per platform; three different binaries using the same (single) source code:
As you can see, the cross-platform capabilities of Delphi are highlighted in the preceding screenshot. You are building your application (using a single programming language: Delphi), addressing multiple platforms easily. You can design your app in the IDE, select one of the supported styles (each style being associated with a specific platform—Android, as shown in the previous screenshot) to preview the result in the form designer, seamlessly. At the same time, you can also have a look at Multi-Device Preview (part of the IDE set of functionalities named Fire UI). There, you'll get a realistic preview of how your application will look on other (multiple, eventually) platforms (iOS, which is also shown in the preceding screenshot).
Note that neither of the two mentioned platforms (Android and iOS) is the one that your IDE is running (Windows) and that your app will also be able to be executed, no code changes needed, on Windows (and Linux and OS X/macOS). Doesn't sound great enough? Then you can go even further and have your forms previewed, live, on a mobile device through another technology named Live Preview (still part of the Fire UI set, http://docwiki.embarcadero.com/RADStudio/en/FireUI_Live_Preview). This time, you'll be able to preview (without having to wait until the compilation time) your UI on actual physical devices, without effort, with the screen of the device acting as an extension of your IDE.
In this section, we discussed the current scenario of software development, describing how and why we are facing the need to deliver multi-platform applications. We also introduced the FMX framework approach, with respect to the difficulties of the implementation of the same application using different tools to address different platforms.
In the next section, we are going to focus on the strategy FMX takes in order to provide different UI visuals to match the current platform of the running application.