ProgrammingPro #80: Declarative UI in Flutter, GitHub Copilot’s New AI Models, and PyTorch 2.5 Intel GPU Optimizations
Welcome to this week’s edition of ProgrammingPro!
In today’s Expert 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.
🗞️News and Analysis🔎
Central Package Management (CPM) Now Available in .NET Upgrade Assistant: Available in Visual Studio and CLI, CPM reduces redundancy by consolidating package versions, simplifying updates with a single directory file.
PyTorch 2.5 Release Includes Support for Intel GPUs: Key features include the FlexAttention API for streamlined attention mechanisms, backend optimizations for faster performance, and regional compilation to reduce latency.
Java News Roundup: Apache Pulsar 4.0, Jakarta EE 11, Open Liberty, Helidon, JHipster, Apache Camel: Key developments also include JDK 24 progress and Project Loom builds, plus Spring framework releases.
Flutter forked as Flock, developer cites “company-wide issues at Google”: Flutter developer Matt Carroll has forked the framework to create “Flock” in response to Google’s deprioritization of Flutter, particularly on desktop platforms.
OpenSSF updates its Developing Secure Software course with new interactive labs: The free course covers secure design principles, supply chain security, and threat modeling and offers a certificate valid for two years.
OSI officially releases its definition for Open Source AI: The definition includes code, model, and “data information,” requiring detailed descriptions of training data for reproducibility.
Microsoft engineer describes a flaw in Git that can hugely bloat repositories – fix is on the way: The fix aimed at large repositories, will soon be available in a Git update, minimizing storage needs.
GitHub Copilot now offers access to new Anthropic, Google, and OpenAI models: Updates also include multi-modal support, side-by-side comparisons, Autofix security features, and customization options.
🎓Tutorials and Learning Resources💡
Python
💼Case Study | Concurrent Requests in Python: httpx vs aiohttp: Describes how switching from the
httpx
toaiohttp
library resolved high-concurrency issues and improved stability in a computer vision application.
For more Python resources, go to PythonPro
Spark and Scala
📖Open Access Book | The Internals of Spark Core (Apache Spark 3.5.2): Covers Spark’s structure, job scheduling, execution, and resource management, beneficial for developers looking to understand Spark at a systems level.
Optimizing Spark Compute for Medallion Architectures in Microsoft Fabric: Explains how to optimize Spark compute in Microsoft Fabric’s Medallion architecture (Bronze, Silver, Gold) by tailoring configurations for each layer.
C# and .NET
A comparison of Rust’s borrow checker to the one in C#: Shows that C# achieves similar safety without explicit lifetimes by making trade-offs, such as restricted lifetime management.
🎓Tutorial | Integrating Large Language Models in .NET Projects: Demonstrates how to use Microsoft's Semantic Kernel and Extensions.AI, to query custom data and enhance interactions with LLMs.
The Power of Function Composition — to Find If an Array Is Special: Explores advanced techniques in function composition to evaluate if an array meets certain criteria, with examples in C# and Haskell.
C and C++
🎓Tutorial | Square a Number in C++: Methods and Applications: Covers approaches ranging from basic multiplication to complex use cases, such as handling overflow, bitwise operations, and custom number systems.
🎓Tutorial | How to Reverse a C++ String: Practical Guide: Covers approaches such as using temporary strings and efficient in-place swaps, STL’s
std::reverse
, and Unicode handling.🎓Tutorial | Ray-Casting [C]CUB3D Project [42-cursus] (1337 KH): Describes techniques for horizontal and vertical intersections, wall projection, texture mapping, and color handling, including pixel data manipulation.
Java
Spring News Roundup: Release Candidates for Spring Boot, Security, Auth Server, Modulith: New release candidates include Spring Boot 3.4.0-RC1, Spring Security 6.4.0-RC1, and updates to Spring Integration.
🎥Better Java Builds with the Mill Build Tool, Japan Java User Group Fall Conference 2024: Introduces Mill, a faster, more user-friendly JVM build tool, recently expanded from Scala to Java and Kotlin projects.
🎓Tutorial | Applying Clean Architecture in Java with Spring Boot: Provides practical, in-depth examples of architecture decoupling, multiple data sources, and managing external libraries like Lombok, Log4j, and Cacheable.
JavaScript and TypeScript
🎓Tutorial | Testing In JavaScript With Jest: Guides you through setup, basic testing syntax, matchers, asynchronous testing, and organizing tests for maintainability.
💼Case Study | How we shrunk our Javascript monorepo git size by 94%: Described how Microsoft's 1JS team reduced a massive 178GB monorepo's size by addressing several git inefficiencies, particularly with CHANGELOG files.
💼Case Study | How We Rebuilt the ChatGPT & YouTube Summary Extensions: Details Glasp's rewrite of their Summary extension, transitioning from VanillaJS to a React and TypeScript setup using Vite.
Go
🎓Tutorial | Go I/O Closer, Seeker, WriterTo, and ReaderFrom: Explains Closer's role in resource management, Seeker's ability to navigate within streams, and WriterTo and ReaderFrom's streamlining of data transfer.
Go does what RxJS couldn't: Compares the simplicity of Go with the complexities of RxJS and imperative JavaScript for state management in an audio player app.
Rust
Async Rust is not safe with io_uring: Examines the issues of connection leaks and incomplete cancellation in async Rust when using
io_uring
instead ofepoll
and proposes partial solutions to address these challenges.Unsafe Rust Is Harder Than C: Explores the complexities of using unsafe Rust to create an optimized batch-processing channel, highlighting the difficulties with intrusive data structures, lifetimes, and Rust’s aliasing model.
Swift
🎓Tutorial | A Whirlwind Tour of Swift Concurrency: Provides an overview of Swift Concurrency, highlighting its benefits in creating more readable and maintainable code, safer multithreading through actors, and more.
🎓Tutorial | Using the #require macro for Swift Testing: Introduces Apple’s new library for testing, which ensures prerequisites are met before tests proceed, enhancing code readability and reducing ambiguity in failure cases.
PHP
🎓Tutorial | Clean Code Architecture in Laravel: A Practical Guide: Details implementing clean code practices by structuring applications into layers: entities, repositories, interfaces, controllers, and services, with clear examples.
SQL
SQLite will migrate from GNU Autotools to Autosetup, team warns of ‘some build-level breakage’: While most users won’t notice changes, the shift may cause “build-level breakage,” especially in automated build processes.
Ruby
Ruby Caches - Rails Cache Comparisons: Compares various caching options like memory store, file store, Memcached, Redis, and SolidCache, emphasizing their scalability and performance in different deployment contexts.
Kotlin
JetBrains updates Kotlin roadmap: The updated roadmap emphasizes better data handling, abstraction, and performance, with plans for faster code completion and stable analysis in the K2 IntelliJ IDEA plugin.
🌟Best Practices and Advice🚀
RAG-Powered Copilot Saves Uber 13,000 Engineering Hours: Uber’s Genie streamlines incident response for engineers by quickly retrieving relevant internal data to answer support questions.
Securing Cell-Based Architecture in Modern Applications: Details essential strategies including isolation, zero-trust security, role-based and attribute-based access controls, and encrypted communication (TLS, mTLS).
Do's and Don'ts of Commenting Code: Covers best practices like using consistent standards, explaining "why" rather than "what," and documenting hacks or tradeoffs for team clarity
Jump Into the Demoscene; It Is Where Logic, Creativity, and Artistic Expression Merge: Explores the demoscene, a subculture where programmers blend creativity and technical skill to create real-time digital art.
🧠Expert Insight📚
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.
Understanding the difference between declarative and imperative UI design
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 the overall 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 wrong with imperative.
Understanding the imperative paradigm
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 such as 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 mutated their 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 the following problems:
The more elements that can change their presentation based on a state change, the more mutations you need to handle. You can easily imagine how this simple
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 becomes more complex.Modifying the global state can produce side effects. On every such change, we mutate the same UI element and possibly call other methods that also mutate the same elements. The resulting myriad of nested conditionals can quickly lead to inconsistency and illegal states in the final view that the user sees. Such bugs tend to manifest only when certain conditions are met, which makes them even harder to reproduce and debug.
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 from the start.
Understanding the declarative paradigm
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 the following 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 the isError
or isProgress
fields). In the upcoming chapters, you will learn how to elegantly handle the state, but for now, you only need to understand the concept.
This approach can also be called reactive, since the widget tree updates itself as a reaction to a change of state.
Does Flutter use the declarative or imperative paradigm?
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 (see https://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 a Container
or Chip
widget unreadable. It would also make it more complicated to manage all of their 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 about it 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 book here!
Get the eBook for $31.99 $21.99
🛠️Useful Tools⚒️
trench: An open-source, real-time analytics platform using Kafka and ClickHouse for high-volume event tracking with self-hosted and cloud options.
pneumaticworkflow: An open-source, cloud-native workflow manager to automate business processes with a visual designer and API integrations.
Codehooks Analytics: An open-source web tool for tracking and analyzing user interactions across websites, giving full data control and real-time insights.
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 useful here.
If your company is interested in reaching an audience of developers, software engineers, and tech decision makers, you may want to advertise with us.