Zack: The question of whether to use kv-args or option maps is unrelated to the use of make and make-args, which Dylon rightly points out are intended to allow values specified in system.clj to be overridden in the config file.
You don't have to use make and make-args at all, and I originally create make and make-args for my own experimental use. Somehow they found their way into the system.clj generation with 'lein new modular'. However, it's obviously not great that you had to spend so much time figuring them out. To be honest, they're not well documented, please accept my apologies for that. One of the aims of modular is to keep components agnostic from the code that assembles them. So if you find 'make' and 'make-args' useful to you in the assembly of your Clojure systems, great. If you don't want to use them, that's fine too.
I do think though that the configuration mechanism used in the assembly of systems could be improved, retaining the ability to override system configuration with config files/data-sources, but not requiring your system.clj to have knowledge the structure of your config file.
Ideally you want things to be configurable even in situations when you've forgotten to make them so. For example, you might have hard-coded the port of the web server to be 3000, only to find that when you deploy onto your prod machine, someone else has already running another service on 3000 and you don't have the option of going back and modifying the original code (for political or other reasons).
One idea is for the config tree (sourced from a local file or elsewhere) to mirror the structure of the system tree. For example, it's quite possible with modular to have two Jetty web servers running on different ports. But each instance would have to have a unique key in the system map. If the config tree mirrors the system tree, it's then obvious which config setting affects which Jetty web server instance. Of course, you could have a more complex mapping between your configuration tree and the system tree, but the out-of-the-box case should be an easy one-to-one. And you could always process a config file from one map to another.
However, I'm keen that modular doesn't dictate to developers how to do configuration, when there are other really good approaches out there which should fit (env, nomad, etc.). Rather, new projects generated with 'lein new modular' should contain a basic default mechanism that can be swapped out or extended easily. I don't have anything in mind, just hoping to prompt further discussion in this group. Modular should focus on what it does, and stay out of areas best left to other libraries.
So, back to the topic of the thread: constructors with kv-args. I am sympathetic to the arguments of both camps. One compromise I'm considering of to support both approaches: If there's a single argument to a constructor, it's treated as an option map. If there's more that one, it's kv-args. It's just more work in the constructors, and I feel we should cater for users of components rather than their authors. While it's not always a good idea to try to keep everyone happy with compromises, I think this might work. Would they be any major drawbacks with this dual approach? For example, would it cause unforeseen problems and complexity in composition?