AuthMe/ConfigMe

Prototype other way of handling properties

Opened this issue · 2 comments

Users may find it inconvenient to have to declare Property fields whose values must be resolved with a SettingsManager. I would like to invest some time into looking for alternative approaches, such as:

  • Offering a @Property annotation alongisde our current approach. How would we deal with immutability and default values?
  • getValue() method on the property itself? Would no longer require having access to the SettingsManager everywhere, while still being immutable / reload friendly.

Creating a child interface to SettingsHolder would allow to mark classes with property values on fields directly. If the class has instance variables we can check for non-null default values (configurable), and testing-wise we can easily go back to default values by creating a new instance.

For static fields probably need to use the same marker interface or it becomes too confusing. Only idea for testing / keeping default values would be through reflections by storing the current values beforehand. This is not so nice. We can either just always work with whatever value we've got, but if I delete my config.yml file I expect a "factory default" config.yml to be generated...

The SettingsManager could keep a list of transformers that can transform from PropertyResource to the given field type. Custom ones could be provided to it, of course, and the new Property annotation can have an optional value where the class of a Transformer can be provided.

The idea of having classes holding their properties in fields (non-static) seems like the best option here. The only issue is if we want to reload the config (as in AuthMe) we'd tend to just create a new object of the type. As they are injected we suddenly find two objects being used alongside. On reload, we probably need to talk to the same object and create a second such object (lazily) if we need to access some default value.

Lastly, to have the same behavior between e.g. a StringProperty and a String field we probably need to extract an interface from Property to create these new Transformers. I don't want the transforming logic to be duplicated between Property and the future Transformer. During this process we need to ensure that it's relatively easy to extend these types for custom user behavior.

Unordered thoughts:
Maybe by unifying the bean mapper types and the property types into one interface, we could still allow the current style of Property fields for whoever like this and provide something else like @Config that makes ConfigMe go into "bean mode". Could have a separate annotation to specify a custom type when necessary.
Maybe more context on ConfigMe itself (the SettingsManager) to provide custom types, desired behaviors and then with those configs it parses @Config classes for example.

Not really related but this + #164 Default values in configuration file I think should be a focus in ConfigMe 2.0 (+ related #116)

Also a lot of the fields have natural defaults, like, the type impl could provide a natural default (or maybe define that's not allowed). If we go the @Config way fields could be initialized there directly. Later on think about maybe providing a method to construct the default value if there would be some "costly" defaults, though on the other hand if you have values in a config that are "expensive" to construct (especially defaults) you're probably doing something wrong?

Whatever handling changes in ConfigMe I think it's important to keep its strengths: easy migrations, decoupling between configuration handling and YAML file handling (YamlFileReader by itself is a really useful class!) and null-safeness.