Reactive GUI Implemented in Clojure
-
Upload
denyslebediev -
Category
Software
-
view
220 -
download
0
Transcript of Reactive GUI Implemented in Clojure
Reactive GUI Implemented in Clojure
Denys Lebediev
Quick background
Traditional approach
• Event Listener pattern
• Widget model is mutable
– Example: isPressed/setPressed
• Widget state is mutable
– Example: isEnabled/setEnabled
Traditional approach: problems
• Complicated GUI containers (dialogs, wizards, etc) are often difficult to implement, support and extend. Why?
Traditional approach: problems
• Obscuring the logic
Traditional approach: problems
• Obscuring the logic
– It may be unclear why the button is enabled and when it becomes enabled
Traditional approach: problems
• Obscuring the logic
– It may be unclear why the button is enabled and when it becomes enabled
• Spreading the logic
Traditional approach: problems
• Obscuring the logic
– It may be unclear why the button is enabled and when it becomes enabled
• Spreading the logic
– The reasons for the button to be enabled tend to be spread across the application code
Traditional approach: problems
• Obscuring the logic
– It may be unclear why the button is enabled and when it becomes enabled
• Spreading the logic
– The reasons for the button to be enabled tend to be spread across the application code
– Moreover with time
Traditional approach: problems
• Incidental complexity
– In fact, non-essential code has to be written
– Developer has to bother deciding when
– And spend time investigating another developer’s decisions
• Automated testing is tricky
– Robot-based testing
There is another way
• The framework takes care of routine
– It is already implemented and tested
– Developer concentrates on essential application logic
There is another way
• The framework takes care of routine
– It is already implemented and tested
– Developer concentrates on essential application logic
• All logic about a single property in a single place
There is another way
• The framework takes care of routine
– It is already implemented and tested
– Developer concentrates on essential application logic
• All logic about a single property in a single place
• Unit tests for code that manages widget model and state
Hello world with FlatGUI
(defcomponent checkbox :say-hello {:text "Greeting"})
(def nogreeting-text "Greeting not provided")
(def greeting-text "Hello, world!")
(defevolverfn greeting-evolver :text
(if (get-property [:say-hello] :pressed)
greeting-text
nogreeting-text))
(defcomponent label :greeting-label
{:text nogreeting-text
:evolvers {:text greeting-evolver}})
Hello world with FlatGUI
(defcomponent checkbox :say-hello {:text "Greeting"})
(def nogreeting-text "Greeting not provided")
(def greeting-text "Hello, world!")
(defevolverfn greeting-evolver :text
(if (get-property [:say-hello] :pressed)
greeting-text
nogreeting-text))
(defcomponent label :greeting-label
{:text nogreeting-text
:evolvers {:text greeting-evolver}})
Hello world with FlatGUI
(defcomponent checkbox :say-hello {:text "Greeting"})
(def nogreeting-text "Greeting not provided")
(def greeting-text "Hello, world!")
(defevolverfn greeting-evolver :text
(if (get-property [:say-hello] :pressed)
greeting-text
nogreeting-text))
(defcomponent label :greeting-label
{:text nogreeting-text
:evolvers {:text greeting-evolver}})
What’s the difference?
• greeting-evolver is a single place for the logic of
label’s :text property
What’s the difference?
• greeting-evolver is a single place for the logic of
label’s :text property
• It contains the logic, not routine
What’s the difference?
• greeting-evolver is a single place for the logic of
label’s :text property
• It contains the logic, not routine
• It’s easy to troubleshoot
What’s the difference?
• greeting-evolver is a single place for the logic of
label’s :text property
• It contains the logic, not routine
• It’s easy to troubleshoot
• It’s easy to cover with unit tests
What’s the difference?
• greeting-evolver is a single place for the logic of
label’s :text property
• It contains the logic, not routine
• It’s easy to troubleshoot
• It’s easy to cover with unit tests
• Developer does not have to decide when to call it
What’s the difference?
• greeting-evolver is a single place for the logic of
label’s :text property
• It contains the logic, not routine
• It’s easy to troubleshoot
• It’s easy to cover with unit tests
• Developer does not have to decide when to call it
• Developer does not have to call it
What’s the difference?
• Reactive framework takes care of these routine things
– Implemented once, no need to solve similar problems again
– Tested
FlatGUI architecture
Engine performs state transition
Option to run as RIA
Setup collaboration sessions
Clojure usage
• Macros are nice
– defining widget types and instances, property evolvers
– Layout management, like “below” “to the right of”
– Though IDE capabilities are still not enough
• Had fun with profiler to tune engine performance
– Introduced some non-idiomatic code
Current state of the project
• This is a poof-of-concept implementation
• What’s next
– Publish sources
– Prepare documentation and examples
– Launch the website
– Finalize the engine and basic widgets
– Optimize network solution