





















































Hi ,
Welcome to this week’s edition of ProgrammingPro!
In today’sExpert Insight, we bring you an excerpt from the recently published book, Flutter Design Patterns and Best Practices, which briefly discusses the declarative UI in Flutter, contrasting it with the traditional imperative approach.
News Highlights: NET’s new Central Package Management streamlines dependencies across projects;Flutter is forked as "Flock" due to Google's reduced focus; Microsoft’s Git fix reduces repo bloat; GitHub Copilot expands with new AI models; and PyTorch 2.5 adds Intel GPU support and optimizations for ML.
My top 5 picks from today’s learning resources:
But there’s more, so dive right in.
Stay Awesome!
Divya Anne Selvaraj
Editor-in-Chief
PS:Thank you all who participated in this month's survey. With this issue we have fulfilled all resource requests made in October. Keep an eye out for next month's survey.
This free 3-hour Training on AI & ChatGPT (worth $399) will help you become a master of 20+ AI tools & prompting techniques and save you 16 hours/week.
httpx
toaiohttp
library resolved high-concurrency issues and improved stability in a computer vision application.std::reverse
, and Unicode handling.io_uring
instead of epoll
and proposes partial solutions to address these challenges.Here’s an excerpt from “Chapter 1: Best Practices for Building UIs with Flutter" in the book, Flutter Design Patterns and Best Practices by Daria Orlova, Esra Kadah, and Jaime Blasco, published in September 2024.
The beauty of technology is that it evolves with time based on feedback about developer experience. Today, if you’re in mobile development, there is a
high chance that you have heard about Jetpack Compose, SwiftUI, React Native, and of course Flutter. The thing these technologies have in common is both that they’re used for creating mobile applications and the fact that they do it via a declarative programming approach. You may have heard this term before, but what does it actually mean and why is it important?
To take full advantage of a framework, it’s important to understand its paradigm and work with it rather than against it. Understanding the “why” behind the architectural decisions makes it much easier to understand the “how,” and to apply design patterns that complement theoverall system.
Native mobile platforms have a long history of development and major transitions. In 2014, Apple announced a new language, Swift, that would replace the current Objective-C. In 2017 the Android team made Kotlin the official language for Android development, which would gradually replace Java. Those introductions had a hugely positive impact on the developer experience, yet they still had to embrace the legacy of existing framework patterns and architecture. In 2019, Google announced Jetpack Compose and Apple announced SwiftUI – completely new toolkits for building UIs. Both SwiftUI and Jetpack Compose take advantage of their respective languages, Swift and Kotlin, leaving legacy approaches behind. Both toolkits also loudly boast their declarative programming paradigm. But language advantages aside, let’s explore why declarative is now the industrial de facto and what is wrongwith imperative.
By definition, the imperative programming paradigm focuses on how to achieve the desired result. You describe the process step by step and have complete control of the process. For example, it could result in code suchas this:
fun setErrorState(errorText: String) {
val textView = findViewById<TextView>(R.id.error_text_view)
textView.text = errorText
textView.setTextColor(Color.RED)
textView.visibility = View.VISIBLE
val button = findViewById<Button>(R.id.submit_button)
button.isEnabled = true
val progressView = findViewById<ProgressBar>(R.id.progress_view)
progressView.visibility = View.GONE
}
In the preceding snippet, we imperatively described how to update the UI in case of an error. We accessed the UI elements step by step and mutatedtheir fields.
This is a real example of code that could’ve been written for a native Android application. Even though this approach may be powerful and gives the developer fine-grained control over the flow of the logic, it comes with the possibility of thefollowing problems:
setErrorState
becomes cumbersome as more fields need to be hidden or changed. The approach also assumes that there are similar methods for handling a progress and success state. Code such as this may easily become hard to manage, especially as the amount of views in your app grows and the state becomesmore complex.For many years, the imperative approach was the only way to go. Thankfully, native mobile frameworks have since started adopting declarative toolkits. Although these are great, developers who need to switch between paradigms inside of one project can encounter many challenges. Different tools require different skills and in order to be productive, the developer needs to be experienced with both. More attention needs to be paid to make sure that the application that is created with various approaches is consistent. While the new toolkits are in the process of wider adoption, some time and effort are required until they are able to fully implement what their predecessors already have. Thankfully, Flutter embraced declarative fromthe start.
In an imperative approach, the focus is on the “how.” However, in the declarative approach, the focus is on the “what.” The developer describes the desired outcome, and the framework takes care of the implementation details. Since the details are abstracted by the framework, the developer has less control and has to conform to more rules. Yet the benefit of this is the elimination of the problems imposed by the imperative approach, such as excessive code and possible side effects. Let’s take a look at thefollowing example:
Widget build(BuildContext context) {
final isError = false;
final isProgress = true;
return Column(
children: [
MyContentView(
showError: isError,
),
Visibility(
visible: isProgress,
child: Center(
child: CircularProgressIndicator(),
),
),
],
);
}
In the preceding code, we have built a UI as a reaction to state changes (such as theisError
orisProgress
fields). In the upcoming chapters, you will learn how to elegantly handle the state, but for now, you only need to understandthe concept.
This approach can also be called reactive, since the widget tree updates itself as a reaction to a changeof state.
It is important to understand that Flutter is a complex framework. Conforming to just one programming paradigm wouldn’t be practical, since it would make a lot of things harder (seehttps://docs.flutter.dev/resources/faq#what-programming-paradigm-does-flutters-framework-use). For example, a purely declarative approach with its natural nesting of code would, make describing aContainer
orChip
widget unreadable. It would also make it more complicated to manage all oftheir states.
...
If you are coming from an imperative background, getting used to the declarative approach of building the UI may be mind-bending at first. However, shifting your focus from “how” to “what” you’re trying to build will help. Flutter can help you too, as instead of mutating each part of the UI separately, Flutter rebuilds the entire widget tree as a reaction to state changes. Yet the framework still maintains snappy performance, and developers usually don’t need to think aboutit much.
Flutter Design Patterns and Best Practices was published in September 2024. Packt library subscribers can continue reading the entire book for free or you can buy the bookhere!
That’s all for today.
We have an entire range of newsletters with focused content for tech pros. Subscribe to the ones you find the most usefulhere.
If your company is interested in reaching an audience of developers, software engineers, and tech decision makers, you may want toadvertise with us.