From c42bb9fa41380771a844925c463d8d8e23929ab5 Mon Sep 17 00:00:00 2001 From: Ulrich Huber Date: Mon, 11 Aug 2025 17:36:51 +0200 Subject: [PATCH] Update api_guideline.rst --- docs/contribute/development/api_guideline.rst | 66 ++++++++++++++++--- .../development/cpp/coding_guidelines.rst | 34 +++++++++- 2 files changed, 91 insertions(+), 9 deletions(-) diff --git a/docs/contribute/development/api_guideline.rst b/docs/contribute/development/api_guideline.rst index 0b110a875d..bd7291e7e5 100644 --- a/docs/contribute/development/api_guideline.rst +++ b/docs/contribute/development/api_guideline.rst @@ -19,15 +19,65 @@ Designing API :id: doc__api_guidelines :status: draft -User friendly API design -======================== +What makes a good API? A start is to create an API that feels natural to a user. +There are multiple layers to "natural". -* Each public API shall support the idioms of the programming language it is written in. -* Each public API shall use core infrastructure of its programming language and accompanying standard libraries, whenever possible and meaningful. +One part is finding a natural abstraction of the usecase that this API should fulfill. +Since this is a general guidance on designing APIs, it is out of its scope to answer how that abstraction looks for your individual usecase. +But, this guidance can help you on some other aspects of "natural". + +In the following, we go through some aspects of an API you should consider. +This is not a complete list. Designing a good API is no easy task. +See this more as a starting point and feel free to add further aspects you think are worth the read. + +Naming conventions +------------------ + +Patterns and Idioms of the Programming Language +----------------------------------------------- + +When a software developer interacts with an API, he does so using a programming language. +With this language come specific patterns and idioms, how good code should look like. +To make an API feel "natural" to a user, it must follow these patterns and idioms prescribed by the programming language. +Otherwise, it will feel foreign and requires a user to constantly doublecheck in the manual how the API behaves. + +An example from the C++ world is the named requirement `Container `_. +If an API is developed against this named requirement, it seamlessly fits into the expectations a C++ developer has for code. + +So, when designing an API, do not only consider the problem you are trying to solve, but also how a user would want to interact with your solution. +Approaches like test-driven development can support you in taking the perspective of a user. +Given that the interaction differs for multiple programming languages, that the same API is likely not a good fit for more than one programming language. + +Programming Language Infrastructure +----------------------------------- + +Each programming language comes with a set of infrastructure. Be it features of the compiler, standard libraries or other helpers. +To make an API feel natural to the user means that you use this infrastructure wherever possible. + +This has several reasons: + +* The infrastructure is used most likely in the surrounding code already +* The infrastructure supports you in getting the patterns and idioms right +* By using existing infrastructure you reduce code duplication and maintenance effort + +Should it be impossible to use the existing infrastructure, try to stay as close as possible to it with your replacement. Error handling -============== +-------------- + +Avoid encoding errors in the returned value (e.g.: do not use -1 for a function that returns an integer). +Instead, follow the language-specific coding guidelines or the language specific features if no guidelines exist. + +Further, handle errors internally if feasible but bubble an error up if a user should know about it. + +Consider aborts as a final resort, since they will reduce the availability of the S-CORE platform. +Even if an error does not allow you to continue operation, providing this error to the user is still better than an abort. +The user may decide to abort himself, or he may continue in a degraded fashion without your library. + +Testability +----------- + +Consider that users may have to test their code that interfaces with your API. +This means, an API always needs to consider the additional usecase of testing. -* (C++) exceptions shall not be used for error handling, as these will be directly leading to an abort and thus reducing availability of the S-CORE platform. -* The best way to deal with errors is to try to resolve those component internally. If not possible the caller of the function shall be notified of the error. -* For (error) returns there is a specific library to be used in S-CORE, it is the Score::Result library which is part of the :ref:`baselibs_feature` feature. +A common solution is to apply the dependency injection pattern to the API. diff --git a/docs/contribute/development/cpp/coding_guidelines.rst b/docs/contribute/development/cpp/coding_guidelines.rst index 399e38f93a..586934507c 100644 --- a/docs/contribute/development/cpp/coding_guidelines.rst +++ b/docs/contribute/development/cpp/coding_guidelines.rst @@ -45,7 +45,24 @@ Examples are: * function calls * initialization of variables. -For this project an code style is not yet decided. +For this project a coding style is not yet fully decided. + +Naming Conventions +------------------ + +Interfaces +^^^^^^^^^^ + +A user should program against interfaces. +This reduces coupling of code and retains big projects maintainable. +To advertise this, name your interfaces accordingly. + +This means: + +* Avoid prepending an `I` or appending `Interface` +* Instead, append `Impl` to implementations to clearly mark them + +Finally, consider hiding implementations behind a factory to ease the instantiation effort of a user. C++ Version =========== @@ -92,3 +109,18 @@ C++20 * `Spans `_ * `jthread `_ * `stop_token `_ + +Error handling +============== + +Error handling for C++ is solved through score::Result in the :ref:`baselibs_feature` feature. +Avoid encoding errors in the returned value (e.g.: do not use -1 for a function that returns an integer). +Instead, always use the :ref:`baselibs_feature` feature. +Throwing exceptions should be avoided, as they normally come with heap allocation. +Exceptions are therefore hardwired to an abort. + +Further, handle errors internally if feasible but bubble an error up if a user should know about it. + +Consider aborts as a final resort, since they will reduce the availability of the S-CORE platform. +Even if an error does not allow you to continue operation, providing this error to the user is still better than an abort. +The user may decide to abort himself, or he may continue in a degraded fashion without your library.