DEV Community

Cover image for Forging the Future of Developer Experience
Leo ___
Leo ___

Posted on

Forging the Future of Developer Experience

Every once in a while, a developer scratches an itch so persistent it turns into something bigger. That’s exactly what CppForge is: a response to the pain of boilerplate, inconsistencies, and the lack of elegant BDD tooling in C++.

CppForge isn’t just another framework. It’s a developer-first, test-driven, and scaffold-powered engine designed to elevate the experience of writing, testing, and maintaining C++ applications.


🧱 Why I Started This

It began with a vision: building my own portable cloud, powered by a cluster of Raspberry Pis — not in a datacenter, but right at home. I wanted services I could control, scale, and take with me. Not just as a personal cloud, but as a resilient, modular system that could one day run anywhere.

To get there, I needed the right tools — tools that understood structure, automation, and developer-first thinking. Most C++ systems lacked that. They were brittle, boilerplate-heavy, and far from portable.

CppForge is my way of changing that — by building a framework that can scaffold services, generate testable modules, and orchestrate clusters with ease. It's not just about better code — it's about creating the backbone for portable, self-sovereign cloud systems.


🔍 What CppForge Solves

  • 🧪 Full BDD support in C++ with scenario-based test generation
  • 🛠 Template-powered scaffolding: libraries, executables, and testable interfaces
  • 💡 Feature-focused development: think in terms of outcomes, not just files

🧬 The Vision

CppForge isn't just for scaffolding or testing — it's laying the groundwork for a developer operating system for C++. Imagine a platform where:

  • You write your use case in plain language
  • The engine scaffolds the entire architecture
  • Tests, interfaces, and integrations are wired in from the start
  • You focus only on what matters: business logic

But a vision is only as powerful as the tools it delivers. So here’s what’s already working — and why it’s changing the game:


🧰 Scaffolding Engine

CppForge can generate fully structured modules — libraries or executables — with just a single scenario description. You define what the system should do, and CppForge builds the folder structure, CMake config, and interface contracts.

Think: monitor.bddmonitor/src, monitor/include, CMakeLists.txt, main.cpp, test stubs — all automatically created.

./agent
├── CMakeLists.txt
├── include
│   ├── agent.hpp
│   └── agent_factory.hpp
├── src
│   ├── agent.cpp
│   └── main.cpp
└── test
    ├── CMakeLists.txt
    ├── test_1_agent_heartbeat_agent_sends_heartbeat.cpp
    ├── test_2_monitor_local_services_docker_is_active.cpp
    ├── test_2_monitor_local_services_k3s_is_inactive.cpp
    ├── test_3_agent_package_reporting_agent_lists_all_packages.cpp
    ├── test_3_agent_package_reporting_agent_lists_simplified_packages.cpp
    ├── test_4_remote_command_execution_execute_shell_command_on_target_node.cpp
    ├── test_4_remote_command_execution_handle_command_timeouts.cpp
    ├── test_4_remote_command_execution_return_execution_result_to_master.cpp
    ├── test_4_remote_command_execution_sanitize_and_validate_incoming_commands.cpp
    └── test_main.cpp

Enter fullscreen mode Exit fullscreen mode

🧪 Scenario-Driven Test Generation

At the heart of CppForge is a test-first mindset. Developers write features in plain English using BDD-style syntax, and CppForge translates them into structured, ready-to-run C++ test scaffolds using Google Test.

This approach bridges the gap between behavioral expectations and actual test code — enforcing structure, encouraging clarity, and ensuring nothing gets implemented without a test.

📜 Example Feature Spec

A developer defines a feature like this:

Feature: Monitor Local Services

  Scenario: Docker is active
    Given Docker is installed
    When the agent checks for running services
    Then Docker should be reported as running

  Scenario: K3s is inactive
    Given k3s is not running
    When the agent checks for running services
    Then it should report k3s as inactive
Enter fullscreen mode Exit fullscreen mode

CppForge then automatically generates a test file with:

  • A virtual interface class representing the scenario
  • A stub implementation that causes the test to fail until implemented
  • A factory method forge_bdd_steps() to swap in the real implementation when ready
  • A runnable Google Test case that exercises the scenario
#include <gtest/gtest.h>
#include <iostream>
#include <memory>

// Step Interface
class scn_2_monitor_local_services_docker_is_active {
public:
    virtual void given_docker_is_installed() {
        FAIL() << "[STEP NOT IMPLEMENTED] Given Docker is installed";
    }
    virtual void when_the_agent_checks_for_running_services() {
        FAIL() << "[STEP NOT IMPLEMENTED] When the agent checks for running services";
    }
    virtual void then_docker_should_be_reported_as_running() {
        FAIL() << "[STEP NOT IMPLEMENTED] Then Docker should be reported as running";
    }

    virtual ~scn_2_monitor_local_services_docker_is_active() = default;
};

// Stub fallback
class stub_scn_2_monitor_local_services_docker_is_active : public scn_2_monitor_local_services_docker_is_active {};

#ifdef HAS_IMPL_scn_2_monitor_local_services_docker_is_active
std::unique_ptr<scn_2_monitor_local_services_docker_is_active> forge_bdd_steps() {
    return std::make_unique<impl_scn_2_monitor_local_services_docker_is_active>();
}
#else
std::unique_ptr<scn_2_monitor_local_services_docker_is_active> forge_bdd_steps() {
    return std::make_unique<stub_scn_2_monitor_local_services_docker_is_active>();
}
#endif

// Executable scenario
TEST(scn_2_monitor_local_services_docker_is_active_test, executes_scenario) {
    auto steps = forge_bdd_steps();

    std::cout << "[GIVEN] Given Docker is installed" << std::endl;
    steps->given_docker_is_installed();
    std::cout << "[WHEN] When the agent checks for running services" << std::endl;
    steps->when_the_agent_checks_for_running_services();
    std::cout << "[THEN] Then Docker should be reported as running" << std::endl;
    steps->then_docker_should_be_reported_as_running();
}
Enter fullscreen mode Exit fullscreen mode

🧑‍💻 Developer Implementation

Once ready, the developer creates their real implementation:

class impl_scn_2_monitor_local_services_docker_is_active
    : public scn_2_monitor_local_services_docker_is_active {
public:
    void given_docker_is_installed() override {
        // Simulate installation or validate system state
    }

    void when_the_agent_checks_for_running_services() override {
        // Trigger service check logic
    }

    void then_docker_should_be_reported_as_running() override {
        // Assert result or state output
        ASSERT_TRUE(service_report().docker_running);
    }
};
Enter fullscreen mode Exit fullscreen mode

The test now passes — and the developer never has to touch the test runner logic. All they write is the behavior logic in one clean implementation file.


🧠 Smart CMake Integration

Every module, whether it’s an app or a library, is wired into your project’s build system automatically. CppForge knows how to cleanly register, link, and organize CMake targets — even supporting modular test discovery.

You never have to touch CMake unless you want to.


🧱 Composable Interfaces

CppForge creates standard, override-ready interfaces for every generated module. These are designed for testability, extension, and inversion of control. Developers write only the logic; the glue is already there.

Encourages a clean separation between core logic and system boundaries.


🔌 Plugin-Ready Foundation

From the start, the engine is built with plugins in mind — whether for source analysis, metadata extraction, DI, or CI hooks. CppForge is positioning itself as a pluggable, opinionated, developer-focused platform.

Future tools like DI or clustering will simply drop into place.


🧭 Run Configuration Support

Scenarios generate test runners with built-in CLion support — each test can have its own green button, making BDD development visible, trackable, and clickable.

That scenario you defined? It now lives in your IDE’s test runner — no config required.


This is just scratching the surface — we’re building towards something where the developer experience leads the architecture, not the other way around.

Top comments (0)