ProgrammingPro #29: Are your Proxies safe?, Swift 5.9, Node.js 21, C# Memory Alignment, & JIT compilation in JS
Bite-sized actionable content, practical tutorials, and resources for programmers
"During my first Microsoft internship, I wrote string libraries to run on the Macintosh…Everything I did was right from K&R — one thin book about the C programming language. Today, … I need to know … high level tools compared to the old K&R stuff, but I still have to know the K&R stuff or I’m toast.”
– Joel Spolsky (2002), The Law of Leaky Abstractions
Welcome to this week’s issue of our programmer focused newsletter.
Are your web proxies safe? Squid, a proxy cache server with over 2.5 million instances, has 35 unpatched security vulnerabilities. On the bright side, Swift 5.9 has improved code generation and introduced C++ interoperability, while GitGuardian has created a free tool for securing cloud-native secrets.
Our tutorials and learning resources this week cover a bit of Swift with all the other good stuff. Here are my top three picks:
We also have an exclusive excerpt for you on “Using Domain Driven Design to shape the Domain hexagon” from the book Designing Hexagonal Architecture with Java. So, scroll down and dive right in!
Stay awesome!
Divya Anne Selvaraj
Editor-in-Chief
PS: If you want us to find a tutorial for you the next time or give us any feedback, take the survey! Also, the PythonPro newsletter subscription link is up, and you can subscribe here.
🗞️News
Squid games: 35 security holes still unpatched in proxy after 2 years, now public: Squid, which has over 2.5 million instances in use, has resolved only 20 of the 55 flaws identified in its source code 2 years ago. Read if you are wondering whether your web proxies are safe.
Swift 5.9 Brings a Macro System and C++ Interoperability: The new version enhances code generation and compatibility with parameter packs, ownership-based memory management, and if and switch as expressions. Read for insight into the C++ interoperability feature and to know more about the feature updates.
GitGuardian unveils “HasMySecretLeaked” to bring leak detection to DevOps pipelines: This free tool addresses the challenge of safeguarding secrets in cloud-native application development, where secrets can spread across developer tools and end up in personal GitHub repositories. Read if you want to check whether your organization's confidential information is secure.
Node.js 21 is here with updated V8 engine and test runner improvements: The updated V8 engine, now at version 11.8, brings stability, speed, and new capabilities. Read to learn more about performance gains in file system, stream, and HTTP field.
💡Opinions and Analysis🔎
"Swift as C++Successor in FoundationDB" by Konrad Malawski (Strange Loop 2023):This video describes how FoundationDB, a distributed database struggling to modernize its C++ codebase, adopted Swift incrementally, while preserving semantics without bindings. Watch for insights on modernizing legacy systems.
The road to hell is paved with good intentions and C++ modules: Pretty strong language…, but this article is actually about the challenges of integrating C++ modules into build systems, especially Meson. Read to explore a simpler design and understand compatibility issues, file extension problems, and more.
Mojo does give superpowers: Mojo is a new programming language for AI developers that aims to combine the usability of Python with the performance of C while maintaining access to the Python ecosystem of libraries. Read to see how Mojo outperforms Python, Numpy, JAX, and C++.
Better HTTP server routing in Go 1.22: The version is set to introduce a new HTTP server routing multiplexer, enhancing pattern-matching capabilities. Read to learn more about how this new mux simplifies routing and more.
🎓 Tutorials and Guides🤓
How to Sort Unicode Strings Alphabetically in Python: This article addresses the challenges posed by non-Latin characters. Read to get to know the Unicode Collation Algorithm (UCA), learn how to use the pyuca library and the PyICU library to implement UCA-based sorting, and more.
How to scrape Google search results with Python: This comprehensive guide teaches you how to use the SerpApi Python library to scrape Google search results efficiently. Read for guidance on optimizing the process by using multithreading for faster scraping of multiple queries.
Develop with Cocoa for Apple Devices without using Objective-C: This article discusses "c-ocoa" which allows you to interact with MacOS and iOS APIs using a custom C API instead of Objective-C. Read to learn how this technology facilitates the use of the APIs on iOS, Android, and more, through a real-world case-study.
Memory alignment of doubles in C#:This article explores the reasons behind aligning doubles and recommends an 8-byte boundary. Read if you want to understand how the .NET runtime handles the alignment of arrays of doubles, especially in 32-bit applications, and the use of dummy objects.
Mastering Backpressure in Java: Concepts, Real-World Examples, and Implementation: This article delves into backpressure's significance in data streaming, through real-world examples like video streaming services. Read to discover how Java's Flow API makes backpressure implementation effective.
The nuances of base64 encoding strings in JavaScript: JavaScript's Base64 encoding (btoa() and atob()) works smoothly with ASCII text but struggles when dealing with non-ASCII characters like Unicode. Read to solve the problem using TextEncoder for UTF-16 to UTF-8 conversion and TextDecoder for decoding.
How to model a Typescript app using Effect: docgen: This article explores "docgen," an open-source library developed using Effect, focusing on its clear and organized structure. Read to learn how Effect simplifies dependency management and error handling to improve codebase clarity.
🔑 Secret Knowledge: Learning Resources🔬
Swift Everywhere: Using Interoperability to Build on Windows: This article explores Swift's native interoperability with other languages, particularly in the context of the Windows API. Read to learn how Swift embeds the C and C++ compiler to seamlessly work with C libraries and even access modern C++ APIs.
Fast(er) JavaScript on WebAssembly - Portable Baseline Interpreter and Future Plans: Implementing the "Portable Baseline Interpreter” in JavaScript code within a Wasm module can result in speedups without requiring JIT compilation. Read if you are looking for improved execution speed in sandboxed environments.
Building a Japanese Kanji Flashcard App using GPT-4, Python and Langchain: This article explores GPT-4's capabilities to facilitate the learning of Kanji characters by dynamically generating and formatting Kanji data. Read to learn how you can apply advanced AI while developing learning experiences or tools.
Objective-C Internals - Release: This article explores the complexities of implementing the release operation, particularly in the context of ARM architecture and memory ordering requirements. Read to understand the process of decrementing the retain count, handling underflows, and more.
*(char*)0 = 0; -What Does the C++ Programmer Intend With This Code? - JF Bastien - C++ on Sea 2023: This video presentation aims to dissect the intent of the programmer behind this seemingly simple code and discuss what it means in different versions of C++ standards. Read to understand how compilers handle this code, the role of undefined behavior, and the implications on the stack.
C++ Modules: The Packaging Story: This article discusses the advantages of C++ modules (introduced in C++20) over headers and delves into the concept of Binary Module Interfaces (BMIs). Read to understand the need to package module interfaces alongside library binaries and CMake's support for C++ modules.
Let's prototype a JavaScript JIT compiler!: This video demonstrates the creation of a quick and simple JIT compiler, separate from existing codebase, to better understand the potential performance gains. Watch if you are considering the trade-offs between security and want insight into using the JIT compiler.
Systemic TypeScript: This series of articles is focused on making TypeScript more effective for handling complex projects. Read to identify TypeScript features that scale well with complexity while avoiding those that cause complications.
🧠 Expert insights from the Packt Community📚
Here’s an exclusive excerpt from “Chapter 15, Good Design Practices for Your Hexagonal Application” in the book Designing Hexagonal Architecture with Java by Davi Vieira.
Using Domain Driven Design to shape the Domain hexagon
When employing the hexagonal architecture to design a system's code structure, we cannot stress enough how important it is to first implement the Domain hexagon. It's the Domain hexagon that sets the tone for the
development of the entire application.
As long as you keep the code in the Domain hexagon that purely expresses the problem domain—the code that does not merge business concerns with technology ones—you are on the right path to ensuring the encapsulation level that favors a more change-tolerant design. The technique you'll use to develop the Domain hexagon should not be your main concern at this stage—instead, your aim should be to create a Domain hexagon that is focused on the system's purpose, rather than the technology you might use to implement it. So, you can develop the Domain hexagon using your own set of principles, or you can borrow ideas from others who have addressed a similar problem previously.
The advantage of using DDD is that it means you don't need to reinvent the wheel. Most—if not all—of the concepts and principles that you need to model your problem domain are well established in the rich body of knowledge present in DDD techniques. However, this does not mean you must follow all DDD principles to the letter. The recommended approach is to adopt and adapt the things you find helpful for your project.
Next, we'll explore some of the approaches you can follow when using DDD to design the Domain hexagon.
Understanding the business we are in
A good application design reflects a good understanding of the business it is intended to serve. The design journey does not start in the code but by seeking business knowledge. I'm not telling you to become a business expert in the field you intend to build software for. However, I think it's important to understand the fundamentals because if you don't, mistakes made at the start of the design phase can cause irreversible damage that will extend through the software project.
In the best scenario, the project can survive these early mistakes, but not without paying the high cost of tangled and hard-to-maintain software. In the worst scenario, the result is unusable software, and starting a new project from scratch is the best thing to do.
Understanding the business fundamentals is the first thing we should do. The business details are important too, and we should pay close attention to them if we want to make top-notch software. But mistakes relating to details aren't as serious as mistakes relating to fundamentals. The former is generally easier and cheaper to fix than the latter.
Let's revisit the topology and inventory system for a moment. We have a business rule stating that only edge routers from the same country can be connected to each other. We use the edge routers to handle regional traffic because they have less traffic capacity than core routers. The core routers can be located in different countries because they have more traffic capacity.
The whole domain model has been built based on these business premises. We compromise the entire system development if we fail to understand and translate these business premises into a cohesive domain model. Everything we build on top of such a model will be based on weak or wrong assumptions. That's why we need to spend whatever time is necessary to grasp the business fundamentals.
Now, let's see some of the techniques we can use to build business knowledge.
Business Model Canvas
An excellent exercise to understand how the business works can be done with the Business Model Canvas technique. A Business Model Canvas is a tool to create business models. It provides instruments to analyze and understand the main elements of a business. By providing a structured and simplified way to identify a business's main aspects, the Business Model Canvas can be the starting point to draw the big picture you and your team need to understand the business fundamentals.
The tool's main benefit is its focus on the key elements that are crucial for the profitability of a business. Another helpful aspect is how it represents customers and partners in the overall business landscape. This helps us to understand how well the business model is fulfilling the expectations of both customers and partners.
A disadvantage is that it does not provide a deep and comprehensive view of how a business should operate to produce good results. Also, it does not touch on the business strategy. Much of its emphasis is on end results instead of long-term goals.
There is a variation of—and an alternative to—the Business Model Canvas called the Lean Canvas, which is more directed toward start-ups. The main difference of this approach is that it focuses on the high uncertainty level that start-ups face when they try to develop new ideas and products.
Here is an illustration of the Business Model Canvas:
Figure 15.1 – The Business Model Canvas
As we can see in the preceding figure, the Business Model Canvas lets us structure each business aspect in distinct parts. This separation helps us to visualize the main elements comprising the business. Here are the elements of the Business Model Canvas:
The Key Partners element represents our key partners and suppliers and contains information about the key resources or activities that are involved in that relationship.
In Key Activities, we state the value propositions required for the key activities.
For Key Resources, we need to identify the value propositions required to enable the key resources.
In Value Propositions, we describe the elements of value we intend to deliver to the customer.
The Customer Relationships element is about the expectations of each customer segment in establishing and maintaining a relationship with us.
In Channels, we identify the communication channels through which our customer segments will reach us.
The Customer Segments element represents the groups of people we want to deliver value to.
The Cost Structure element describes the highest costs involved in enabling the business model.
The Revenue Streams element shows the value our customers are really willing to pay for.
In addition to the Business Model Canvas, we also have the Event Storming technique as an alternative, which is geared more toward DDD projects. Let's examine it now.
Event Storming
If you do not find the Business Model Canvas a suitable approach, another technique called Event Storming can help you understand your business needs. Created by Alberto Brandolini, Event Storming uses colored sticky notes to map business elements into domain events, commands, actors, and aggregates.
Each one of these sticky note elements has its own color, as shown in the following flowchart:
Figure 15.2 – The Event Storming technique
As we can see in the preceding diagram, the sticky notes from Event Storming use the same terminology we encounter when dealing with DDD. That's because Event Storming was created especially for those who use DDD and need to understand the business requirements for their project.
The Event Storming sessions should be conducted by developers, domain experts, and a facilitator who coordinates the session to ensure the mapping efforts go in the right direction.
The starting point of an Event Storming session is usually a challenging business process to model. In these sessions, it's common to discuss how actors and their actions influence the business processes. Another central point is how external systems support and interact with the business processes. Risks and pain points are also essential subjects to map to identify business-critical areas.
Once we understand how the business works, we need to translate that knowledge into a domain model. In the next section, we'll see how collaboration can help us to be better prepared for creating a good domain model.
Promoting collaboration to increase knowledge
The domain model is the outcome of people trying to understand the business and translating that understanding into code. In order to get the most out of this process, collaboration plays a vital role where the degree of complexity is high and things are hard to accomplish. To overcome this complexity, we need to establish a collaborative atmosphere where everyone involved in the project can contribute with relevant information that helps to build the big picture. The collaborative approach helps to ensure that everyone is on the same page regarding the problem domain, leading to a domain model that better reflects the business concerns.
Aside from using the code itself to capture and convey the problem domain knowledge, written documentation is another useful tool for collaboration. I'm not talking about writing long and comprehensive documentation – I mean the opposite. Let me explain.
Concise documentation that is focused on explaining the building blocks of a system can help people who aren't acquainted with the code to take their first steps into understanding the system and, consequently, the problem domain. Sometimes, an introduction to the system's main elements quickly leads to a comprehensive understanding of the problem domain.
What I'm saying may seem obvious, but very often, I've stumbled upon a complex code base with poor or no documentation at all. When the problem domain is complex, it's natural for the code to be complex too. Without documentation to explain the system, what's already complicated becomes even harder to grasp.
I recommend allocating some time at the end of the project to write the system documentation. New joiners, in particular, will benefit from a friendly document providing an overview of the system's big picture.
Now that we know how important it is to have a solid foundation based on an understanding of the business requirements and have discussed the value of collaboration in increasing our knowledge of the problem domain, let's explore some of the DDD techniques adopted when building the Domain hexagon.
Applying DDD techniques to build the Domain hexagon
In this section, we'll explore some design practices to help us establish clear boundaries in the hexagonal system...
Subdomains
The purpose of a subdomain is to group the elements that support the core domain but cannot be considered elements that express the core domain. These supporting elements are essential for the activities conducted by the core domain. Without the supporting elements, the core domain cannot work. There are also generic subdomains whose purpose is to provide additional capabilities to both core domains and supporting subdomains. A generic subdomain works as a standalone component that doesn't depend on things provided by other domains.
We can say that in the core domain, we have primary activities. And in the subdomain, we have secondary activities that enable the primary ones. If we blend primary and secondary activities, we'll end up with a domain model with mixed concerns. It may not be a big deal for smaller systems, but in larger ones, it can add a considerable complexity that can undermine the productivity of anyone trying to understand the system. That's why it's a good approach to break a domain into subdomains. We'll always have a core domain concentrating on the most important part of the code.
Let's use a banking system as an example to explore the subdomain idea further. In such a system, it's possible to identify the following domains:
As a core domain, we have Transactions that allow users to receive and send money.
As supporting subdomains, we may have Loans and Insurances that add more capabilities to the system but rely on the Transactions core domain to enable such capabilities.
Finally, we have Authentication as a generic subdomain, serving both the core domain and supporting subdomains that require every transaction to be authenticated.
The following diagram shows how subdomains relate to the core domain:
Figure 15.3 – Banking system subdomains
The Transactions core domain contains the system's building block elements. These elements are also present in the Loans and Insurances subdomains, but for different purposes. The generic Authentication subdomain knows nothing about the other domains. It only provides an authentication mechanism that is shared across the core domain and supporting subdomains.
Ubiquitous Language
One of DDD's touchstones is its emphasis on how we use language to describe a domain model. This emphasis aims to avoid the pitfall of ambiguities in our general communication seeping into the system code we want to create.
As human beings, we have much more capacity than computers to handle ambiguities in language because we can add context to our words. Computers, on the other hand, don't have this ability unless we provide it for them. In order to decrease the ambiguity level of a system, a Ubiquitous Language seeks precise terminology to describe the things that comprise the domain model.
Defining precise terminology, however, is not enough to ensure that we'll always convey the right meaning in the domain model, as similar words may have a different meaning depending on the context in which they are used. That's why there's another technique in DDD called bounded context that we can use to deal with differences in meaning within a domain model.
Bounded context
The bounded context idea is a response to the fact that words have a different meaning depending on the context in which they are used. When we bring this idea to DDD, we may find that a domain model element can have a different meaning or behave differently depending on the context where it's applied. If we do not actively take action to explicitly define a context to clarify the meaning of such a domain model element, we are contributing to the ambiguity within the system.
For example, take the topology and inventory system. Suppose that other than inventory capabilities, we want to allow the system to get real-time status and basic information from routers and other network equipment. This new feature could result in two contexts: one for inventory and the other for status.
From the inventory perspective, a router means a static record in a database. On the other hand, from the status perspective, a router is a living thing that issues real-time data. By expressing this distinction in the form of a bounded context, we ensure that our understanding of one context does not blur with another. More than that, by structuring the code within the clear boundaries that a bounded context can provide, we're creating a system that can evolve and receive changes in a more organized way. Also, we are enforcing the Single Responsibility Principle at the level of modules. This means a module should change only for a single reason and not multiple reasons.
The DDD techniques discussed in this session don't offer much value if we don't first grasp our business needs. That's why we started by exploring some of the techniques we can use to enhance our understanding of the business model. Once we know about the business we're in, we can safely employ the DDD techniques (such as subdomains and bounded contexts) to establish boundaries between different system components and remove ambiguities within the domain model.
Designing Hexagonal Architecture with Java by Davi Vieira was published in September 2023. Buy the book here or signup for a Packt subscription to access the entire Packt digital library.
🛠️ HackerHub: Useful Tools ⚒️
PixieBrix (Sponsored): a browser extension that empowers you to customize and enhance the functionality of websites, allowing you to streamline interfaces, automate tasks, and integrate with popular business services like Asana, Google Workspace, and more.
SKIE: an open-source tool by TouchLab which simplifies Kotlin and Swift integration, preserving Kotlin features for iOS API design.
MemGPT: a Discord chatbot that intelligently manages memory tiers for extended context, offering perpetual conversations and groundbreaking possibilities.
trufflehog: a robust tool for detecting secrets and credentials across various sources, offering 700+ detectors, support for GitHub, GitLab, S3, and more.
📢 If your company is interested in reaching an audience of developers, software engineers, and tech decision makers, you may want to advertise with us.
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.
If you have any comments or feedback, take the survey!