-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[PoC] Introduced read/write interface for preferences #8006
Conversation
Thanks for working on this! After the many refactorings of the preferences in the past, I think we are now finally in a position to migrate to a new system that addresses the shortcomings you mentioned. What I don't understand in your proposal is how this is different to the existing A few more points that should be considered:
When I last thought about this, my hope was that JavaFX observables can be used, especially to cover the last point. The idea was roughly the following:
|
I did not know that. This eliminates the second benefit I listed above.
You pass a lambda that returns a static preference object or mock with the preferences you need for the test.
Still in the old way: not at all...
I like that idea. We could still bundle sets of PreferenceObservable's into Preference-Classes to make the passing easier. The needed refactoring would also be minimal I think (except for places where you actually want to have a listener on a preference, but that would be an improvement rather than a refactoring). |
Thanks for the explanation! @calixtus what are your thoughts about this? |
Did not have much time to dive deep into this. Sorry, will do in the next days... |
So I finally got into the code. One thing I see is that the ReadInterface is just a simple supplier, the ReadWriteInterface almost a consumer, except it integrates the ReadInterface. My proposal would be to simplify the proposal to the following in a first step:
In a second step, as soon as we have reached a consistent codebase in the preferences package we should be able to easily refactor the supplier-methods to maybe ReadOnlyObservables providing update listeners. About the other questions:
I'll push my proposal on this branch, if you don't like it, you can always force push your branch again. Some things to think about:
edit: was late, when i made the comment... some clearifications made. |
# Conflicts: # src/main/java/org/jabref/gui/preferences/importexport/ImportExportTabViewModel.java # src/main/java/org/jabref/preferences/JabRefPreferences.java
I tried to keep changes commit by commit |
We really should move and rename |
I'm not sure if I like the additional overhead that comes with the load/store interface (either in the original form proposed by Benedikt or using Supplier/Consumer). It just feels too complicated. What do you guys think about this proposal using observables: |
As I understand you proposal, this would mean that the PreferencesObjects are some kind of singletons. I still don't understand why for tests nothing should happen? |
I think the getters and setters are superfluous in the preferences object, instead one should only provide the property like we do in the viewmodels. |
Kind of. They are still normal classes that can be initialized as often as you want, but in practice you use the PreferenceService to get them and then they are essentially singletons, yes.
In tests, you simply create a new instance of the preference object (vie the constructor). So, in this case, no listener is added and thus they are not persisted (which is the behavior that what you want in tests).
The getters don't change and so far we don't have any setters. Thus the only thing that changes is how you store the new version, which happens mainly in the preference dialog. In this case, you can actually simplify the code quite a bit since you can simply bind the preferences to the ui components.
That would be possible, but is essentially equivalent to the above load/store procedure (accept that they are then called get/set). What advantages would this have?
In some way, yes. But it's actually javafx convention to add get + set + property methods. It's also handy for backwards compatibility since you don't need to change any getters. |
Took the liberty to add some flesh to your changes. Yes, i think this could be a way to go. Just want see how this works with those opt-in stuff. |
I know. But in this case, I think it improves readability to have the interfaces. Passing a supplier and a consumer clutters the method signature IMO. I really like the observables approach. I think it makes it very easy and clean to bind preferences to UI elements (in the preferences dialog) and to read them. I also like that there are still getters for the individual preferences in @tobiasdiez s code, so there is no need for a big refactoring. We just havte to use the observables where we actually want to react to changes / change the value. One thought about reference keeping: Storing a reference to all Preference-Objects that were ever used means they will stay in memory until JabRef exits, even if they are not needed anymore. This could be seen as a feature - since we only have to read them once. On the other hand, I don't know how resource-demanding that would be. |
I don't think hat these few preferences objects (maybe 20-30) will take much memory. There are maybe one or two exceptions, that are more resource demanding (Theme?). |
Great! |
@calixtus Great! I would suggest to convert the static variables like "OVERRIDE_DEFAULT_FONT_SIZE" to method-variables. In this way, you make sure that there is only one instance where the those variables are used and you prevent the potential bugs that would result otherwise. Also this has the advantage that the |
What still makes me think is how we can uncouple the higher logic in JabRefPreferences from the low level java API preferences like in createColumns. |
We can extract the |
We want to avoid to pass the big JabRefPreferences Object around. This is mostly done by just passing the smaller PreferencesObjects, but this approach has two problems:
We want to fix that.
The interfaces I propose here basically gives classes the possibility to load an up-to-date preference object whenever they need it. The ReadWriteInterface adds the possibility to store the preferences to disk.
I show a possible use case on hand of the ImportSettingsPreferences. I chose that class because it is small and not used very often, so the change was quick.
Advantages:
CHANGELOG.md
described in a way that is understandable for the average user (if applicable)