I have some ideas about dendritic patterns, but they may have nothing to do with the views of SergeK and TLATER. I’m not good at English, so I’m using a translator, with no intention to offend. I’m a complete beginner in nix, and most of these ideas are based on intuition, so corrections to any mistakes are welcome.
I think the problem with the dendritic pattern is that we used too many custom functions that are hard to modify.The dependencies of modules, the parameters passed to modules, and so on, these functions are all implemented by nix functions written by the dendritic pattern framework itself. This feels more like the style of flake-utils rather than nixpkgs/flake-parts. It completely ignores the options and type features of the module system, and this approach makes it impossible for users to modify the behavior of the framework. If you want an extra feature, you either have to modify the framework code or go through 200% of the effort to migrate to another framework.
When I try to implement a dendritic pattern outside of flakes, I often have the illusion that I am still doing something similar to inputs.self.*, but through config. It doesn’t feel like writing nix in a NixOS-like module system. I cannot simply affect another module through config. I had to create several specialized module variants.
If I have an impermanence module, then it would be difficult for me to directly use it in other modules in this way:
config = {
out.imports = [ ./nixos-iwd.nix ];
hardware.impermanence = {
dirs = [ "/var/lib/iwd" ];
};
};
I often have to create multiple variant modules like iwd-impermanence, or handle it manually.
Wow, this is exactly what I wanted to say!
I recently did something similar in my configuration by using specialized evalModules and a function similar to extendModules.
EDIT:
(Some probably unrelated nonsense)
Perhaps the original discussion was not completely unrelated to the dendritic pattern, and there is a reason for mentioning it. I remember Vic said, ‘The dendritic pattern is for the convenience of sharing configurations.’ So this is still a DI problem. The problem with nix is that it is really free. No one can guess where the entry point of a project is before reading the documentation.
This is what nixers has been doing all along, but it is not user-friendly at all! Flakes might be a solution. But in my opinion, flakes are a ‘compromise’ solution. It builds an ordered ‘virtual file system’ in the nix data structure, but essentially it is still a compromise with the unordered reality of the project’s actual file structure.
I guess flakes were intentionally designed to be simple, because we always need to check what a flake actually provides through nix flake show.
The dendritic pattern was originally built on top of the flakes foundation, right? But after studying the nixpkgs module system, I feel that the dendritic pattern might have made a flawed system abstraction: it treats the module system as an untyped attribute set framework, thereby losing both the declarative dependency handling and AOP advantages of the nixpkgs module system, while also failing to achieve the simple evaluability of flakes. It is an intermediary layer that is, in the worst sense, ‘unsupported on both ends.’
BTW, I have always felt a ghost of Guix wandering around these discussions. Guix is not like this. Scheme has a clear module system that relies on the existence of real file structures. Therefore, they never need to discuss the issue of entry points.