ProgrammingPro #58: Kotlin Design Patterns, RustRover IDE by JetBrains, Temurin's Major Update, and AI Predictions in Java
Bite-sized actionable content, practical tutorials, and resources for programmers
Welcome to this week’s edition of ProgrammingPro!
In today’s Expert Insight, we bring you an excerpt from the recently published book, Kotlin Design Patterns and Best Practices - Third Edition, which talks about the practical applications of the Prototype design pattern in Kotlin, including how to efficiently handle object cloning to manage evolving user data structures.
News Highlights: JetBrains launches RustRover IDE with a full Rust toolchain and AI-assisted coding; Eclipse Temurin rolls out its largest update, supporting multiple OpenJDK versions; Angular 18 releases with stable APIs and Google Search's library; and Azul's CEO predicts Java will rival Python in AI dominance.
My top 5 picks from today’s learning resources:
How Python Compares Floats and Ints - When Equals Isn’t Really Equal🤨
Evaluating AI-generated code for C++, Fortran, Go, Java, Julia, Matlab, Python, R, and Rust🤖
But there’s more, so dive right in.
Stay Awesome!
Divya Anne Selvaraj
Editor-in-Chief
PS: This week is your last chance to take part in our monthly survey for May. If you haven’t yet, we invite you to take the opportunity to tell us what you think about ProgrammingPro so far, request a learning resource for future issues, tell us what you think about a recent development in the Programming world, and earn a Packt Credit.
🗞️News and Analysis🔎
JetBrains releases RustRover IDE for Rust development: RustRover integrates a complete Rust toolchain and offers AI-assisted coding via an optional plugin. Read to learn about the IDE’s functionalities.
Angular 18 released, including the ‘same library used by Google Search’ thanks to Wiz merger: This release includes stable APIs for Material 3 design system components, deferable views for improved load times, and new control flow directives that enhance performance and replace older directives. Read for more.
Azul CEO sees Java’s AI future as bright: Scott Sellers expresses optimism for Java's role in AI, predicting it will eventually match Python's popularity in the sector. Read to learn about Java's emerging potential in AI.
Eclipse Temurin gets its largest release to date: The update is an open source Java build based on OpenJDK which includes support for 54 platform-version combinations across five major OpenJDK versions. Read to learn more.
Customers protest as JetBrains ends Space collaboration platform, intros SpaceCode as partial alternative: Space is being discontinued due to low adoption. Read to learn more about the replacement, SpaceCode, which only offers git hosting and code reviews.
OpenSSF teams up with Eclipse Foundation to define specifications for the EU’s Cyber Resilience Act: This act sets security requirements for hardware and software sold in the EU. Read to learn more about the collaboration.
Why enterprises rely on JavaScript, Python, and Java: These three programming languages introduced in the 1990s, continue to dominate the software industry due to their versatility, broad adoption, and robust ecosystems. Read for insights into how these languages sustain their legacy.
🎓Tutorials and Learning Resources💡
Python
Statically Typed Functional Programming with Python 3.12: This article promotes declarative operations, pattern matching in functions, and more. Read to learn how to avoid complex class hierarchies and excessive exception use.
How Python Compares Floats and Ints - When Equals Isn’t Really Equal: This article reveals discrepancies due to precision limits in floating-point representation and Python's infinite precision integers. Read to gain insight into why seemingly equivalent numbers can produce different comparison results.
For more Python resources go to PythonPro
C# and .NET
🎓Tutorial | How to implement identity authentication in minimal APIs in ASP.NET Core: The process has been streamlined with the identity management enhancements in .NET 8. Read to learn how to utilize the built-in features.
What's new in C# 13: The version introduces several enhancements including params collections with broader type support, a new lock type for improved thread synchronization, and an escape sequence for the ESCAPE character. Read to learn more.
What's new in .NET 9: Key updates include a new attribute model for feature switches, performance boosts in the .NET runtime, enhanced JSON serialization options, and LINQ methods in .NET libraries. Read to learn more.
C and C++
C++ Core Guidelines: This living document edited by Bjarne Stroustrup and Herb Sutter, serves as a continuously evolving reference aimed at fostering the effective use of modern C++. Read to gain insights into best practices.
The C++ Object Lifecycle: This article emphasizes the vital role of adhering to implicit contracts during unsafe operations such as custom container creation and memory management. Read to discover best practices for memory allocation, object construction, and destruction.
strb_t - A new string buffer type (2 of 2): This article introduces a proposed new string buffer type for C, aiming to reduce common programming errors through a safer, more ergonomic interface. Read to learn how the profiler simplifies string management in C.
Java
🎓Tutorial | Classes and objects in Java: This tutorial explores how to effectively use classes, fields, methods, constructors, and objects in Java programming. Read to gain comprehensive knowledge on structuring Java applications.
🎓Tutorial | Class and object initialization in Java: This tutorial details the use of constructors, class and object initialization blocks, and field initializers to prepare them for execution in the JVM. Read for detailed insight into the mechanism.
🎓Tutorial | Tackling Records in Spring Boot: This article explores the use of Java records in Spring Boot to enhance code readability and expressiveness by reducing redundancy. Read to learn how to simplify and condense code structures.
JavaScript and TypeScript
Cypress vs Playwright - A Comparative Analysis: This article provides a comparative analysis of two popular testing tools for web applications. Read for detailed insights into the functionalities, advantages, and disadvantages of both.
🎓Tutorial | How To Create a Network Graph Using JavaScript: This tutorial covers setting up HTML and JavaScript files to scripting and customizing the network graph. Read to learn how to visualize complex relationships and structures.
On Laravel, full-stack JavaScript, and productive frameworks: This article explores the author's extensive experience with Laravel and full-stack JavaScript frameworks, weighing their productivity, functionality, and ecosystem support. Read to learn about the trade-offs between the two.
Go
Runtime code generation and execution in Go - Part 1: This article discusses the author’s experience with generating and executing machine code within the Go environment. Read to learn the foundational ideas behind executing custom machine code within a Go application.
Abusing Go's infrastructure: This article explores an unusual aspect of Go's infrastructure, particularly the checksum database which appears to store records for modules unrelated to Go, such as Ruby and Rust projects. Read for more.
Rust
Rust's Unsafe Pointer Types Need An Overhaul: This article covers three main areas: conceptual background, problems with the current pointer design, and proposed solutions. Read to learn about advanced memory handling concepts.
Exploring Seamless Rust Interop for Newer Languages, Part 1: This article addresses the challenges and potential of using Rust's vast library ecosystem without traditional bindings. Read to discover innovative approaches.
PHP
Running PHP blazingly fast at the Edge with WebAssembly: This article discusses how running PHP in WebAssembly using Wasmer and Wasmer Edge can achieve up to 3x speed improvements. Read to learn about the security and performance gains.
SQL
💼Case Study | How We Improved Our SQL Parser Speed by 70x: Bytebase’s original parser took 147 seconds to process a 1000-line SQL due to ambiguities in handling complex SQL statements. Read to learn how parsing time was reduced to just 2.3 seconds.
Ruby
Fast, Simple and Metered Concurrency in Ruby with Concurrent::Semaphore: This article explores different methods to handle high concurrency in Ruby. Read to learn about implementing concurrency using both a ThreadPoolExecutor and a Semaphore.
Swift
ChatGPT for Swift - Top 5 code generation prompts: Prompts discussed range from creating Swift structs for JSON handling to writing unit tests to suggesting code improvements. Read to learn practical ways to integrate ChatGPT into your Swift development process.
Kotlin
Streamline Data Analysis with Kotlin DataFrame Tables in Notebooks: This article introduces an improved UI component in Kotlin DataFrame 0.13.1. Read to learn about the functionalities of the new component.
Fortran
Using Fortran on Cloudflare Workers: This article discusses how to run Fortran code by compiling it to WebAssembly, leveraging the advancements in the WebAssembly ecosystem. Read to explore the possibilities for utilizing Fortran in web-based and serverless environments.
🌟Best Practices, Advice, and Case Studies🚀
Evaluating AI-generated code for C++, Fortran, Go, Java, Julia, Matlab, Python, R, and Rust: For this study, the AI models were tasked with generating codes for numerical integration, a conjugate gradient solver, and a parallel 1D stencil-based heat equation solver. Read to explore the results.
Architecting flexible back ends with GraphQL: Utilizing GraphQL with Ballerina and Choreo can allow for more dynamic data retrieval and reduced issues with over-fetching and under-fetching. Read to learn about this powerful solution.
Experimenting with LLMs for Developer Productivity: The results of an experiment have suggested that while no LLM succeeded without human intervention, some did accelerate the process of coding unit tests. Read for more insights.
How To Protect a File Server: This article outlines using a Defense in Depth approach, incorporating technical, physical, and administrative controls. Read to learn how to systematically secure a Linux file server.
Take the Survey, Get a Packt credit!
🧠 Expert Insight 📚
Here’s an excerpt from “Chapter 2: Working with Creational Patterns” in the book, Kotlin Design Patterns and Best Practices - Third Edition by Alexey Soshin.
Prototype
The Prototype design pattern focuses on customization and the creation of objects that are similar but have slight variations. To gain a better understanding, let’s examine an example.
Consider a system that handles user
management and permissions. We can represent a user using a data class, which might be structured as follows:
data class User(
val name: String,
val role: Role,
val permissions: Set<String>,
) {
fun hasPermission(permission: String) = permission in permissions
}
Each user must have a role, and each role has a set of permissions.
We’ll describe a role as an enum class:
Enum classes offer a convenient method for representing a collection of constants. This approach is advantageous compared to using strings to represent roles, as it allows for compile-time checks ensuring the existence of such objects. Additionally, using an enum allows the creation of when blocks without the need for an else clause.
In the scenario of creating a new user, we can assign them permissions that are similar to another user who has the same role. This can be achieved by utilizing the prototype design pattern, where we clone an existing user object and make the necessary adjustments:
// In real application this would be a database of users
val allUsers = mutableListOf<User>()
fun createUser(name: String, role: Role) {
for (u in allUsers) {
if (u.role == role) {
allUsers += User(name, role, u.permissions)
return
}
}
// Handle case that no other user with such a role exists
}
Let’s consider a situation where we need to introduce a new field to the User class called tasks:
data class User(
val name: String,
val role: Role,
val permissions: Set<String>,
val tasks: List<String>,
) {
...
}
Once we add the tasks field to the User class, the createUser function will no longer compile. We will need to modify the function to include the value of this newly added field when creating a new instance of the class. Here’s an example of how the modified function might look:
allUsers += User(name, role, u.permissions, u.tasks)
Indeed, the aforementioned work of copying the newly added field’s value to the new instance of the User class will need to be repeated every time the User class undergoes changes.
However, an even more significant issue arises when a new requirement is introduced, such as making the permissions property private. This change would render our previous approach ineffective and would require significant modifications to the code base:
data class User(
val name: String,
val role: Role,
private val permissions: Set<String>,
val tasks: List<String>,
) {
...
}
If we make the permissions property private, our code won’t compile, and we’ll need to make more changes to fix it. This shows that we need a different way to handle this problem instead of repeatedly modifying the code. Now that we’ve introduced the challenges, let’s see how the Prototype design pattern solves them.
Starting from a prototype
The concept behind a prototype is to enable easy cloning of an object. There are at least two reasons why you might want to do this:
It is beneficial in cases where creating an object is resource-intensive or expensive. For example, if the object needs to be fetched from a database or involves complex initialization processes.
It is useful when you need to create objects that are similar but have slight variations. By cloning a prototype object, you can avoid the repetition of similar parts and customize the cloned objects as needed.
By utilizing the prototype design pattern, you can address these scenarios effectively.
IMPORTANT NOTE:
There are also more advanced reasons to use the Prototype design pattern. JavaScript, for example, uses prototypes to implement inheritance-like behavior without having classes.
Kotlin effectively addresses the limitations of Java’s clone() method by offering a more robust alternative. In contrast to Java, where clone() necessitates the implementation of the Clonable interface and managing potential exceptions, Kotlin simplifies the process. It integrates the functionality directly into its data classes, making object copying more straightforward and reducing the likelihood of errors. Kotlin’s data classes come equipped with a built-in copy() method. This method facilitates the creation of a new instance of an existing data class, with the option to modify some of its attributes. We have previously touched on this method while discussing data classes in the preceding chapter.
Here’s an example of how the copy() method can be used:
fun createUser(userName: String, role: Role) {
for (u in allUsers) {
if (u.role == role) {
allUsers += u.copy(name = userName)
return
}
}
// Handle case that no other user with such a role exists
}
…named arguments in Kotlin allow us to specify attributes in any desired order. Moreover, we only need to specify the attributes we want to modify, as the remaining data will be automatically copied for us, including private properties.
Kotlin Design Patterns and Best Practices - Third Edition by Alexey Soshin was published in April 2024. You can buy the book here! Packt library subscribers can continue reading the entire book for free here.
🛠️ Useful Tools ⚒️
Phi-3: a family of open-source, small language models developed by Microsoft, designed for efficient, simple tasks and suited for local device operation, with models tailored for text, vision, and multimodal interactions.
Indexify: an open-source framework for creating fast data pipelines, enabling real-time extraction and querying of unstructured data such as video, audio, and documents for LLM applications.
dataherald: an open source natural language-to-SQL engine that enables enterprise users to query relational databases in plain English without SQL knowledge.
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. Complete ProgrammingPro archives can be found here. Complete PythonPro archives are 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.
If you have any comments or feedback, take the survey, leave a comment below.