'version'-based code selection
Jonathan M Davis
newsgroup.d at jmdavisprog.com
Sun Jun 2 19:57:30 UTC 2019
On Sunday, June 2, 2019 11:43:09 AM MDT Anonymouse via Digitalmars-d-learn
wrote:
> On Saturday, 1 June 2019 at 07:46:40 UTC, Jonathan M Davis wrote:
> > For the most part though, you don't declare your own version
> > identifiers. It sometimes makes sense, but usually, version
> > identifiers are used for versioning code based on the platform
> > or architecture that it's compiled on. They're really only
> > intended to be a saner version of #ifdefs, and if you're doing
> > anything fancy with them, you're really not using them as
> > intended and are probably going to have problems.
>
> I use versioning pervasively to make features opt-in/opt-out at
> compile-time.
>
> Like so, from dub.json:
>
> "versions":
> [
> "AsAnApplication",
> "WithAdminPlugin",
> "WithAutomodePlugin",
> "WithBashQuotesPlugin",
> "WithChanQueriesService",
> "WithChatbotPlugin",
> "WithConnectService",
> "WithCTCPService",
> "WithHelpPlugin",
> "WithNotesPlugin",
> "WithPersistenceService",
> "WithPipelinePlugin",
> "WithPrinterPlugin",
> "WithQuotesPlugin",
> "WithSedReplacePlugin",
> "WithSeenPlugin",
> "WithWebtitlesPlugin"
> ],
>
> ---
>
> module foo;
>
> version(WithFoo):
>
> // ...
>
> Is this recommended against? It's a very convenient way of
> enabling and disabling modules outright, since (by default) dub
> eagerly compiles everything it sees. I haven't had any problems
> with it as of yet, at the very least.
Personally, I wouldn't be in favor of doing much in the way of enabling or
disabling features in a library or application in such a manner, but if
you're going to do it, then version identifiers would be appropriate.
However, you do need to watch out, because such an approach runs the risk of
problems if you end up with a project depending on libraries that depend on
your library, because they may not be compiled with the same set of version
identifiers. I'm not sure how dub handles that (probably by considering it a
conflict), but without any form of conflict resolution (or you have a form
of conflict resolution that doesn't catch this issue), you run the risk of
modules being imported with one set of version identifiers but actually
compiled with another. In some situations, that will result in a linker
error, but in others, it's just going to result in the code not behaving as
expected. It's less of an issue if the version identifiers are for an
application rather than a library. Also, if you're versioning out entire
modules rather than pieces of modules, you're likely to be less at risk of
subtle problems, since then you'll just get large stuff missing, and linking
will fail, whereas if you're using such version identifiers within code
(e.g. changing the body of a function), then you run a high risk of subtle
problems.
Personally, if I were writing a library with optional stuff, I'd make the
optional stuff into sub-modules and try to avoid using version identifiers.
I might do it for an application though, since in that case, you wouldn't be
dealing with sub-modules, and you're not dealing with anything depending on
your code, just controlling what ends up in the executable.
- Jonathan M Davis
More information about the Digitalmars-d-learn
mailing list