Why you should consider using the C++ POCO library?

The POCO C++ Libraries (POCO stands for “Portable Components”) is a collection of open-source C++ class libraries that simplify and accelerate the development of network-centric, portable applications in C++. These libraries provide a wealth of features, ranging from HTTP and HTTPS clients and servers, to XML parsing, to data encryption, to threading support, and much more.

We’ve relied on the POCO library for over 15 years to verify whether CppDepend accurately evaluates well-implemented projects. Therefore, this assessment is not drawn from a fleeting encounter with the library but from a thorough analysis of its many versions over the past 15 years.

Let’s explore a code snippet from the POCO source code:

This method implementation is characterized by:

  • Has a few parameters.
  • Assert technique is used to check if the entries are OK.
  • The  variable names are easy to understand.
  • The method is short.
  •  No extra comments in the body. The code explains itself.
  • The function body is well indented.
  • The STL library is used when needed.

When delving into the POCO source code, one can readily observe the consistency of its implementation, as the same best practice rules are applied to each function. Upon exploring the source code, it becomes apparent that POCO is approachable even for C++ beginners. Specifically, POCO has the following characteristics:

  1. It’s not over-engineered, and one doesn’t need to possess advanced C++ skills to comprehend its implementation.
  2. The public classes provided to end users are well-organized and straightforward to utilize.
  3. The design is modular, with the library divided into several projects, each addressing a specific need.
  4. For those seeking advanced utilization of the library, extending, customizing, or modifying the behavior of certain classes is remarkably straightforward.

In this post we will focus on some keys of its design:

ABSTRACT VS INSTABILITY

Robert C.Martin wrote an interesting article about a set of metrics that can be used to measure the quality of an object-oriented design in terms of the interdependence between the subsystems of that design.

Here’s from the article what he said about the interdependence between modules:

What is it that makes a design rigid, fragile and difficult to reuse. It is the interdependence of the subsystems within that design. A design is rigid if it cannot be easily changed. Such rigidity is due to the fact that a single change to heavily interdependent software begins a cascade of changes in dependent modules. When the extent of that cascade of change cannot be predicted by the designers or maintainers the impact of the change cannot be estimated. This makes the cost of the change impossible to estimate. Managers, faced with such unpredictability, become reluctant to authorize changes. Thus the design becomes rigid.

And to fight the rigidity he introduce metrics like Afferent coupling, Efferent coupling, Abstractness, Instability and the “distance from main sequence” and the “Abstractness vs Instability” graph.

The “Abstractness vs Instability” graph can be useful to identify the projects  difficult to maintain and evolve. Here’s the “Abstractness vs Instability” graph of the POCO library:

The idea behind this graph is that the more a code element of a program is popular, the more it should be abstract. Or in other words, avoid depending too much directly on implementations, depend on abstractions instead. By popular code element I mean a project (but the idea works also for packages and types) that is massively used by other projects of the program.
It is not a good idea to have concrete types very popular in your code base. This provokes some Zones of Pains in your program, where changing the implementations can potentially affect a large portion of the program. And implementations are known to evolve more often than abstractions.

The main sequence line (dotted) in the above diagram shows the how abstractness and instability should be balanced. A stable component would be positioned on the left. If you check the main sequence you can see that such a component should be very abstract to be near the desirable line – on the other hand, if its degree of abstraction is low, it is positioned in an area that is called the “zone of pain”.

Only the Fondation project is inside the zone of pain , which is normal because it’s very used by the other projects. and contains mostly utility classes which are not abstracts.

TYPE COHESION

The single responsibility principle states that a class should not have more than one reason to change. Such a class is said to be cohesive. A high LCOM value generally pinpoints a poorly cohesive class. There are several LCOM metrics. The LCOM takes its values in the range [0-1]. The LCOMHS (HS stands for Henderson-Sellers) takes its values in the range [0-2]. Note that the LCOMHS metric is often considered as more efficient to detect non-cohesive types. LCOMHS value higher than 1 should be considered alarming.

Only 1% of types are considered as no cohesive.

In this post, we’ve offered a brief glimpse into the design of POCO. In upcoming posts, we’ll explore its design and implementation in greater detail to understand why this library stands out as one of the well-implemented open-source C++ libraries.

C++ always comes to the rescue for challenging problems: the llamafile case study is a prime example.

C++ has been instrumental in resolving numerous challenging problems across various domains due to its efficiency, performance, and versatility. Some of the challenging problems resolved by C++ include:

  1. System Software Development: C++ has been extensively used in developing system software such as operating systems (e.g., Windows, Linux), device drivers, and embedded systems due to its low-level capabilities and ability to interact closely with hardware.
  2. Game Development: C++ is widely employed in the game development industry to create high-performance and resource-efficient games. Its ability to manage memory and provide low-level access to hardware makes it suitable for developing game engines and graphics-intensive applications.
  3. High-Performance Computing: C++ is a preferred choice for developing high-performance computing applications, including simulations, scientific computing, and numerical analysis. Its ability to optimize code for speed and efficiency allows for faster execution of complex algorithms.
  4. Financial Systems: C++ is commonly used in developing financial systems and trading platforms due to its speed and reliability. It is crucial in building algorithmic trading systems, risk management software, and market analysis tools.
  5. Networking and Telecommunications: C++ is utilized in networking and telecommunications for building efficient network protocols, routers, and communication software. Its ability to handle low-level network operations and optimize network performance makes it invaluable in this domain.

These are just a few examples of the challenging problems resolved by C++, showcasing its wide-ranging applicability and importance across various industries and domains.

C++ remains the preferred language for tackling contemporary challenges, as evidenced by projects like Mozilla’s llamafile.

Large language models are advanced artificial intelligence systems designed to understand and generate human-like text. These models are trained on vast amounts of text data and utilize sophisticated algorithms to process and generate responses. And a llamafile is an executable LLM that you can run on your own computer. It contains the weights for a given open LLM, as well as everything needed to actually run that model on your computer. There’s nothing to install or configure . So the goal is to make open LLMs much more accessible to both developers and end users. This great work is done by combining  llama.cpp with Cosmopolitan Libc into one framework that collapses all the complexity of LLMs down to a single-file executable (called a “llamafile”) that runs locally on most computers, with no installation.

llamafile is based on two major components:

Cosmopolitan Libc:
Cosmopolitan Libc makes C a build-once run-anywhere language, like Java, except it doesn’t need an interpreter or virtual machine. Instead, it reconfigures stock GCC and Clang to output a POSIX-approved polyglot format that runs natively on Linux + Mac + Windows + FreeBSD + OpenBSD + NetBSD + BIOS with the best possible performance and the tiniest footprint 

llama.cpp:

The main goal of llama.cpp is to enable LLM inference with minimal setup and state-of-the-art performance on a wide variety of hardware – locally and in the cloud.

Advantages of using llamafile:

  1. llamafiles can run on multiple CPU microarchitectures. We added runtime dispatching to llama.cpp that lets new Intel systems use modern CPU features without trading away support for older computers.
  2. llamafiles can run on multiple CPU architectures. We do that by concatenating AMD64 and ARM64 builds with a shell script that launches the appropriate one. Our file format is compatible with WIN32 and most UNIX shells. It’s also able to be easily converted (by either you or your users) to the platform-native format, whenever required.
  3. llamafiles can run on six OSes (macOS, Windows, Linux, FreeBSD, OpenBSD, and NetBSD). If you make your own llama files, you’ll only need to build your code once, using a Linux-style toolchain. The GCC-based compiler we provide is itself an Actually Portable Executable, so you can build your software for all six OSes from the comfort of whichever one you prefer most for development.
  4. The weights for an LLM can be embedded within the llamafile. We added support for PKZIP to the GGML library. This lets uncompressed weights be mapped directly into memory, similar to a self-extracting archive. It enables quantized weights distributed online to be prefixed with a compatible version of the llama.cpp software, thereby ensuring its originally observed behaviors can be reproduced indefinitely.
  5. Finally, with the tools included in this project you can create your own llamafiles, using any compatible model weights you want. You can then distribute these llamafiles to other people, who can easily make use of them regardless of what kind of computer they have.

To resume, thanks to C++, it helped always to resolve the challenging problems in an efficient way, and we can’t imagine the programming world without this amazing programming language 🙂

Testing if the newcomer Llama3 is beneficial for c++ developers

AI has become prevalent in various domains, including software development. Many developers leverage generative AI to aid them in coding. Let’s explore the newcomer Llama3 and assess its suitability for C++ developers.

Related to Meta here’s a brief description of Llama3:

Our new 8B and 70B parameter Llama 3 models are a major leap over Llama 2 and establish a new state-of-the-art for LLM models at those scales. Thanks to improvements in pretraining and post-training, our pretrained and instruction-fine-tuned models are the best models existing today at the 8B and 70B parameter scale. Improvements in our post-training procedures substantially reduced false refusal rates, improved alignment, and increased diversity in model responses. We also saw greatly improved capabilities like reasoning, code generation, and instruction following making Llama 3 more steerable.

Certain developers may lack interest in AI generative tools due to their perception that the results are not yet mature. This sentiment is particularly pronounced among expert developers who swiftly identify areas for improvement in generated code. Nonetheless, I believe that for the majority of developers, generated code could serve as a valuable starting point for implementation, refactoring, or explanation purposes.

Let’s discover if Llama3 is suitable for C++ developers or not.

New coding:

We asked Llama3 to implement the dining philosophers problem in modern C++, and the outcome is interesting. It effectively utilizes modern C++ features, resulting in clean and comprehensible code.

However, we wonder if Llama3 is trained to utilize the most commonly used C++ libraries. To investigate this, we instructed it to employ the Boost library for implementing certain algorithms, and the outcome is impressive. LLama3 demonstrates adept utilization of Boost features.

Similarly, we tested Llama3’s proficiency with the Qt library by requesting it to implement a login form. Once again, the results are noteworthy, showcasing Llama3’s capabilities in utilizing the Qt library effectively.

Code Refactoring

After testing the refactoring of some pieces of C++ code, we remark that the refactoring not concern only these aspects:

  • The variable renaming.
  • Remove duplicate code.
  • Reformat code style.
  • Removing unecessary code.
  • Modernizing C++ code.

But it refactor also the design by splitting methods in many other methods to make the code more clean and more maintainable.

Explains existing code:

Understanding a legacy C++ code become an important task, specially for new developers joining a C++ project. And asking Llam3 to explain a piece of code worth it, it describe in details what the code does.

Master C++ features:

When prompted to discuss a C++ feature, LLama3 provides concise documentation accompanied by numerous examples.

Conclusion:

Following our tests, we’ve found that Llama3 serves as an excellent assistant for C++ developers. It proves beneficial for tasks such as new coding, refactoring, explaining legacy code, and mastering C++ features. Therefore, to all C++ developers, I recommend giving it a try—you may be pleasantly surprised by its results.

The single C++ line that is worth millions of dollars.

Many developers has already heard about the Ariane5 bug , it was one of the most infamous software failures in the history of aerospace engineering. It occurred on June 4, 1996, during the maiden flight of the Ariane 5 rocket, which was intended to launch four Cluster satellites into orbit to study Earth’s magnetosphere.

The bug itself was a software issue related to the guidance system of the rocket. The software component responsible for converting a 64-bit floating-point value to a 16-bit signed integer for use in the guidance system caused an unhandled exception due to an overflow error. So finally one line of code costs millions of dollars and make the Ariane 5 launch is widely acknowledged as one of the most expensive software failures in history.

But in the other side do you know which line of code worth million of dollars?

It was this magic C++ line : i = 0x5f3759df – ( i >> 1 );

This line was introduced first in the code of Quake to optimize the calculation of the inverse square root.

float Q_rsqrt(float number)
{
  long i;
  float x2, y;
  const float threehalfs = 1.5F;

  x2 = number * 0.5F;
  y  = number;
  i  = * ( long * ) &y;                       // evil floating point bit level hacking
  i  = 0x5f3759df - ( i >> 1 );               // what the fuck?
  y  = * ( float * ) &i;
  y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
  // y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed

  return y;
}

Why optimizing Inverse square root is so important?

Inverse square roots find utility in video game graphics, particularly within the realm of 3D game engines. Various aspects of game programming, such as pathfinding, lighting, and reflections, heavily rely on vector normalization, a process that necessitates an inverse square root operation. However, performing inverse square roots, which involve floating-point division, can be computationally costly for processors. In fast-paced and visually immersive games like Quake III Arena, these computations occur millions of times per second. Therefore, even a slight enhancement in the performance of such calculations could notably augment the speed of graphics computation and ultimately enhance the game’s frame rate. To circumvent the resource-intensive nature of the inverse square root function, the programmers of the id Tech 3 engine devised an exceptionally precise and rapid approximation.

Without this clever optimization, perhaps Quake would not have achieved its status as a benchmark in the gaming industry.

Who is the brilliant mind behind this innovative solution?

Rys Sommerfeldt, Senior Manager of the European Game Engineering Team at AMD RTG, launched an investigation into the function’s origins in 2004. And finally it appears that Greg Walsh is the author. Greg Walsh is a monument in the world of computing. He helped engineer the first WYSIWYG (“what you see is what you get”) word processor at Xerox PARC and helped found Ardent Computer. Greg worked closely with Cleve Moler, author of Matlab, while at Ardent and it was Cleve who Greg called the inspiration for the Fast Inverse Square Root function.

Morale of the story

For some problems, take your time and think outside the box. Thinking outside the box is about breaking away from conventional or traditional ways of thinking and exploring unconventional, innovative, and creative solutions to problems. So when the problem is difficult to resolve, take your time to try exploring it from different sides, maybe you could find a solution that surpass your exceptations.

Be prepared to work soon with a C++ agent.

Perhaps within two years or even sooner, developers could find themselves having a conversation like this:

“Which C++ agent are you utilizing?”

“I’m using the X agent.”

“And does it contribute to cleaner code with fewer bugs?”

“Yes, it’s fantastic! My C++ code has been modernized.”

“What about the application design?”

“My agent has been trained to implement design patterns. Additionally, I’ve provided it with training data to incorporate the best C++ idioms.”

So why are we quickly approaching a future where humans collaborate with agents to accomplish our tasks? Because major players in AI are pushing for the rapid release of AI agents.

AI agents, also known as intelligent agents, are software entities that perceive their environment and take actions to achieve specific goals. These agents are a fundamental concept in artificial intelligence and are widely used in various applications, ranging from simple automation tasks to complex decision-making systems. Here are some key points about AI agents:

  1. Goal-Oriented Behavior: AI agents are typically designed to achieve specific goals or objectives. These goals can range from simple tasks like navigating a maze to more complex objectives such as winning a game or optimizing resource allocation in a manufacturing plant.
  2. Autonomy: AI agents operate autonomously, meaning they can make decisions and take actions without direct human intervention. They have the ability to adapt and respond to changes in their environment, making them suitable for dynamic and unpredictable scenarios.
  3. Learning and Adaptation: Many AI agents are capable of learning from experience and improving their performance over time. This can involve various learning techniques such as supervised learning, reinforcement learning, or evolutionary algorithms. By learning from past interactions, agents can become more effective at achieving their goals.
  4. Types of Agents: AI agents can be classified into various types based on their capabilities and behavior. For example, reactive agents simply respond to stimuli in their environment, while deliberative agents plan and reason about their actions. Hybrid agents combine multiple approaches to achieve more complex behavior.
  5. Applications: AI agents are used in a wide range of applications across different domains. In robotics, agents control the movement and behavior of robots in various environments. In virtual assistants, agents interpret user queries and perform tasks on their behalf. In finance, agents can execute trades based on market data and predictive analytics.
  6. Challenges: Designing effective AI agents involves addressing various challenges, such as ensuring robustness to uncertain and noisy environments, dealing with incomplete or inaccurate information, and balancing exploration and exploitation in decision-making.

Overall, AI agents play a crucial role in artificial intelligence research and applications, providing a framework for building intelligent systems that can perceive, reason, and act in complex environments. As AI technology continues to advance, the capabilities of AI agents are expected to grow, enabling new possibilities for automation, decision support, and intelligent interaction.

The new C++ standards must anticipate the coming AI tsunami.

The significant and rapid transformation driven by advancements in artificial intelligence (AI) technology promise a very big AI tsunami that will change our life as developers. While the exact nature of these changes can vary depending on context and perspective, there are several broad trends and potential impacts that might be expected following such a transformative event:

  1. Automation of Routine Tasks: With the advancement of AI algorithms and robotics, routine tasks across various industries could be automated at a scale never seen before. This could lead to increased efficiency and productivity in sectors like manufacturing, logistics, and customer service.
  2. Job Displacement and Reskilling: The widespread adoption of AI-driven automation may lead to job displacement in certain sectors, as tasks traditionally performed by humans become automated. This could necessitate significant efforts in workforce reskilling and upskilling to adapt to the changing job market and enable people to transition to new roles that require more creative or complex problem-solving skills.
  3. Enhanced Personalization and User Experience: AI technologies enable the analysis of vast amounts of data to personalize products, services, and experiences for individuals. This could lead to more tailored recommendations, better customer service interactions, and more intuitive user interfaces across various digital platforms.
  4. Rapid Innovation and Disruption: The AI tsunami could accelerate innovation across numerous sectors, leading to the emergence of new products, services, and business models. This rapid pace of change may also result in disruption for incumbent players who fail to adapt to the evolving technological landscape.
  5. New Opportunities for Collaboration: Addressing the complex challenges and opportunities presented by AI will likely require collaboration among diverse stakeholders, including governments, businesses, academia, and civil society organizations. This could lead to new forms of partnerships and collaborations aimed at harnessing the potential of AI while mitigating its risks.

Every industry must adjust to this new context, and programming languages are no exception. In this scenario, code generation by robots will likely dominate, with humans primarily tasked with reviewing the output. Consequently, programming languages will become more tailored to machines rather than humans. This shift will change a lot of things concerning the priority of the new standards features.

For example, recently a big debat was initiated concerning the C++ safety. However with the AI robots, this issue will not be the most important. because the robots will be trained using the most well developped C++ projects and the basic C++ errors producing a not safe C++ code will disapear.

The good news for C++ is that it can be the most prefered language by the AI robots compared to the other programming languages, indeed C++ has many advantages:

  1. Performance: C++ is known for its high performance and efficiency, making it ideal for applications that require fast execution speeds and low-level system access. Its ability to directly manipulate memory and optimize code makes it suitable for resource-intensive tasks such as game development, embedded systems, and real-time applications.
  2. Portability: C++ code can be compiled to run on various platforms with minimal modifications, offering excellent portability across different operating systems and hardware architectures. This makes C++ a versatile choice for developing software that needs to run on multiple platforms.
  3. Control: C++ provides developers with fine-grained control over system resources and hardware, allowing for efficient resource management and optimization. This level of control is essential for developing performance-critical applications and low-level system software.
  4. Flexibility: C++ is a multi-paradigm programming language that supports both procedural and object-oriented programming paradigms, as well as generic programming techniques. This flexibility enables developers to choose the most suitable programming approach for their specific project requirements.
  5. Rich Standard Library: C++ comes with a rich standard library that provides a wide range of functionality for common programming tasks, including data structures, algorithms, file I/O, and networking. The standard library’s comprehensive nature reduces the need for external dependencies and simplifies development.
  6. Scalability: C++ is well-suited for developing scalable software solutions, from small embedded systems to large-scale enterprise applications. Its performance, control, and flexibility make it a reliable choice for projects of varying sizes and complexities.

Thus, AI robots could effortlessly circumvent C++’s drawbacks such as safety concerns, its perceived complexity, and the steep learning curve. They could instead capitalize on its myriad advantages. Nonetheless, it is imperative for the C++ standards committee to proactively prepare for the impending AI revolution by introducing features that render C++ more accommodating for AI robots.

The next successful programming language will be the one that best suits the needs of AI robots, rather than simply being favored by human developers 🙂

C++ creator rebuts White House warning, but there’s no smoke without fire :)

In a March 15 response to an inquiry from InfoWorld, Stroustrup pointed out strengths of C++. “I find it surprising that the writers of those government documents seem oblivious of the strengths of contemporary C++ and the efforts to provide strong safety guarantees,” Stroustrup said. 

And Stroustrup cited a fact about the origin of the issue :

There are two problems related to safety. Of the billions of lines of C++, few completely follow modern guidelines, and peoples’ notions of which aspects of safety are important differ.

This highlights a significant problem with C++. When any programming language permits the execution of potentially harmful actions, it shouldn’t come as a surprise that a considerable portion of developers may misuse it.

And when confronted about writing bad code, developers may offer various arguments to justify their actions, though these are often excuses rather than valid reasons:

  1. Tight Deadlines: “I had to rush because of tight deadlines. There wasn’t enough time to write clean code.”
  2. Legacy Code: “The existing codebase is messy and poorly structured. My changes just blend in with the existing mess.”
  3. Scope Creep: “The requirements kept changing throughout the project, making it difficult to maintain clean code.”
  4. Technological Constraints: “The technology stack we’re using isn’t suitable for writing clean code. We’re limited by what we have.”

So yes the developers have a responsibility to ensure they develop their code properly in C++. However, this kind of approach could be risky for the futur of C++. Just few years ago we have suprisingly assisted to the Nokia failure. Indeed, Nokia’s decline from being the world’s leading mobile phone manufacturer to struggling in the market is a story marked by several factors and strategic missteps. One of Nokia’s critical mistakes was its decision to stick with its Symbian operating system for too long. While Symbian was once a dominant platform, it struggled to compete with the user experience offered by iOS and Android.

In C++ we stick for too long with the current memory management mechanism and no radical solution is suggested, only few improvements that need to be applied by the developers.

C++ vs .Net startegy:

C# was developed in 2000 primarily for Windows machines. Miguel de Icaza created Mono to enable its use on Linux and Mac OSX. However, after over a decade of predominantly using the standard .Net framework on Windows, a significant issue arose regarding the language’s portability. To address this, Microsoft collaborated with Miguel to create .Net Core, a subset of .Net designed to function on other operating systems.

This is not a step by step solution to resolve the portability issue, but a radical one even if the legacy code is not compatible. at this time  Miguel de Icaza describes .NET Core as a “redesigned version of .NET that is based on the simplified version of the class libraries”,and Microsoft’s Immo Landwerth explained that .NET Core would be “the foundation of all future .NET platforms“.

And finally this solution worked perfetly and .Net core become widely used, and the big portability issue is resolved.

Ultimately, this solution proved highly effective, with .Net Core becoming widely adopted, successfully resolving the significant portability issue.

Why not take a similar approach with C++ to definitively address the safety concerns? Why not develop a safe subset of C++ and provide the option to work with this subset through the compiler?

clang –safe

Conclusion:

If C++ continues to allow developers to engage in unsafe memory practices, this significant safety concern will persist, potentially leading to other languages such as Rust or Go being preferred for new projects. Maybe, it’s time to think to a radical solution rather than step by step improvements. Certainly, experience has demonstrated that despite the availability of modern features in C++ aimed at addressing safety concerns for over a decade, the issue persists due to the language’s continued allowance of legacy bad practices.

What attempts have been made to bring memory safety to C++?

C++ is a powerful and widely used programming language known for its flexibility and performance. However, one of its historical drawbacks has been the lack of built-in memory safety features, which can lead to various types of memory-related bugs such as buffer overflows, dangling pointers, and memory leaks.

This is a known issue that has persisted for decades, and numerous attempts have been made to find a solution. Unfortunately, none have succeeded.

What has been done in the past to enhance memory safety within the language?

Continue reading “What attempts have been made to bring memory safety to C++?”

Make your C++ code more safer by enabling the native compiler Runtime Checks.

Runtime checks in C++ refer to mechanisms or tools used to detect errors, vulnerabilities, or unexpected behavior in a program while it is executing. These checks are performed dynamically during runtime rather than at compile-time and can help identify issues that may not be apparent during static analysis or code review.

Continue reading “Make your C++ code more safer by enabling the native compiler Runtime Checks.”