This is mostly a RnD idea that came up when looking into mattstermiller/koffee#20
What I try here is to extract away the different prompts into submodules to be able to assign to the MainModel what dispatcher to use.
-
Creating WPF
UserControl
's. Sadly I couldn't find an easy way as FsXaml doesn't support proper code-behind for controls. Also Acadian-Ambulance/VinylUI doesn't seem to have the greatest support for handling that kind of stuff. Would be nice to have though, like to let VinylUI to handle the dispatcher and focus stacks. -
Create
IPrompt
interface withdispatcher
method that different prompts (ex:DeleteBookmarkPrompt
vsGoToBookmarkPrompt
) implements. -
Change to
module
based with staticdispatcher
functions. That's the code snippet I provided here withPrompts.fs
.
-
Edit the model binding in MainView.fs and try in an abstract way display the correct data depending on selected prompt. Would be nice to allow specifying if we want to show a list and/or the input field, and what text should be written in those field.
-
Make composing of prompts better (in the code, that is). The current
module
based approach makes it tedious to handle that stuff and the file could get really big. It isn't that easy to read actually, in comparison to the previous solution. -
Make some unified way of opening prompts. Get's annoying quite quick though as you can't really have circle dependencies in F# in a smooth way. For example: I can't access
Koffee.MainLogic.Nav
from the prompts without doing some major refactoring. I can't create aIPrompt
interface that theMainModel
has as a property/member for routing dispatcher events to the hypothetical "selected prompt instance", as some of the functions has dependency on theMainModel
orMainEvents
itself (ex: the dispatcher). -
Change the flow of the
fallback
dispatcher calls. Currently they go in kind of reverse order. Optimally we want theClosablePrompt
dispatcher to fire first, then if it didn't handle the event it should continue to the next one.
I think this is me bringing too much C#/OO into F#. I want to solve this problem with polymorphism, but I can feel the framework and language is somewhat holding me back. The fact that everything has to be declared above/before does force me to not cheat and create a spaghetti of dependencies for the prompts, and that's probably for the better as it's probably considered bad-practice in F# code. But what do I know.
It's of course possible to create FSM's for this case. I just haven't found the way to do so yet in a clean way, while still staying true with the conventions of VinylUI and F#.
Bottom line: I think this is trying to bend the language and framework against their wills. I am consceding this fight and going with basic implementation instead.
You are correct. F# was intentionally designed so that you can't refer to things defined later in a file (except with the
and
keyword), or defined in files lower in the project. This prevents circular dependencies within projects. This is jarring coming from C#/Java, but I believe that once you get used to it, it really does produce better architecture. The main function in an F# project is always in the bottom file, and the utilities and global models are in the top files. You are forced to think about how different parts of the program should interact in a clean way. It forces you to separate the low-level "services" or whatever you want to call them from your higher-level business logic and makes it difficult to create spaghetti architecture. After 4 years of experience with F#, I'm a firm believer that this "limitation" of the compiler is actually a solid language decision.