Reactive GUI Implemented in Clojure

30
Reactive GUI Implemented in Clojure Denys Lebediev

Transcript of Reactive GUI Implemented in Clojure

Page 1: Reactive GUI Implemented in Clojure

Reactive GUI Implemented in Clojure

Denys Lebediev

Page 2: Reactive GUI Implemented in Clojure

Quick background

Page 3: Reactive GUI Implemented in Clojure

Traditional approach

• Event Listener pattern

• Widget model is mutable

– Example: isPressed/setPressed

• Widget state is mutable

– Example: isEnabled/setEnabled

Page 4: Reactive GUI Implemented in Clojure

Traditional approach: problems

• Complicated GUI containers (dialogs, wizards, etc) are often difficult to implement, support and extend. Why?

Page 5: Reactive GUI Implemented in Clojure

Traditional approach: problems

• Obscuring the logic

Page 6: Reactive GUI Implemented in Clojure

Traditional approach: problems

• Obscuring the logic

– It may be unclear why the button is enabled and when it becomes enabled

Page 7: Reactive GUI Implemented in Clojure

Traditional approach: problems

• Obscuring the logic

– It may be unclear why the button is enabled and when it becomes enabled

• Spreading the logic

Page 8: Reactive GUI Implemented in Clojure

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

Page 9: Reactive GUI Implemented in Clojure

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

Page 10: Reactive GUI Implemented in Clojure

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

Page 11: Reactive GUI Implemented in Clojure

There is another way

• The framework takes care of routine

– It is already implemented and tested

– Developer concentrates on essential application logic

Page 12: Reactive GUI Implemented in Clojure

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

Page 13: Reactive GUI Implemented in Clojure

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

Page 14: Reactive GUI Implemented in Clojure

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}})

Page 15: Reactive GUI Implemented in Clojure

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}})

Page 16: Reactive GUI Implemented in Clojure

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}})

Page 17: Reactive GUI Implemented in Clojure

What’s the difference?

• greeting-evolver is a single place for the logic of

label’s :text property

Page 18: Reactive GUI Implemented in Clojure

What’s the difference?

• greeting-evolver is a single place for the logic of

label’s :text property

• It contains the logic, not routine

Page 19: Reactive GUI Implemented in Clojure

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

Page 20: Reactive GUI Implemented in Clojure

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

Page 21: Reactive GUI Implemented in Clojure

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

Page 22: Reactive GUI Implemented in Clojure

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

Page 23: Reactive GUI Implemented in Clojure

What’s the difference?

• Reactive framework takes care of these routine things

– Implemented once, no need to solve similar problems again

– Tested

Page 24: Reactive GUI Implemented in Clojure

FlatGUI architecture

Page 25: Reactive GUI Implemented in Clojure

Engine performs state transition

Page 26: Reactive GUI Implemented in Clojure

Option to run as RIA

Page 27: Reactive GUI Implemented in Clojure

Setup collaboration sessions

Page 28: Reactive GUI Implemented in Clojure

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

Page 29: Reactive GUI Implemented in Clojure

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