On Feb 19, 2009, at 4:11 PM, Krzysztof Kosiński wrote:

The preferences being global is not a bad thing, since we want consistent

behavior. There is exactly zero use for multiple Preferences objects.

Similarly, using the "global" clipboard is not bad. I think you're taking

the "globals are evil" approach too far.


The only problem with the prefs now is that nearly everything depends on

them, so it's hard to come up with the correct link order and it would be

hard to separate out libraries to use for other apps. However, the first

point would be mooted if we linked the executable from single object files

rather than a multitude of static libraries, because then the linker would

resolve back-references and the link order wouldn't matter.


...

I think one pattern I've heard used is "dependency injection".  Many  

aspects of that address what we're seeing in the code now.


This is essentially what I wanted to do when I proposed GConf.


That's not what I'm seeing.

I'll try to draw a lot up to pinpoint the differences, but a key is that things are spaghetti connected when what we need are stand-alone sub-components that can be reused in different ways. A few of the patterns that might come into play could include mediator, memento, and adapter. 

A color picker is a good example. If the color picker class itself hooked into the preferences, we would not be able to reuse it within different contexts. However if the color picker only picks a color and exposes a property or two, then different classes could create their own instances of color pickers, with some colors getting their values shoved in from preference settings, but others not. An adapter could be hooked to one color picker to keep it in sync with a specific preference setting, but then another color picker might be connected to a context object that switches to track the active documents.

In that case instead of having a color picker poll the preferences directly, the color picker would only know UI for selecting a color. Then a different small class would be instantiated that knows about preferences and about color pickers, and would watch the color picker's property and push any changes into the preferences. It could also watch the preference for changes and push those into the color picker as needed.

Among other things, by separating responsibilities we get pieces of code that can be more easily reused and also can be easily tested. Without such separation it becomes significantly more difficult to engage in a Test Driven Development (TDD) approach.

One of the concrete instances of such abstract problems was encountered in the toolbars and drawing contexts. I have to do some more cleanup on the eraser context, as there is still a fair bit of duplicate code in need of refactoring, but I did run up on some major problems. The worse is that the existing context was not reusable. It depended on the UI widgets such as sliders to actually set default values to get things functional. It also counted on the widgets for range checking, instead of validating values itself.  That also caused problems with trying to make the UI dynamic and toolbars configurable.