Characterizing examples

Picking this 16739 comment into generalization, let’s think about what purposes examples serve:

  • Demos. Users flash this, and can right away explore what RIOT can do, play with it, learn the high-level concepts and verify their understanding of what their hardware can do.

    Examples: filesystem, gcoap, saul, nimble_heart_rate_sensor

  • Utilities: Similar to demos, but with the additional expectation that you’d just flash them and start using them in almost a productive setup.

    Examples: gnrc_border_router, maybe ccn-lite-relay

  • Scaffolding to start own applications: You can flash this, but usually you’d start editing there until you’re fed up with the “helloworld” name and copy what by now has become an own project of yours into a separate folder.

    Examples: gcoap (esp. server side), hello-world, usbus_minimal

  • Illustrations of concrete APIs and how to use them.

    Examples: the TCP Echo server of the abovementioned issue, dtls-echo, timer_periodic_wakeup

  • Build and hardware testing:

    Examples: everything in test

The reason I’m pulling test in here is that time and again when trying to understand an API I grep to the examples, find nothing, but the tests work perfectly fine to serve the “Illustration of a concrete API” case.


So far, I don’t have a point to make, but more of an open question:

Is the line currently drawn between tests and examples the right one? Do API examples water down the more read-to-start examples? Did we see feedback from newcomers who try to navigate the examples?

I think I agree mostly with your assessment. However, I think tests also used to be, at least in the past, also be a place where to look up API usage.

Maybe, by your characterization, we should finally go ahead and add a sub-hierarchy within the examples directory. This at least seems a far more sensible and entry-level friendly hierarchy than hierarchies proposed in the past (e.g. by sub-modules).

[Seperate post in case this spins out into its own discussion]

Another aspect of examples, aside from characterization, I am a bit worried about tbh, is that many examples do not contain much of an example. gnrc_networking e.g. mostly contains the UDP usage code (with efforts being made to remove that too), but mostly shows which modules to include to get a certain set of functionality (and even that sometimes not really well, judging from the emails I sometimes get, asking why a node does not forward packets very well with gnrc_ipv6_default pulled in).

While I agree, that code duplication needs to be also addressed, I remember that I was quite confused in the beginning where all those nice shell commands came from. Maybe moving shell commands to their respective modules, using XFAs can help, but then again, as a beginner you do not always know where which module is located.

The UDP pointer is spot-on:

Code that can serve to illustrate a particular API can live anywhere, for example in a shell command.

(Granted, if tailored towards “compact but still shell command” or towards “teaching the API”, there’d be different outcomes. But that’s only for APIs that don’t have perfect usability ;-), and for as long as we’re not spot on there, there’s nothing wrong with any rough edges showing in the example code).

Maybe we can find ways to make them more visible in the documentation? (Rust will do this automatically for shipped examples in the future, but we wouldn’t limit ourselves to examples.)

Taking up the recent question of “Which boards can RIOTBOOT be used with”, part of a classification of examples could be a criterion (ideally expanded to a list in some documentation automatically, if one may dream) for which board this can meaningfully be used with.

(This is pulling the “bootloaders” into the discussion, but on a high level where tests and examples are lumped together, they should go in there too.)