Core Programming Principles

Code Uniformity

This is listed first because we consider it the most important! Code uniformity is crucial when designing an API as it ensures consistency, predictability, and ease of use for developers. A uniform API adheres to established conventions for naming, structure, and behavior, making it intuitive and reducing the learning curve for new users. It minimizes errors by ensuring similar inputs produce similar outputs and standardizes error handling, leading to fewer surprises. Uniformity also enhances maintainability and scalability, enabling teams to update or extend the API with minimal friction. Moreover, it promotes collaboration by providing a shared framework for developers to follow, streamlining code reviews and reducing miscommunication. Ultimately, a consistent API design improves the developer experience, fosters trust, and drives adoption.

Limit Third-Party Dependencies

Relying on third-party dependencies can introduce significant risks and challenges that far outweigh their convenience. Dependencies are external, uncontrollable entities that can compromise the stability, security, and maintainability of your software. They are often subject to updates, deprecations, or removal without notice, leaving the application vulnerable to breaking changes or outright failure. Security vulnerabilities in third-party libraries are a persistent threat, and each additional dependency increases your attack surface exponentially. Furthermore, using third-party code can lead to bloated applications with unnecessary features, hampering performance and increasing complexity.

It also creates technical debt, as updating, replacing, or auditing dependencies demands time and resources that could be spent on core development. By avoiding third-party dependencies, you retain full control over your codebase, ensure its long-term stability, and avoid being at the mercy of external actors. Building in-house solutions, though potentially more time-intensive initially, results in cleaner, more robust, and better-understood code tailored precisely to your needs.

At NDEVR we spent years building up our code base from scratch, using bare-bones libraries. Our core dependency is ZLib for compression. Aside from that we use QT for our UI, and the Vulkan or OpenGL APIs for our 3D rendering. Everything else within our standard API is built in house which means we have a strong understanding of the underlying logic.

We do allow 3rd party libraries to be used in our modules. These are usually for reading/writing specific file types, or for interfacing with specific hardware or tools.

Modular Design

Modular design offers significant advantages by promoting flexibility, scalability, and maintainability. By breaking down the API into smaller, self-contained modules, developers can focus on individual components without affecting the entire system, simplifying updates, debugging, and testing.

This separation of concerns enables teams to work on different parts of the API concurrently, accelerating development cycles. Modular design also enhances reusability, allowing components to be repurposed across different projects or extended without duplicating effort. Additionally, it provides consumers with the ability to interact only with the modules relevant to their needs, improving the user experience and reducing complexity.

As the API grows, new features can be integrated seamlessly by adding or enhancing modules, ensuring the system remains organized and scalable. This approach results in an API that is more adaptable to changing requirements and easier to manage over time.

Asserts

Asserts play a crucial role in software development by acting as a safety net to ensure code behaves as expected during runtime. They are particularly valuable for catching bugs early in the development process, as asserts validate assumptions made by the code and immediately raise errors when those assumptions are violated. This proactive error detection helps developers pinpoint issues closer to their source, making debugging faster and more efficient. By documenting these assumptions directly in the code, asserts also enhance readability and maintainability, providing clear insights into the intended behavior. In testing and debugging environments, asserts enforce correctness without the need for manual checks, increasing confidence in the software’s reliability. However, because asserts are typically disabled in production, they offer a non-intrusive way to safeguard development while minimizing runtime overhead in deployed applications.

TABS Are Better

At NDEVR we don’t shy away from taking controversial positions on even the most important issues. 

Using tabs for code indentation offers several advantages over spaces, particularly in flexibility and consistency. Tabs allow developers to customize the display width of their code indentation according to their preferences or accessibility needs, providing a personalized viewing experience without altering the source code. This is especially beneficial in team environments where developers may have different preferences for indentation width.  Additionally, using tabs ensures consistency, as there is no ambiguity about the number of characters needed for each level of indentation. This eliminates potential formatting discrepancies that can arise when mixing spaces and ensures cleaner diffs in version control systems, as a tab is a single character change rather than multiple spaces. Overall, tabs promote a more adaptable and efficient coding environment.

To leave feedback on our decision to prefer tabs over spaces, see the below link: