2010-07-23 18:24:30 +02:00
|
|
|
Design Process : C Coding Style Guide
|
|
|
|
|
=====================================
|
|
|
|
|
|
2025-09-08 04:04:39 +02:00
|
|
|
[options="autowidth"]
|
|
|
|
|
|====================================
|
2025-09-16 23:50:55 +02:00
|
|
|
|*State* | _Dropped_
|
2025-09-08 04:04:39 +02:00
|
|
|
|*Date* | _2007-07-03_
|
|
|
|
|
|*Proposed by* | ct
|
|
|
|
|
|====================================
|
2010-07-23 18:24:30 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
C Coding Style Guide
|
|
|
|
|
--------------------
|
|
|
|
|
I introduce here my favorite C coding style.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Description
|
|
|
|
|
~~~~~~~~~~~
|
2010-07-24 16:48:32 +02:00
|
|
|
In the following I'll explain a C coding style I used frequently for other
|
|
|
|
|
projects. Take this as suggestion for parts written in C (it definitely makes
|
|
|
|
|
no sense for C++). We probably don't need to enforce this style for normal C
|
2025-09-02 19:42:49 +02:00
|
|
|
code, but for the related
|
2025-09-08 04:04:39 +02:00
|
|
|
link:{rfc}/AllPluginInterfacesAreC.html[Rfc: »All Plugin Interfaces Are C«]
|
2010-07-24 16:48:32 +02:00
|
|
|
it really makes sense to have some well defined style.
|
2010-07-23 18:24:30 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
Function names follow the rule:
|
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
.`namespace[\_object][\_verb[\_subjects]][\_version]`
|
2025-09-08 04:04:39 +02:00
|
|
|
* namespace is `lumiera_` appended with some subsystem tag
|
2010-07-24 16:48:32 +02:00
|
|
|
(`lumiera_plugin_audio_`)
|
2025-09-08 04:04:39 +02:00
|
|
|
* object is the type of the `this' (or `self') object we are addressing,
|
|
|
|
|
maybe followed by the object we are returning
|
2010-07-24 16:48:32 +02:00
|
|
|
* verb is the action to take, (new, copy, free, set, clear,.. etc.) if omitted
|
|
|
|
|
the action is `get`
|
|
|
|
|
* subjects is a descriptive list of the arguments which the action takes, this
|
|
|
|
|
should be a human readable word describing the parameter concept, and NOT
|
|
|
|
|
encoding a concrete type (name, age, weight; not string, int, float)
|
|
|
|
|
* for interfaces we may use versioning, then a number is appended to the name
|
|
|
|
|
but we alias the actual function with a inline function or a macro without
|
|
|
|
|
this number.
|
2010-07-23 18:24:30 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
Prototypes follow the rule:
|
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
.`rettype function (Object self, ...)`
|
|
|
|
|
* function is the functionname as above
|
2010-07-24 16:48:32 +02:00
|
|
|
* rettype is sensible to what object and verb define, setters return a pointer
|
|
|
|
|
to the set'ed element if an allocation could be involved (or NULL on
|
2025-09-08 04:04:39 +02:00
|
|
|
failure), a int if the setter does some checks over the supplied argument
|
|
|
|
|
(`0` indicates failure, `!0` success), void for procedures and actions which can
|
2010-07-24 16:48:32 +02:00
|
|
|
never fail.
|
2025-09-08 04:04:39 +02:00
|
|
|
* Object is a pointer to referred object (`this' like C++) in rare cases
|
|
|
|
|
(`_new()`) functions may be used without this self pointer, see below
|
2010-07-24 16:48:32 +02:00
|
|
|
* `...` are the types and names of the arguments described in `subjects` of the
|
|
|
|
|
name.
|
2010-07-23 18:24:30 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
Object variants:
|
|
|
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
|
For each `struct namespace_foo_struct` we have following typedefs:
|
|
|
|
|
|
|
|
|
|
[source,C]
|
|
|
|
|
----
|
2011-11-27 06:15:35 +01:00
|
|
|
typedef struct namespace_foo_struct namespace_foo; // basic struct name
|
|
|
|
|
typedef namespace_foo* NamespaceFoo; // canonical object pointer/handle
|
|
|
|
|
typedef const namespace_foo * const_NamespaceFoo; // pointer to const object
|
|
|
|
|
typedef namespace_foo ** NamespaceFoo_ref; // when intend to mutate the handle itself
|
|
|
|
|
typedef const namespace_foo ** const_NamespaceFoo_ref; // same for const object handle
|
2010-07-23 18:24:30 +02:00
|
|
|
----
|
|
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
|
+++++++++
|
|
|
|
|
.`lumiera_plugin_audio_sample_normalize_limit_1 (AudioSample self, int limit)`
|
2025-09-08 04:04:39 +02:00
|
|
|
* namespace is `lumiera_plugin_audio`
|
|
|
|
|
* operates on a `sample' object (and likely returns a pointer)
|
|
|
|
|
* operation is `normalize`
|
2010-07-23 18:24:30 +02:00
|
|
|
* takes one additional parameter describing the limit for normalization
|
|
|
|
|
* this is a version 1 interface we later define:
|
|
|
|
|
|
|
|
|
|
[source,C]
|
|
|
|
|
----
|
|
|
|
|
#define lumiera_plugin_audio_sample_normalize_limit\
|
|
|
|
|
lumiera_plugin_audio_sample_normalize_limit_1
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
.`lumiera_plugin_audio_sample_rate_1 (AudioSample self)`
|
|
|
|
|
* this would be just a getter function returning the sample rate
|
|
|
|
|
|
|
|
|
|
.`lumiera_plugin_audio_sample_set_rate_1 (AudioSample self, unsigned rate)`
|
|
|
|
|
* a setter, note that the 'rate' is defined after the verb
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Pros
|
|
|
|
|
^^^^
|
|
|
|
|
* supplements documentation, makes it even unneeded sometimes
|
|
|
|
|
* well defined namespace
|
|
|
|
|
* C language bindings without tricks
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Cons
|
|
|
|
|
^^^^
|
|
|
|
|
* very long identifier names
|
|
|
|
|
* not completely unique
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Alternatives
|
|
|
|
|
^^^^^^^^^^^^
|
2010-07-24 16:48:32 +02:00
|
|
|
* Hungarian notation isn't readable, fails semantic consistency, has renaming
|
|
|
|
|
issues and encodes types rather than concepts. There are simpler schemes
|
|
|
|
|
which are even more unambiguous.
|
2010-07-23 18:24:30 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Rationale
|
|
|
|
|
~~~~~~~~~
|
2010-07-24 16:48:32 +02:00
|
|
|
I am trying/using this scheme since some time now, at first it looks like
|
|
|
|
|
overhead to encode arguments to functionnames. But the intention here is to
|
|
|
|
|
make code easy readable and memorizeable, when one follows this scheme one does
|
|
|
|
|
seldom need to lookup the docs about the API. In fact it sometimes even turns
|
|
|
|
|
out that one wants to use a functionname which isn't defined in the API, which
|
2025-09-08 04:04:39 +02:00
|
|
|
is a good indicator to add such a missing function to the API.
|
2010-07-23 18:24:30 +02:00
|
|
|
|
2010-07-24 16:48:32 +02:00
|
|
|
This scheme is not fully unambiguous but suffices for all practical task. It
|
|
|
|
|
encodes parameters like C++ does for overloading without strange mangling. All
|
|
|
|
|
names are global in a well defined namespace which is very natural for C (other
|
2025-09-08 04:04:39 +02:00
|
|
|
OO like C styles involve structs and hand written CTables, with this scheme we
|
|
|
|
|
trampoline from this global names to VTables _only if needed_)
|
2010-07-23 18:24:30 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Conclusion
|
|
|
|
|
----------
|
2025-09-08 04:04:39 +02:00
|
|
|
Finalized at the link:{ldoc}/devel/meeting_summary/2008-03-06.html[2008-03-06 developer meeting]
|
2010-07-23 18:24:30 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Comments
|
|
|
|
|
--------
|
|
|
|
|
|
2025-09-08 04:04:39 +02:00
|
|
|
I strongly object promoting such a scheme as a general ``Style Guide''. It can be
|
2010-07-26 02:54:14 +02:00
|
|
|
a help or last resort if you are forced to work with improper tools (a
|
|
|
|
|
situation that's rather frequent in practice though). __As such it is well
|
2025-09-08 04:04:39 +02:00
|
|
|
chosen and practical__, however.
|
2010-07-23 18:24:30 +02:00
|
|
|
|
|
|
|
|
But basically, it shows several things:
|
2025-09-08 04:04:39 +02:00
|
|
|
|
2010-07-23 18:24:30 +02:00
|
|
|
* you are using a global namespace
|
|
|
|
|
* you deal with way to fat interfaces
|
2010-07-24 16:48:32 +02:00
|
|
|
* you mix deployment metadata (a version/compatibility check) with functional
|
|
|
|
|
code
|
2025-09-08 04:04:39 +02:00
|
|
|
|
2010-07-24 16:48:32 +02:00
|
|
|
All of this indicates some design style breakage, so it would be preferable to
|
|
|
|
|
fix the design if possible.
|
2010-07-23 18:24:30 +02:00
|
|
|
|
2010-07-24 16:48:32 +02:00
|
|
|
The only part I'd like to support as a Style Guide is the rule of using the
|
2010-07-26 02:54:14 +02:00
|
|
|
"verb+object" pattern for creating function names
|
2025-09-08 04:04:39 +02:00
|
|
|
|
|
|
|
|
Ichthyostega:: '2007-07-08T11:42:39Z'
|
2010-07-23 18:24:30 +02:00
|
|
|
|
|
|
|
|
Probably needs little explanation:
|
2025-09-08 04:04:39 +02:00
|
|
|
|
2010-07-23 18:24:30 +02:00
|
|
|
* you are using a global namespace
|
2025-09-08 04:04:39 +02:00
|
|
|
|
|
|
|
|
** This is only about C for names which get exported, C only has a global
|
2010-07-24 16:48:32 +02:00
|
|
|
namespace and we need some way to get unique names. The
|
2025-09-08 04:04:39 +02:00
|
|
|
link:{rfc}/AllPluginInterfacesAreC.html[RfC: Plugin Interfaces in C]
|
|
|
|
|
already uses better/smaller namespaces by defining interfaces as C structs.
|
|
|
|
|
The full blown long names explained here are technically not needed when we use
|
|
|
|
|
the plugin system as proposed, I just shown them here for completeness. Next,
|
|
|
|
|
when we decide for alternative linking methods like static builds we would need to
|
2010-07-24 16:48:32 +02:00
|
|
|
declare all "verb+object" functions static, else there is a high probability of
|
|
|
|
|
clashes.
|
2010-07-23 18:24:30 +02:00
|
|
|
|
|
|
|
|
* you deal with way to fat interfaces
|
2025-09-08 04:04:39 +02:00
|
|
|
|
|
|
|
|
** How can you tell that? This is only a nameing style. No interfaces mentioned
|
2010-07-24 16:48:32 +02:00
|
|
|
here. I am all after small well defined specialized interfaces.
|
|
|
|
|
|
2025-09-08 04:04:39 +02:00
|
|
|
* you mix deployment metadata (a version/compatibility check) with functional code
|
|
|
|
|
|
|
|
|
|
** Yes, I cant figure out how to do it better but still lightweight in C. the
|
|
|
|
|
`_version` thing is something I added here after the interfaces proposal. I work
|
2010-07-24 16:48:32 +02:00
|
|
|
on a example how this will be used in a more friendly way.
|
|
|
|
|
|
2025-09-08 04:04:39 +02:00
|
|
|
Note again that this is a ``naming system'', it is intended to be very verbose
|
2010-07-24 16:48:32 +02:00
|
|
|
and give unique declarative names. It is not about design! Design is done as
|
|
|
|
|
usual and only when things have to be exported as C symbols (both, exported and
|
|
|
|
|
C!!) this applies. This has zero implication for C++ code, zero implication
|
|
|
|
|
for C functions which are not exported (while I personally still prefer this
|
|
|
|
|
style) and finally when we do the interfaces thing like I proposed, then the
|
|
|
|
|
naming can be much simpler, see examples there or in my repository.
|
2025-09-08 04:04:39 +02:00
|
|
|
|
|
|
|
|
ct:: '2007-07-10T08:03:06Z'
|
2010-07-23 18:24:30 +02:00
|
|
|
|
|
|
|
|
|
2010-07-24 16:48:32 +02:00
|
|
|
Thanks, your explanation together with the example in git made the usage
|
2025-09-08 04:04:39 +02:00
|
|
|
pattern much more clear. I think the `_version` postfix is esp. helpful on the
|
2010-07-26 02:54:14 +02:00
|
|
|
names of the plugin interfaces (structs in C), and probably it will be a good
|
2025-09-08 04:04:39 +02:00
|
|
|
practice, to have one such common plugin interface on every ``plugin extension
|
|
|
|
|
point'', i.e. every point in the system, that can be extended by plugins.
|
|
|
|
|
|
|
|
|
|
Ichthyostega:: '2007-07-10T17:23:33Z'
|
2010-07-23 18:24:30 +02:00
|
|
|
|
2025-09-16 23:50:55 +02:00
|
|
|
|
|
|
|
|
.State -> Dropped
|
|
|
|
|
During the last years, I have read this RfC several times, and I am still
|
|
|
|
|
not sure what this proposal wanted to achieve, and what was the intention of
|
|
|
|
|
proposing it this way. +
|
|
|
|
|
A ``C coding style'', a ``naming system'' meant to be very verbose,
|
|
|
|
|
but not intended to be about design, yet ``technically not needed when
|
|
|
|
|
using the plugin system'' -- which all together touches at
|
|
|
|
|
questions of design for sure.
|
|
|
|
|
|
|
|
|
|
In the early stages of the project, there was a debate revolving around the
|
|
|
|
|
idea of bootstrapping the application from a tiny core, with pretty much
|
|
|
|
|
any functionality assembled from plugins, and internal functions being
|
|
|
|
|
callable directly from Lua code. Combined with a low-ceremony, distributed,
|
|
|
|
|
collaborative working style, such a setup was linked to the promise of
|
|
|
|
|
fluid evolution of ideas in order to try out unconventional solutions
|
|
|
|
|
and see what works best.
|
|
|
|
|
|
|
|
|
|
Personally, this premise made me feel queasy, because I had a clear vision
|
|
|
|
|
in my head, which required to build some rather advanced and challenging
|
|
|
|
|
structures. Mastering complexity means to segregate and settle parts of a
|
|
|
|
|
problem in order to avoid excess interdependencies. I'd rather attempt
|
|
|
|
|
to deflect and redirect flexibility and differentiation towards the
|
|
|
|
|
periphery and establish stable yet generic structures in the core.
|
|
|
|
|
|
|
|
|
|
Ichthyostega:: '2025-09-16'
|
|
|
|
|
|
2010-07-23 18:24:30 +02:00
|
|
|
''''
|
2025-09-08 04:04:39 +02:00
|
|
|
Back to link:/x/DesignProcess.html[Lumiera Design Process overview]
|