Write all modules with destructured arguments #93

Open
opened 2025-01-31 11:29:01 +01:00 by fricklerhandwerk · 4 comments

This is an authoritative decision I'm making here, and maybe we want to record it somewhere. Rationale:

  • Most modules will eventually need arguments anyway
  • While grabbing the module contents from the outside is a nice hack (which also avoids a full eval) it's a layer violation and such a situation can (and should) be handled differently, e.g. by factoring out the values in question to a separate file
  • For the sake of readability, we want to make explicit when we have a module in front of us. It's well known that NixOS beginners are very confused about modules as it is, no need to make it worse than necessary.

The underlying problem that prompted this issue is that currently some deployment code depends on at least one module to be denoted as a plain attrset, and this needs to be refactored.

This is an authoritative decision I'm making here, and maybe we want to record it somewhere. Rationale: - Most modules will eventually need arguments anyway - While grabbing the module contents from the outside is a nice hack (which also avoids a full eval) it's a layer violation and such a situation can (and should) be handled differently, e.g. by factoring out the values in question to a separate file - For the sake of readability, we want to make explicit when we have a module in front of us. It's well known that NixOS beginners are very confused about modules as it is, no need to make it worse than necessary. The underlying problem that prompted this issue is that currently some deployment code depends on at least one module to be denoted as a plain attrset, and this needs to be refactored.
fricklerhandwerk added the
contributor experience
label 2025-01-31 11:30:04 +01:00
Owner

You may also specify the _class module attribute, which documents and enforces the purpose of the module, and has potential to be a recognizable keyword for those who read the code. They are checked against class, so they also provide a clear error message when, for example, a nixosTest module is imported into a NixOS configuration.

Common class declarations would be:

  • _class = "nixos";
  • _class = "nixosTest";
  • _class = "nixops4Resource";
  • _class = "nixops4Deployment";

A good place is at the top of the module attribute set literal:

{ lib, config, options, ... }:
{
  _class = "nixos";
  options = <...>;
  config = <...>;
}

Alternatively, instead of specifying _class manually, you could use modules.<class>.<name> and/or derive that from a directory structure.

I could work on upstream documentation for the module syntax if that is deemed necessary.

You may also specify the `_class` module attribute, which documents and enforces the purpose of the module, and has potential to be a recognizable keyword for those who read the code. They are checked against [`class`](https://nixos.org/manual/nixpkgs/stable/index.html#module-system-lib-evalModules-param-class), so they also provide a clear error message when, for example, a `nixosTest` module is imported into a NixOS configuration. Common class declarations would be: - `_class = "nixos";` - `_class = "nixosTest";` - `_class = "nixops4Resource";` - `_class = "nixops4Deployment";` A good place is at the top of the module attribute set literal: ```nix { lib, config, options, ... }: { _class = "nixos"; options = <...>; config = <...>; } ``` Alternatively, instead of specifying `_class` manually, you could use [`modules.<class>.<name>`](https://flake.parts/options/flake-parts-modules.html) and/or derive that from a directory structure. I could work on upstream documentation for the module syntax if that is deemed necessary.
Author
Owner

Do you mean also == "instead of" xor also == "in addition to"?

Do you mean also == "instead of" xor also == "in addition to"?
Owner

Does your authoritative decision also hold for modules that are not the only thing in a file? For instance, in a NixOps4 resource:

{
  ...some stuff...

  nixos.module = {
    services.mastodon = ...
    fileSystems = ...
  };
}

Should this also be written:

{
  ...some stuff...

  nixos.module =
    { ... }:
    {
      services.mastodon = ...
      fileSystems = ...
    };
}

?

Does your authoritative decision also hold for modules that are not the only thing in a file? For instance, in a NixOps4 resource: ```nix { ...some stuff... nixos.module = { services.mastodon = ... fileSystems = ... }; } ``` Should this also be written: ```nix { ...some stuff... nixos.module = { ... }: { services.mastodon = ... fileSystems = ... }; } ``` ?
Author
Owner

Does your authoritative decision also hold for modules that are not the only thing in a file?

Not fully sure, but I tend towards yes, since all the same arguments apply.

> Does your authoritative decision also hold for modules that are not the only thing in a file? Not fully sure, but I tend towards yes, since all the same arguments apply.
Sign in to join this conversation.
No description provided.