ProgrammingPro #49: ASP.NET Core Insights, Java 22 & GraalVM, .NET AI Smart Components, & Open Source Challenges
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, Architecting ASP.NET Core Applications - Third Edition, that will teach you how to implement and leverage the Data Transfer Object (DTO) pattern within MVC applications.
News Highlights: ASP.NET Core updates enhance Blazor and security, Oracle's GraalVM integrates with Java 22, .NET Smart Components democratize AI programming, and Synopsys report reveals open source software challenges.
My top 5 picks from today’s learning resources:
Dynamic Querying in C# - Real-World Scenarios and Techniques🎲
Building Serverless Apps with the AWS CDK Using TypeScript🌩️
Distributed Caching: Enhancing Performance in Modern Applications💨
But there’s more, so dive right in.
Stay Awesome!
Divya Anne Selvaraj
Editor-in-Chief
PS: If you have any food for thought, feedback, or would like us to find you a specific Programming learning resource for our next issue, take the survey!
🗞️News and Analysis🔎
ASP.NET Core Updates in .NET 9 Preview 2 - Blazor, OIDC, OAuth and Configuring HTTP.sys: The preview includes advancements in Blazor, authentication processes, HTTP.sys configuration, and JSON serialization. Read to learn how the updates aim to streamline and secure development processes.
Oracle’s GraalVM backs Java 22: Oracle's latest release, GraalVM for JDK 22, integrates Java 22 features into its Java runtime, enabling both just-in-time and ahead-of-time compilation. Read to learn more about GraalVM’s efficiency improvements and the strategic move towards closer integration with OpenJDK.
.NET Smart Components experiment the “Visual Basic” of AI programming?: Mcrosoft has introduced .NET Smart Components which aim to simplify AI programming for every developer. Read to learn how this release can integrate AI-enhanced functionalities into Blazor or ASP.NET applications.
Open source in 2024 - Tackling challenges related to security, AI, and long-term sustainability: A Synopsys report highlights that a typical application includes more than 500 open source components, with the demand-side value of open source software estimated at $8.8 trillion. Read for insights into OSS challenges, the role of AI, and concerns regarding sustainability.
Java 22 brings security enhancements: JDK 22 enhances Java's security with new root CA certificates, an asymmetric key interface, and a -XshowSettings option for security settings visibility. Read to learn how these updates bolster Java's cryptographic capabilities, public key infrastructure, and overall security.
Rust adds support for C-string literals: Rust 1.77 introduces support for C-string literals, simplifying interoperability with foreign languages by allowing null-byte terminated strings, with compile-time error checking. Read to learn more.
Development Environment Manager (DEM) Daytona Now Open Source: The move offers an alternative to Codespaces for self-hosted, secure development environments. Read to learn why despite mixed community feedback, the initiative has been prasied.
🎓Tutorials and Learning Resources💡
Python
Designing a Pure Python Web Framework: This article introduces Reflex, a pure Python web framework designed to simplify the development of web apps by integrating frontend and backend development into a single Python codebase. Read for insights into the framework’s development.
Every dunder method in Python: This article explains how these "double underscore" methods allow for customization of class interactions with Python's features. Read to gain a comprehensive understanding of Python's dunder methods, their applications, and how to implement them.
🎓Tutorial | Prompt Engineering with Python - A Practical Example: This article guides you through applying various prompt engineering techniques, such as using numbered steps, delimiters, and more, to refine the interactions with and responses from LLMs. Read to gain hands-on experience in optimizing LLM outputs.
For more Python resources go to PythonPro
C# and .NET
🎓Tutorial | Avoid using enums in the domain layer in C#: The practice can lead to issues such as tight coupling, broken encapsulation, and maintenance challenges. Read for a detailed critique advocating for record types as a more encapsulated, maintainable, and performant alternative.
🎓Tutorial | Multi-Year Revit Addin - A Better Way: This article presents a structured approach to developing Revit API projects that support multiple Revit versions. Read to learn an effective strategy for structuring C# solutions to easily manage and support multiple versions of Revit addins.
🎓Tutorial | Dynamic Querying in C# - Real-World Scenarios and Techniques: This article delves into the power of dynamic querying in C#, showcasing how it transforms a library app's search functionality from a rigid codebase into a flexible and efficient system. Read to learn how to implement dynamic querying effectively.
C and C++
Why isn’t C++ using my default parameter to deduce a template type?: In C++, default parameters are not considered when deducing template type parameters, leading to errors when calling a templated function without arguments. Read to enhance your understanding of template behavior and parameter deduction in C++.
Passing recursive C++ lambdas as function pointers: Creating recursive lambdas in C++ can be challenging because a lambda doesn't know its own type, preventing self-reference. Read to learn about the intricacies and solutions for implementing recursive lambdas in C++.
Building and testing C extensions for SQLite with ChatGPT Code Interpreter: This article describes an experiment for developing an extension for vector similarity calculations using ChatGPT's Code Interpreter. Read for insights into the approach’s potential and the challenges encountered.
Java
9 Best Java Profilers to Use in 2024: This article discusses the use of Java profilers, focusing on the author's experience with memory leaks in a Linux application and how Java profilers helped identify and analyze the issue. Read to be able to choose the best profiler for your needs.
Gradle's leaky abstractions - Declarative(ish) shell, imperative core Implementing a safe(ish) global configuration DSL: This article discusses the complexity of using Gradle for building Java applications. Read to discover a method for safely configuring Gradle projects from the root project.
Why You Should Stop Using @Value Annotations In Spring (And Use This Instead): This article argues against using @Value annotations in Spring for injecting values, advocating for @ConfigurationProperties instead. Read to learn how to utilize @ConfigurationProperties for a cleaner, more testable, and flexible configuration management approach.
JavaScript and TypeScript
🎓Tutorial | How to handle errors in React: This article explains error handling in React, focusing on JavaScript errors and render errors, and how React error boundaries manage render-time errors. Read to be able to ensure a graceful handling of both JavaScript and render errors.
Optimizing Javascript for fun and for profit: This article presents common JavaScript optimization techniques, emphasizing the trade-off between performance and readability. Read to gain insights into effective JavaScript optimization practices.
🎓Tutorial | Building Serverless Apps with the AWS CDK Using TypeScript: This tutorial covers setting up a project, creating a Lambda function to convert JSON to CSV and upload to S3, and deploying it using TypeScript. Read to learn how to efficiently develop and deploy serverless applications.
Go
🎓Tutorial | Visual Guide to Slices in Go: This article explores Go's slices, essential data structures alongside maps for data storage, delving into their under-the-hood mechanics. Read to gain insights into efficient data manipulation and avoiding common pitfalls associated with slice capacity and memory allocation.
Learning Go in 2024 - From Beginner to Senior: This article provides a comprehensive guide for learning Go, catering to various learning styles and levels of experience. Read for a roadmap for progressing from a novice to an expert in Go.
Rust
Why choose async/await over threads?: This article discusses the preference for async/await over threads in Rust, highlighting the complexity and technical debt associated with threads for I/O-bound tasks. Read to learn about async/await's advantages in handling millions of simultaneous clients efficiently.
What Are Const Generics and How Are They Used in Rust?: Const generics in Rust allow functions, structs, enums, and other items to be parameterized by constant values, in addition to types and lifetimes. Read to learn how to perform more precise and safer compile-time checks for data structures and algorithms.
PHP
🎓Tutorial | How to Architect Laravel + React Applications with Nginx and Docker: This article provides a detailed guide on setting up and deploying a Laravel and React application using Docker and Nginx. Read to learn how to achieve a modern, scalable web application setup.
SQL
🎓Tutorial | Conducting Similarity Search in Enterprise Data: This tutorial showcases how to use pgvector with Postgres for conducting similarity searches for identifying industries related to the software industry for a campaign. Read to learn how to utilize contemporary tools and frameworks to address a specific need.
Ruby
Micro benchmarking value objects in Ruby - Data.define vs Struct vs OpenStruct: This article examines the performance differences between Data.define, Struct (with keyword_init), and OpenStruct for creating and accessing objects in Ruby. Read to understand the performance implications and best practices when choosing your approach for object creation and access.
Swift
Writing GNOME Apps with Swift: This article introduces the use of Swift for developing GNOME applications, focusing on creating user interfaces with clean syntax, static typing, and the Adwaita library for Swift. Read to explore how you can create intuitive and scalable user interfaces.
Kotlin
Toll-free Bridging in Kotlin Native: This article delves into the concept of interoperability between Core Foundation and Foundation Kit frameworks in macOS and iOS development. Read to understand the importance of interoperability and memory management when using Core Foundation and Foundation frameworks.
Scala
💼Case Study | Why we bet on Scala at SwissBorg: This article debunks myths about Scala, such as complexity and hiring difficulties, through a blockchain-based wealth management platform’s experience of building a stable and efficient system. Read for insights into Scala's advantages.
🌟Best Practices, Advice, and Case Studies🚀
💼Case Study | Decathlon Adopts Backend for Frontend (BFF) Pattern to Empower FE Teams: While the BFF pattern introduces potential risks like business logic duplication, Decathlon managed to mitigate these through architectural oversight and adopting patterns like circuit breakers for fault tolerance. Read for insights into the company's strategy and the outcomes.
Some Thoughts on Bad Programming Practices: This article critiques the tendency among developers to prioritize new programming tools and methodologies over proven, simpler techniques. Read to understand how this can cause issues such as overcomplication, neglect of basic principles, and poor software development and maintenance.
How to Get Tech-Debt on the Roadmap: This article emphasizes aligning technical debt resolution with business priorities to incorporate it into the roadmap, evaluating its impact on business growth, and advocating for technical projects by demonstrating their business value. Read to learn strategic approaches for managing technical debt in a way that aligns with business objectives.
Distributed Caching: Enhancing Performance in Modern Applications: This article delves into distributed caching, a technology crucial for enhancing application performance by offering scalable, efficient, and faster data handling across networked resources. Read to understand how distributed caching can significantly improve performance, scalability, and reliability.
Take the Survey, Request a Resource
🧠 Expert Insight 📚
Here’s an exclusive excerpt from “Chapter 6, Model-View-Controller” in the book,
Architecting ASP.NET Core Applications - Third Edition by Carl-Hugo Marcotte.
Using MVC with DTOs
This section explores leveraging the Data Transfer Object (DTO) pattern with the MVC framework.
Goal
As a reminder, DTOs aim to control the inputs and outputs of an endpoint by decoupling the API contract from the
application’s inner workings. DTOs empower us to define our APIs without thinking about the underlying data structures, leaving us to craft our REST APIs how we want.
Other possible objectives are to save bandwidth by limiting the amount of information the API transmits, flattening the data structure, or adding API features that cross multiple entities.
Design
Let’s start by analyzing a diagram that expands MVC to work with DTOs:
Figure 6.2: MVC workflow with a DTO
DTOs allow the decoupling of the domain from the view (data) and empower us to manage the inputs and outputs of our REST APIs independently from the domain. The controller still manipulates the domain model but returns a serialized DTO instead.
Project – MVC API
Note
This code sample is similar to the previous chapter but uses the MVC framework instead of minimal APIs. Both versions are part of the same solution to make it easy to compare them—for example, DTOEndpoints.GetCustomersSummaryAsync is almost the same implementation as CustomersController.GetAllAsync, but one uses the minimal API model while the other uses the MVC model.
Therefore, I kept most of the code out of the book so that it does not feel redundant. You can refer to …GitHub if you are uncertain of some shared code.
Context (reminder): We must build an application to manage customers and contracts. We must track the state of each contract and have a primary contact in case a business needs to contact a customer. Finally, we must display the number of contracts and the number of opened contracts for each customer on a dashboard.
Let’s first explore a CRUD controller that does not leverage DTOs.
Raw CRUD controller
The same issues that we explored in the previous chapter can arise if we create a CRUD controller to manage the customers directly.
The controller code of this section is in the RawCustomersController.cs file. The minimal API model’s equivalent is in the CustomersEndpoints.cs file. The rest of the code is mostly the same.
For example, the controller action that returns all customers looks like this:
using Microsoft.AspNetCore.Mvc;
using Shared.Data;
using Shared.Models;
namespace MVC.API.Controllers.Raw;
[Route("raw/[controller]")]
[ApiController]
[Tags("Customers Raw")]
public class CustomersController : ControllerBase
{
// GET: raw/customers
[HttpGet]
public async Task<IEnumerable<Customer>> GetAllAsync(
ICustomerRepository customerRepository)
{
return await customerRepository
.AllAsync(HttpContext.RequestAborted);
}
// Other actions are omitted
}
Here’s the minimal API version:
var group = routes
.MapGroup("/raw/customers")
.WithTags("Customers Raw")
;
group.MapGet("/", async (ICustomerRepository customerRepository, CancellationToken cancellationToken) =>
{
return await customerRepository
.AllAsync(cancellationToken);
});
As we can see from the preceding two code blocks, both models use a different semantic to declare the endpoint and configure the routing, but the logic is the same (the highlighted code). The controller uses the routing attributes, while the minimal API endpoint uses extension methods like WithTags and MapGet.
Next, we explore a controller when using DTOs.
DTO controller
We can use DTOs with controllers to solve our problems, as we did with minimal APIs. For example, the controller action that returns the customer summaries looks like this:
using Microsoft.AspNetCore.Mvc;
using Shared.Data;
using Shared.DTO;
using Shared.Models;
namespace MVC.API.Controllers.DTO;
[Route("dto/[controller]")]
[ApiController]
[Tags("Customers DTO")]
public class CustomersController : ControllerBase
{
[HttpGet]
public async Task<IEnumerable<CustomerSummary>> GetAllAsync(ICustomerRepository customerRepository)
{
// Get all customers
var customers = await customerRepository.AllAsync(
HttpContext.RequestAborted
);
// Map customers to CustomerSummary DTOs
var customersSummary = customers
.Select(customer => new CustomerSummary(
Id: customer.Id,
Name: customer.Name,
TotalNumberOfContracts: customer.Contracts.Count,
NumberOfOpenContracts: customer.Contracts.Count(x => x.Status.State != WorkState.Completed)
))
;
// Return the DTOs
return customersSummary;
}
// Other actions are omitted
}
Its minimal API counterpart, pointing to the GetCustomersSummaryAsync method, looks like this:
var group = routes
.MapGroup("/dto/customers")
.WithTags("Customers DTO")
;
group.MapGet("/", GetCustomersSummaryAsync);
static async Task<Ok<IEnumerable<CustomerSummary>>> GetCustomersSummaryAsync(
ICustomerRepository customerRepository,
CancellationToken cancellationToken)
{
// Get all customers
var customers = await customerRepository.AllAsync(cancellationToken);
// Map customers to CustomerSummary DTOs
var customersSummary = customers.Select(customer => new CustomerSummary(
Id: customer.Id,
Name: customer.Name,
TotalNumberOfContracts: customer.Contracts.Count,
NumberOfOpenContracts: customer.Contracts
.Count(x => x.Status.State != WorkState.Completed)
));
// Return the DTOs
return TypedResults.Ok(customersSummary);
}
The highlighted code of the two preceding code blocks shows the difference between the two routing models, while the body of the GetAllAsync and GetCustomersSummaryAsync methods are very similar.
Note
The entire API is available on GitHub to compare other methods and explore the codebase more. Moreover, you can play with the API using the HTTP requests in the MVC.API.DTO.http file.
Packt library subscribers can continue reading for free here. Architecting ASP.NET Core Applications - Third Edition by Carl-Hugo Marcotte was published in March 2024. You can buy the book here!
🛠️ Useful Tools ⚒️
Flyde: a visual programming tool for VS Code that enhances JavaScript and TypeScript development with graphical flows, aiming to improve API and microservice design efficiency.
jampack: a post-processing tool that optimizes static websites for the best user experience and Core Web Vitals scores, enhancing images and assets for responsiveness and efficiency.
tracecat: an open source, AI-native automation platform for security teams, providing enterprise-grade tools and user-focused UI/UX to simplify security automation for small-to-mid sized teams.
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 feedback, leave a comment below.