A modest proposal for library & firmware developers alike

…Please, namespace and/or prefix your stuff!

I love Spark and how well it works, but as a professional OO software developer I have to say the coding style used in the core and a lot of the community code sends shivers down my spine.

Namespacing is one thing. If you’re writing a library, use C++ and put your stuff in a neat namespace. And if your library has functions which are internal to that library, better yet, do not expose them in the headers. At least don’t pollute the global namespace.

namespace AwesomeLibrary {
  int counter;
  void doStuff()
  {
    counter++;
  }
}

// Usage:
AwesomeLibrary::doStuff();

And if namespacing isn’t possible for whatever reason, please at least prefix everything that you’re exposing.

int AwesomeLibrary_Counter = 0;
void AwesomeLibrary_DoStuff()
{
  AwesomeLibrary_Counter++;
}

The worst offenders here are the numerous enums, global functions, and worse yet, #defines which are dangerously ambiguous and even look exactly like one another. (!!)

This is, honestly, kinda bad:

typedef enum
{
  AUTOMATIC = 0, SEMI_AUTOMATIC = 1, MANUAL = 2
} System_Mode_TypeDef;

Firstly, it’s not namespaced. The enum typedef has a name, but enums are not namespaces. All the values go to the global namespace.
Secondly, the values aren’t prefixed. What’s MANUAL? A manual what? A proper, expensive IDE might tell you when you hover over the symbol in your code, but I personally believe code should be readable enough in whatever text editor. A little verbosity is very preferable over constant uncertainty.
Thirdly, they look like preprocessor definitions, although (thankfully) they aren’t. I believe it’s very reasonable practice to reserve fully uppercase naming for preprocessor directives.

Much better (in C++):

namespace Spark {
  enum SystemMode {
    SystemMode_Automatic = 0,
    SystemMode_SemiAutomatic,
    SystemMode_Manual
  };
}
// Usage like:
Spark_SetSystemMode( Spark::SystemMode_Automatic );

Alright, thank you for reading! Please do not take this as a personal attack of any kind. That is not at all what I’m going for. Every line of code in the Spark ecosystem is precious and much appreciated. This is merely a humble call for what I hope could be better mutual standards of code for long term prosperity. :slight_smile:
I hope my writing was concise and reasonable. I’d be happy to discuss and answer any C+±specific questions should anyone have such.

6 Likes

@noora Yes! It’s true that replacing #defines with enums/constants and namespacing will help avoid clutter in the firmware code. The core-communication-lib already does this, and library writers are encouraged to put their libraries in a namespace, which the IDE automatically imports. And no reason this shouldn’t also be the case with the main firmware.

The main caveat with using namespaces is that we have to avoid changes to API for user code. The existing public interface has all it’s symbols outside of a namespace E.g. SYSTEM_MODE(MANUAL). This is to make the code easier to write for beginner coders. While this doesn’t preclude putting everything inside namespaces in the source, those namespaces will have to be pulled into global scope with using in the application.h header file to maintain the existing public API.

You and anyone else that would like to are very welcome to submit pull-requests with namespaced code!

1 Like

In particular, none of the Arduino wiring-compatible APIs or libraries use namespaces so that makes Arduino compatibility a struggle. I know I have ported some Arduino libraries where I questioned the wisdom of some of the globals, but you never know who is using them already.

Yeah, I’m aware of this, and I thought about saying something about Arduino in the main post but decided not to.
I think it’s a real pity that Arduino, as a way-maker for the entire DIY tinkerer movement, decided to make their environment/API consistently s★it in terms of software design and development best practices. Now we’re stuck with their legacy everywhere, which is almost offending, having a whole generation of would-be programmers who don’t have a clue that the magical pin symbol A0 in their code is actually a 16-bit integer constant.

Firmware development is still software development, and I believe it would be responsible for the core developers in the movement to try to show these would-be coders what modern, solid programming looks like, and how their code is interpreted by the hardware. It’s not very constructive to pretend that it’s all just magic.

EDIT: Oh right, and I do have something constructive to propose as well: maybe the core wiring code could be refactored to actually be pretty, as per above-lined standards, and then we could have one header with all Arduino-style mappings to the underlying implementations. Then those of us who don’t give a toss about the Arduino-style API could use the beautiful meaty parts directly instead.

Yes, your last paragarph exactly! So come with those PRs for namespaced code! :slight_smile:

2 Likes