12

I encountered the following situation: I have two modules, TokenService and Wifi which are initialized from main(). The modules themselves don't know of the existence of each other and function completely independent, yet they need access to the same global resource which in this case is the nonvolatile storage flash, or short nvs, which must be initialized for the module to function correctly. The flash initialization function however is not idempotent, this means I can't call it twice, yet it should be called at least once when the first of either module goes through initialization. Here's a visualization of the thing:

Two modules accessing same global resource

I have not yet found a suitable elegant way to accomplish this. My current approach is to defer the initialization of the global resource back to the user of the module via a lambda, but it's not satisfying. I imagine that this is not the first time anyone has encountered this problem so I'm looking for the idiomatic approach to solve this.

glades
  • 493

4 Answers4

43

The answer to the problem "a third-party module has unsuitable semantics..." is always "...so I code an adapter that warps those semantics into something suitable." In other words, write e.g. a façade which does nothing except remember the state of initialization, and forwards any actual calls to the actual module.

Kilian Foth
  • 110,899
36

There are several ways to solve this problem.

One is to use an adapter or facade around the nvs, as described in the answer by @KilianFoth.

Another option is to use dependency injection. Then the contract of both TokenService and Wifi can state that they expect to receive a ready-to-use object that will handle their storage needs. That object could be the single instance of nvs, which has been initialized by main, or it could even be a storage mock that is provided by the test environment.

0

Why are you so concerned about Wifi and TokenService not being aware of each other while they're allowed to know about implementation details of the storage module?

Only let each module know what they actually need about the storage and leave everything else about the manufacturer module inside a module of your own whose only job is bridging the gap between what your modules need and what the manufacturer module offers. As other answers say, there are pleny of patterns to do that.

Rad80
  • 376
-1

This looks like use case for a singleton.
Forward all the calls to flash through a singleton - the first time it is accessed, it will handle the initialization logic, and stick around until program exits.

Thomas
  • 1