A long time ago we placed ReactiveX — a family of open-source frameworks for reactive programming — into the Adopt ring of the Radar. In 2017, we mentioned the addition of RxSwift, which brought reactive programming to iOS development using Swift. Since then, Apple has introduced its own take on reactive programming in the form of the Combine framework. Combine has become our default choice for apps that support iOS 13 as an acceptable deployment target. It's easier to learn than RxSwift and integrates really well with SwiftUI. If you're planning to convert an existing application from RxSwift to Combine or work with both in the same project, you might want to look at RxCombine.
Our mobile teams now view LeakCanary as a good default choice for Android development. It detects annoying memory leaks in Android apps, is extremely simple to hook up and provides notifications with a clear trace-back to the cause of the leak. LeakCanary can save you tedious hours troubleshooting out-of-memory errors on multiple devices, and we recommend you add it to your toolkit.
AWS Data Wrangler is an open-source library that extends the capabilities of Pandas to AWS by connecting data frames to AWS data-related services. In addition to Pandas, this library leverages Apache Arrow and Boto3 to expose several APIs to load, transform and save data from data lakes and data warehouses. An important limitation is that you can't do large distributed data pipelines with this library. However, you can leverage the native data services — like Athena, Redshift and Timestream — to do the heavy lifting and pull data in order to express complex transformations that are well suited for data frames. We've used AWS Data Wrangler in production and like that it lets you focus on writing transformations without spending too much time on the connectivity to AWS data services.
We're seeing more teams adopting Python as the preferred language to build solutions, not just for data science but for back-end services too. In these scenarios, we're having good experiences with FastAPI — a modern, fast (high-performance), web framework for building APIs with Python 3.6 or later. Additionally, this framework and its ecosystem include features such as API documentation using OpenAPI that allow our teams to focus on the business functionalities and quickly create REST APIs, which makes FastAPI a good alternative to existing solutions in this space.
We've really enjoyed using TypeScript for a while now and love the safety that the strong typing provides. However, getting data into the bounds of the type system — from, for example, a call to a back-end service — can lead to run-time errors. One library that helps solve this problem is io-ts. It bridges the gap between compile-time type-checking and run-time consumption of external data by providing encode and decode functions. It can also be used as a custom type guard. As we gain more experience with io-ts in our work, our initially positive impressions are confirmed, and we still like the elegance of its approach.
The introduction of coroutines to Kotlin opened the door for several innovations — Kotlin Flow is one of them, directly integrated into the coroutines library. It's an implementation of Reactive Streams on top of coroutines. Unlike RxJava, flows are a native Kotlin API similar to the familiar sequence API with methods that include
filter. Like sequences, flows are cold, meaning that the values of the sequence are only constructed when needed. All of this makes writing multithreaded code much simpler and easier to understand than other approaches. The
toListmethod, predictably, converts a flow into a list which is a common pattern in tests.
Steady progress has been made since we first wrote about Web Components in 2014. LitElement, part of the Polymer Project, is a simple library that you can use to create lightweight web components. It's really just a base class that removes the need for a lot of the common boilerplate, making writing web components a lot easier. We've had success using it on projects, and as we see the technology maturing and the library being well liked, LitElement is becoming more commonly used in our Web Components-based projects.
We've had a bit more experience using Next.js for React codebases since the last time we wrote about it. Next.js is an opinionated, zero-configuration framework that includes simplified routing, automatic compilation and bundling with Webpack and Babel, fast hot reloading for a convenient developer workflow among other features. It provides server-side rendering by default, improves search engine optimization and the initial load time and supports incremental static generation. We've had positive experience reports from teams using Next.js and, given its large community, continue to be excited about the evolution of the framework.
On-demand modules for Android is a framework that allows tailored APKs containing only required functionality to be downloaded and installed for a suitably structured app. This could be worth trialing for larger apps where download speed might be an issue, or if a user is likely only to use some functionality on initial installation. It can also simplify the handling of multiple devices without requiring different APKs. A similar framework is available for iOS.
Streamlit is an open-source application framework in Python used by data scientists for building interactive data applications. Tuning machine-learning models takes time; instead of going back and forth on the main application (the one that uses these models), we've found value in quickly building standalone prototypes in Streamlit and gathering feedback during experimentation cycles. Streamlit stands out from competitors such as Dash because of its focus on rapid prototyping and support for a wide range of visualization libraries, including Plotly and Bokeh. We're using it in a few projects and like how we can put together interactive visualizations with very little effort.
When used in appropriate circumstances, our teams have found that the React Hooks library SWR can result in cleaner code and much improved performance. SWR implements the stale-while-revalidate HTTP caching strategy, first returning data from cache (stale), then sending the fetch request (revalidate) and finally refreshing the values with the up-to-date response. We caution teams to only use the SWR caching strategy when an application is supposed to return stale data. Note that HTTP requires that caches respond to a request with the most up-to-date response; only in carefully considered circumstances is a stale response allowed to be returned.
SSL public key pinning is tricky. If you select the wrong policy or don't have a backup pin, your application will stop working unexpectedly. This is where TrustKit is useful — it's an open-source framework that makes SSL public key pinning easier for iOS applications. There is an equivalent framework for Android as well. Picking the correct pinning strategy is a nuanced topic, and you can find more details about it in the TrustKit Getting Started guide. We've used TrustKit in several projects in production, and it has worked out well.
We don't call out every new .NET version in the Radar, but .NET 5 represents a significant step forward in bringing .NET Core and .NET Framework into a single platform. Organizations should start to develop a strategy to migrate their development environments — a fragmented mix of frameworks depending on the deployment target — to a single version of .NET 5 or 6 when it becomes available. The advantage of this approach will be a common development platform regardless of the intended environment: Windows, Linux, cross-platform mobile devices (via Xamarin) or the browser (using Blazor). While polyglot development will remain the preferred approach for companies with the engineering culture to support it, others will find it more efficient to standardize on a single platform for .NET development. For now, we want to keep this in the Assess ring to see how well the final unified framework performs in .NET 6.
bUnit is a testing library for Blazor that makes it easy to create tests for Blazor components in existing unit testing frameworks such as NUnit, xUnit or MSUnit. It provides a facade around the component allowing it to be run and tested within the familiar unit test paradigm, thus allowing very fast feedback and testing of the component in isolation. If you're developing for Blazor, we recommend that you add bUnit to your list of tools to try out.
Dagster is an open-source data orchestration framework for machine learning, analytics and plain ETL data pipelines. Unlike other task-driven frameworks, Dagster is aware of data flowing through the pipeline and can provide type-safety. With this unified view of pipelines and assets produced, Dagster can schedule and orchestrate Pandas, Spark, SQL or anything else that Python can invoke. The framework is relatively new, and we recommend that you assess its capabilities for your data pipelines.
In the previous Radar, we commented on the beginning of a phase of experimentation with state management in React applications. We moved Redux back into the Trial ring, documenting that it is no longer our default choice, and we mentioned Facebook's Recoil. In this volume we want to highlight Jotai and Zustand: Both are state management libraries for React; both aim to be small and simple to use; and, perhaps not by complete coincidence, both names are translations of the word state into Japanese and German, respectively. Beyond these similarities, however, they differ in their design. Jotai's design is closer to that of Recoil in that state consists of atoms stored within the React component tree, whereas Zustand stores the state outside of React in a single state object, much like the approach taken by Redux. The authors of Jotai provide a helpful checklist to decide when to use which.
Following the trend of cross-platform mobile development, Kotlin Multiplatform Mobile (KMM) is a new entry in this space. KMM is an SDK provided by JetBrains that leverages the multiplatform capabilities in Kotlin and includes tools and features designed to make the end-to-end experience of building mobile cross-platform applications more enjoyable and efficient. With KMM you write code once for business logic and the app core in Kotlin and then share it with both Android and iOS applications. Write platform-specific code only when necessary, for example, to take advantage of native UI elements; and the specific code is kept in different views for each platform. Although still in Alpha, Kotlin Multiplatform Mobile is evolving rapidly. We'll certainly keep an eye on it, and you should too.
With the increasing popularity of smart home and wearable devices, demand for intuitive graphical user interfaces (GUIs)is increasing. However, if you're engaged in embedded device development, rather than Android/iOS, GUI development may take a lot of effort. As an open-source embedded graphics library, LVGL has become increasingly popular. LVGL has been adapted to mainstream embedded platforms such as NXP, STM32, PIC, Arduino, and ESP32. It has a very small memory footprint: 64 kB flash and 8 kB RAM is enough to make it work, and it can run smoothly on various Cortex-M0 low-power MCUs. LVGL supports input types such as touchscreen, mouse and buttons and contains more than 30 controls, including TileView suitable for smart watches. The MIT license it chose doesn’t restrict enterprise and commercial use. Our teams’ feedback on this tool has been positive and one of our projects using LVGL is already in production, more specifically in small batch manufacturing.
Building forms for the web remains one of the perennial challenges of front-end development, in particular with React. Many of our teams working with React have been using Formik to make this easier, but some are now assessing React Hook Form as a potential alternative. React Hooks already existed when React Hook Form was created, so it could use them as a first-class concept: the framework is registering and tracking form elements as uncontrolled components via a hook, thereby significantly reducing the need for re-rendering. It's also quite lightweight in size and in the amount of boilerplate code needed.
At the heart of many approaches to machine learning lies the creation of a model from a set of training data. Once a model is created, it can be used over and over again. However, the world isn't stationary, and often the model needs to change as new data becomes available. Simply re-running the model creation step can be slow and costly. Incremental learning addresses this issue, making it possible to learn from streams of data incrementally to react to change faster. As a bonus the compute and memory requirements are lower and predictable. In our implementations we've had good experience with the River framework, but so far we've added checks, sometimes manual, after updates to the model.
The release of the Webpack 5 Module Federation feature has been highly anticipated by developers of micro frontend architectures. The feature introduces a more standardized way to optimize how module dependencies and shared code are managed and loaded. Module federation allows for the specification of shared modules, which helps with the deduplication of dependencies across micro frontends by loading code used by multiple modules only once. It also lets you distinguish between local and remote modules, where the remote modules are not actually part of the build itself but loaded asynchronously. Compared to build-time dependencies like npm packages, this can significantly simplify the deployment of a module update with many downstream dependencies. Be aware, though, that this requires you to bundle all of your micro frontends with Webpack, as opposed to approaches such as import maps, which might eventually become part of the W3C standard.