ProgrammingPro #46: Plurarsight’s AI Sandbox, PyAirbyte Library, Master Python Requests, DevSecOps Guide, & Modern C++ Strategies
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, Modern C++ Programming Cookbook - Third Edition, which will help you learn the correct application of noexcept in C++ for enhancing code robustness and performance, and provide guidelines for its use in various contexts.
News Highlights: Pluralsight's AI sandboxes and the PyAirbyte library will revolutionize how developers harness AI, while TypeScript 5.4 and Swift 5.10 make a landing. GitHub implementats secret scanning push protection bolstering security across public repos.
My top 5 picks from today’s learning resources:
What we learned in 6 months of working on a CodeGen dev tool GPT Pilot🤖
Exploring Contract First type of development of Microservices with OpenAPI spec📜
A Comprehensive DevSecOps Guide - Key Considerations to Effectively Secure Your CI/CD Pipeline🛡️
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! As a thank you, we will send you one free Packt credit to buy a book of your choice.
🗞️News and Analysis🔎
Pluralsight creates AI sandboxes that allow developers to safely experiment with AI: This initiative aims to bridge the AI expertise gap in the tech industry, offering a cost-effective solution for organizations to enhance their workforce's AI skills. Read to learn about the significance of accessible AI learning platforms.
PyAirbyte Brings the power of Airbyte to every Python developer: PyAirbyte, now in public Beta, is an open-source Python library that facilitates "Pipelines-as-Code" for Python developers. Read to learn about PyAirbyte's key features and its utility in data and AI projects.
Announcing TypeScript 5.4: The new version introduces features like Preserved Narrowing in Closures, the NoInfer Utility Type, Object.groupBy, and Map.groupBy, alongside improved support for require() calls. Read to learn more.
Swift 5.10 Released: The new version introduces full data isolation in its concurrency model, a critical step towards eliminating data races by enforcing mutual exclusive access to shared mutable state at compile time. Read for more.
Over 100,000 Infected Repos Found on GitHub: Attackers clone legitimate repositories, inject malware, and then disseminate these through automatic forks and online forums. Read to learn how despite GitHub's efforts to remove these repositories, the scale and automation of the attack pose a formidable challenge.
What’s new, what’s now, and what’s next in platform engineering: Platform engineering is becoming a key trend, with Gartner predicting 80% of large software organizations will adopt it by 2026. Read to learn about its impact on DevOps, and its potential to significantly improve software quality.
JQuery 4.0.0 Beta Released with Important Deprecations and Breaking Changes: The new version introduces significant updates, including bug fixes, performance enhancements, and breaking changes, notably dropping support for IE<11 and certain older browsers. Read to learn more.
GitHub enables secret scanning push protection by default: GitHub has mandated the protection for all public repositories to prevent API keys, tokens, and sensitive data leaks, following the discovery of one million secrets in public repositories early in 2024. Read to learn more about GitHub's security measures.
AWS CodePipeline Embraces Monorepos, GitFlow, and Branches: These updates include triggers and execution modes like Queued, Parallel, or Superseded, enabling more flexible pipeline designs. Read to learn how the development will enhance automation and efficiency in software delivery.
OpenJDK proposal would streamline Java records creation: The OpenJDK community is considering a preview language feature for Java, aimed at simplifying creating new records without the need for explicit wither methods. Read to learn how the feature would make working with immutable record classes more intuitive.
🎓Tutorials and Learning Resources💡
Python
🎓Tutorial | Python's Requests Library (Guide): This guide provides a comprehensive overview of Python's Requests library, a tool for making HTTP requests. Read to learn the fundamentals, including how to handle response data, manage authentication, and optimize requests.
What we learned in 6 months of working on a CodeGen dev tool GPT Pilot: The GPT Pilot project (a tool intended to become a real AI developer, not just an autocomplete tool) team has been exploring the extent to which coding can be automated using AI. Read for insights into the importance of clear initial app descriptions, the non-linear nature of coding, self-review by AI, and more.
Increasing velocity by modernizing a Python codebase: This article details the process of modernizing a Python codebase at Ramp (a fin-tech company), focusing on machine learning workflows. Read to learn how tools like poetry, ruff, pytest, and mypy improved code quality, prevented bugs, and enhanced development.
For more Python resources go to PythonPro
C/C++/C#
Laser Cutting Meshes in Unity With Shader Graph & C#: Krystian Laskowski has created a Unity-based system to realistically laser cut through meshes using Shader Graph and C#. Read to discover an innovative approach to creating realistic laser-cut effects on meshes in Unity.
🎓Tutorial | Object Creation in C#: Step-by-Step Guide: This tutorial begins with basic object creation and dives into the principles of Object-Oriented Programming, such as Encapsulation, Inheritance, and Polymorphism. Read to learn the intricate details of object creation in C#.
🎓Tutorial | You’ve just inherited a legacy C++ codebase, now what?: This article guides you through revitalizing a legacy C++ codebase, with minimal initial changes, modernizing the project with CI, and more. Read to learn a pragmatic approach to managing and improving a legacy C++ project.
🎓Tutorial | My late discovery of std::filesystem - Part I: This article takes you through the std::filesystem library, a feature introduced in C++17, by comparing it to Python's filesystem manipulation capabilities. Read for insights into managing files and directories efficiently with std::filesystem.
🎥Free Course | Learn C Programming with Dr. Chuck (feat. classic book by Kernighan and Ritchie): This 10-hour, open access course aims to introduce learners to computer architecture and low-level programming in C. Watch for a comprehensive understanding of C.
Java
🎓Tutorial | Dapr For Java Developers: The Dapr project offers a way for Java developers to streamline the complexity of cloud application development. Read to learn how Dapr can enable you to concentrate on creating valuable features rather than on configuring and managing infrastructure services.
🎓Tutorial | Level up your Java skills with Apache Groovy Maps: Groovy maps offer dynamic typing and are ideal for configuration files and data pipelines, enhancing code readability and productivity while reducing boilerplate. Read to learn how Groovy enhances Java's map functionalities.
Increase readability with Java's Pattern Matching: This article contrasts traditional instanceOf with modern pattern matching and switch expressions, demonstrating significant simplifications and readability improvements. Read to learn about the practical applications of Java's Pattern Matching.
JavaScript and TypeScript
JS Toolbox 2024: Runtime Environments and Package Management: This article provides an in-depth look at the latest tools in the JavaScript ecosystem, such as Node.js, Bun, NPM, and Yarn. Read to be able to make informed decisions for your projects in 2024.
Top 6 Easy Ways to Sum an Array in JavaScript: Techniques discussed in this article include reduce(), for-loops, for…of loops, forEach(), combining map() and reduce(), and recursion. Read to discover each method’s pros, cons, and performance.
🎓Tutorial | The `never` type and error handling in TypeScript: This article emphasizes the type’s common misuse in error handling. Read to learn about the type’s role in modeling impossible states rather than errors, and how to properly handle errors using discriminated unions and result types.
Go
The One Billion Row Challenge in Go: from 1m45s to 4s in nine solutions: The fastest Go solution discussed runs in 2.90 seconds. Read to learn advanced Go programming techniques for optimizing performance, including manual parsing, fixed-point arithmetic, and more for developing high-performance applications.
for Loop Semantic Changes in Go 1.22 - Be Aware of the Impact: The latest version of Go introduced significant semantic changes to for loops, particularly affecting loops with freshly-declared variables. Read to ensure your code behaves as intended.
Rust
Rust for Embedded Systems - Current State, Challenges and Open Problems: This paper emphasizes Rust’s importance for safety-critical systems due to its memory safety features. Read to learn about the potential benefits of Rust's memory safety and the existing barriers to its widespread adoption.
Async Rust in a Nutshell: This article article discusses the benefits of async programming in Rust for achieving efficient concurrent execution without managing threads. Read to learn about the Future trait, execution models, the role of async runtimes, and the latest developments in async methods and traits.
PHP
🎓Tutorial | AI for PHP: How to Make AI Assistant Generate Test Implementations: This article explores leveraging JetBrains AI Assistant for generating code implementations from tests in PHP, emphasizing a test-driven development approach. Read to learn how to utilize AI Assistant forTDD in PHP.
SQL
🎓Tutorial | SQL Gymnastics: Bending SQL into flexible new shapes: This article showcases how to tailor queries for specific needs without rewriting them for different datasets. Read to learn innovative ways to enhance SQL query flexibility using DuckDB.
.NET
🎓Tutorial | Get Started with Milvus Vector DB in .NET: This article explains how .NET developers can utilize the Milvus vector database for Generative AI workloads, emphasizing search and Retrieval Augmented Generation (RAG). Read to learn how to integrate vector databases into your .NET applications.
Ruby
🎓Tutorial | Active Record or Sequel: Which Best Fits The Needs of Your Ruby App?: This artcle compares two popular ORM libraries for Ruby applications, focusing on filtering, database locking, and transactions. Read to gain insight into the capabilities and use cases of Active Record and Sequel.
Swift
Optionals in Swift explained: 5 things you should know: Optionals are crucial in Swift, offering a clean code approach to handle nil values via syntax like question marks and unwrapping techniques. Read to learn how to effectively use optionals.
Kotlin
🎓Tutorial | Date and Time Formatting in Kotlin with the DateTime Library: The "kotlinx-datetime" library enhances Kotlin's date and time handling with locale-invariant parsing and formatting, streamlining cross-platform development. Read to learn how to efficiently format and parse dates and times in Kotlin.
🌟Best Practices and Code Optimization🚀
Exploring Contract First type of development of Microservices with OpenAPI spec: In this article, the author, Luis Trigueiros, explores the transition from a Code First approach to a Contract First approach, demonstrating through a practical example how contracts can drive service interface generation, ease parallel development, and facilitate API evolution. Read to learn how switching to Contract First can improve productivity, consistency, and quality.
Integrating Software Supply Chains and DevOps: Tips for Effectively Reconciling Supply Chain Management and DevOps: This article emphasizes that effective management of software supply chains (SSCs) requires visibility, input, and accountability across both development and operations teams. Read to discover practical steps to enhance security, collaboration, and efficiency.
A Comprehensive DevSecOps Guide - Key Considerations to Effectively Secure Your CI/CD Pipeline: This guide introduces the shift-left principle, advocating for early security checks in the SDLC to mitigate risks cost-effectively. Read to learn about the key tools and strategies for implementing a robust DevSecOps approach.
CORS Anywhere on Pure NGINX Config: This guide details setting up NGINX to handle CORS preflight requests, manipulate headers for CORS compliance, and utilize directives for dynamic processing and conditional responses. Read to learn how to to facilitate cross-origin resource sharing and more.
🧠 Expert Insight 📚
Here’s an exclusive excerpt from “Chapter 9, Robustness and Performance” in the book, Modern C++ Programming Cookbook - Third Edition by Marius Bancila.
Using noexcept for functions that do not throw exceptions
Exception specification is a language feature that can enable performance improvements, but on the other hand, when done incorrectly, it can abnormally terminate the program. The exception specification from C++03, which allowed you to indicate what types of exceptions a
function could throw, was deprecated in C++11 and removed in C++17. It was replaced with the C++11 noexcept specifier. Moreover, the use of the throw() specifier to indicate that a function throws, without indicating what exception types have also been deprecated in C++17 and completely removed in C++20. The noexcept specifier only allows you to indicate that a function does not throw exceptions (as opposed to the old throw specifier, which could indicate the list of types a function could throw). This recipe provides information about the modern exception specifications in C++, as well as guidelines on when to use them.
How to do it...
Use the following constructs to specify or query exception specifications:
Use noexcept in a function declaration to indicate that the function is not throwing any exception:
void func_no_throw() noexcept
{
}
Use noexcept(expr) in a function declaration, such as template metaprogramming, to indicate that the function may or may not throw an exception based on a condition that evaluates to bool:
template <typename T>
T generic_func_1()
noexcept(std::is_nothrow_constructible_v<T>)
{
return T{};
}
Use the noexcept operator at compile time to check whether an expression is declared to not throw any exception:
template <typename T>
T generic_func_2() noexcept(noexcept(T{}))
{
return T{};
}
template <typename F, typename A>
auto func(F&& f, A&& arg) noexcept
{
static_assert(noexcept(f(arg)), "F is throwing!");
return f(arg);
}
std::cout << noexcept(generic_func_2<int>) << '\n';
How it works...
As of C++17, exception specification is part of the function type, but not part of the function signature; it may appear as part of any function declarator. Because exception specification is not part of the function signature, two function signatures cannot differ only in the exception specification.
Prior to C++17, exception specification was not part of the function type and could only appear as part of lambda declarators or top-level function declarators; they could not appear even in typedef or type alias declarations. Further discussions on exception specification refer solely to the C++17 standard.
There are several ways in which the process of throwing an exception can be specified:
If no exception specification is present, then the function could potentially throw exceptions.
noexcept(false) is equivalent to no exception specification.
noexcept(true) and noexcept indicate that a function does not throw any exception.
throw() was equivalent to noexcept(true) but was deprecated in C++17 and removed altogether in C++20.
Note:
Using exception specifications must be done with care because if an exception (either thrown directly or from another function that is called) leaves a function marked as non-throwing, the program is terminated immediately and abnormally with a call to std::terminate().
Pointers to the functions that do not throw exceptions can be implicitly converted to pointers to functions that may throw exceptions, but not vice versa. On the other hand, if a virtual function has a non-throwing exception specification, this indicates that all the declarations of all the overrides must preserve this specification unless an overridden function is declared as deleted.
At compile time, it is possible to check whether a function is declared to be non-throwing or not using the operator noexcept. This operator takes an expression and returns true if the expression is declared as either non-throwing or false. It does not evaluate the expression it checks.
The noexcept operator, along with the noexcept specifier, is particularly useful in template metaprogramming to indicate whether a function may throw exceptions for some types. It is also used with static_assert declarations to check whether an expression breaks the non-throwing guarantee of a function, as seen in the examples in the How to do it... section.
The following code provides more examples of how the noexcept operator works:
int double_it(int const i) noexcept
{
return i + i;
}
int half_it(int const i)
{
throw std::runtime_error("not implemented!");
}
struct foo
{
foo() {}
};
std::cout << std::boolalpha
<< noexcept(func_no_throw()) << '\n' // true
<< noexcept(generic_func_1<int>()) << '\n' // true
<< noexcept(generic_func_1<std::string>()) << '\n'// true
<< noexcept(generic_func_2<int>()) << '\n' // true
<< noexcept(generic_func_2<std::string>()) << '\n'// true
<< noexcept(generic_func_2<foo>()) << '\n' // false
<< noexcept(double_it(42)) << '\n' // true
<< noexcept(half_it(42)) << '\n' // false
<< noexcept(func(double_it, 42)) << '\n' // true
<< noexcept(func(half_it, 42)) << '\n'; // true
It is important to note that the noexcept specifier does not provide compile-time checking for exceptions. It only represents a way for users to inform the compiler that a function is not expected to throw exceptions. The compiler can use this to enable certain optimizations. An example is the std::vector, which moves elements if their move constructor is noexcept and copies them otherwise.
There’s more...
As mentioned earlier, a function declared with the noexcept specifier that exits due to an exception causes the program to terminate abnormally. Therefore, the noexcept specifier should be used with caution. Its presence can enable code optimizations, which help increase performance while preserving the strong exception guarantee. An example of this is library containers.
Note:
The C++ language provides several levels of exception guarantees:
The first level, no exception guarantees, does not provide any guarantees. If an exception occurs, there is nothing to indicate whether the program is left in a valid state. Resources could be leaked, memory can be corrupted, and object invariants may be broken.
The basic exception guarantee is the simplest level of guarantee, which ensures that after an exception is thrown, objects are left in a consistent and usable state, no resource leaks occur, and invariants are preserved.
The strong exception guarantee specifies that either an operation is completed successfully, or that it is completed with an exception that leaves the program in the same state it was in before the operation started. This ensures commit-or-rollback semantics.
The no-throw exception guarantee is actually the strongest of them all and specifies that an operation is guaranteed to not throw any exception and to complete successfully.
Many standard containers provide some of their operations with a strong exception guarantee. An example is vector’s push_back() method. This method could be optimized by using the move constructor or move assignment operator instead of the copy constructor or copy assignment operator of the vector’s element type. However, in order to preserve its strong exception guarantee, this can only be done if the move constructor or assignment operator does not throw exceptions. If either does, then the copy constructor or the assignment operator must be used instead.
The std::move_if_noexcept() utility function does this if the move constructor of its type argument is marked with noexcept. The ability to indicate that move constructors or move assignment operators do not throw exceptions is probably the most important scenario where noexcept is used.
Consider the following rules for the exception specification:
If a function could potentially throw an exception, then do not use any exception specifier.
Mark only those functions with noexcept that are guaranteed not to throw an exception.
Mark only those functions with noexcept(expression) that could potentially throw exceptions based on a condition.
These rules are important because, as already noted previously, throwing an exception from a noexcept function will immediately terminate the program with a call to std::terminate().
Packt subscribers can continue reading for free here. Modern C++ Programming Cookbook - Third Edition by Marius Bancila was published in February 2024. You can buy the book here!
🛠️ Useful Tools ⚒️
FastUI: an open-source framework that enables Python developers to build responsive web UIs without JavaScript, focusing on reusability and collaboration efficiency.
mountaineer: a Python and React framework providing seamless client-server integration, typehints, and server-side rendering for improved SEO.
perspective: a versatile analytics tool for processing and visualizing large or streaming datasets, usable in browsers, Python, and JupyterLab.
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 anyfeedback, take the survey, or leave a comment below.




