Building GUI App with Electron and Lisp

229 views

Published on

Talk at Lisp Meetup #50

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
229
On SlideShare
0
From Embeds
0
Number of Embeds
26
Actions
Shares
0
Downloads
1
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Building GUI App with Electron and Lisp

  1. 1. How Building GUI App with Lisp The Case of Pocket Change, Inc. LISP MEETUP #50 Mar 27, 2017
  2. 2. I’m Eitaro Fukamachi @nitro_idiot fukamachi
  3. 3. Joined Pocket Change in Feb 1
  4. 4. Pocket Change http://www.pocket-change.jp
  5. 5. Available at Haneda Airport
  6. 6. Today’s topic
  7. 7. What I want to tell today What I don’t tell How we use Common Lisp in our work How you can use Common Lisp in your work
  8. 8. Touch Screen Coins Bills IC Card Reader Receipt Printer API Server
  9. 9. Touch Screen Coins Bills IC Card Reader Receipt Printer API Server
  10. 10. Building the next version of this software is my work.
  11. 11. How to build Pocket Change
  12. 12. • Windows OS (Rich!) • Fullscreen GUI application
  13. 13. We decided to use Electron https://electron.atom.io by
  14. 14. Web Server (Express) Main Process (Node.js)
  15. 15. Open Web Server (Express) Main Process (Node.js)
  16. 16. Open Web Server (Express) Main Process (Node.js) Renderer Process (Chromium) React.js
  17. 17. Open Web Server (Express) Main Process (Node.js) Bidirectional Communication Renderer Process (Chromium) React.js
  18. 18. Why Electron? • Easy to deploy • Can package into a single EXE installer • Can build GUI with Web technologies • Embedded Chromium
  19. 19. However
  20. 20. The language is JavaScript. 👎
  21. 21. Why can’t we use Common Lisp?
  22. 22. None (just a launcher) Main Process (Node.js) + Common Lisp
  23. 23. Open None (just a launcher) Main Process (Node.js) + Common Lisp
  24. 24. Open None (just a launcher) Main Process (Node.js) Renderer Process (Chromium) React.js + Common Lisp
  25. 25. Open None (just a launcher) Main Process (Node.js) Renderer Process (Chromium) React.js Spawn + Common Lisp
  26. 26. Open None (just a launcher) Main Process (Node.js) Renderer Process (Chromium) React.js Common Lisp Process (SBCL) Spawn + Common Lisp
  27. 27. Open None (just a launcher) Main Process (Node.js) Renderer Process (Chromium) React.js Common Lisp Process (SBCL) Spawn Bidirectional Communication + Common Lisp
  28. 28. Open None (just a launcher) Main Process (Node.js) Renderer Process (Chromium) React.js Common Lisp Process (SBCL) Spawn Bidirectional Communication + Common Lisp Make an SBCL executable and bundle it
  29. 29. Looks a quite easy trick, huh? :)
  30. 30. How communicating between CL and Browser
  31. 31. Open None (just a launcher) Main Process (Node.js) Renderer Process (Chromium) React.js Common Lisp Process (SBCL) Spawn Bidirectional Communication + Common Lisp
  32. 32. Open None (just a launcher) Main Process (Node.js) Renderer Process (Chromium) React.js Common Lisp Process (SBCL) Spawn Bidirectional Communication + Common Lisp
  33. 33. Communication between CL and Browser • MUST be bidirectional • MUST be asynchronous • MUST be easy to handle with JavaScript • SHOULD be real-time
  34. 34. We decided to use JSON-RPC • Small specification • Not depends on a specific transport layer • We use WebSocket • http://jsonrpc.org • https://github.com/fukamachi/jsonrpc
  35. 35. JSON-RPC --> {"jsonrpc": “2.0", "method": “subtract", "params": [42, 23], "id": 1} Request
  36. 36. JSON-RPC --> {"jsonrpc": “2.0", "method": “subtract", "params": [42, 23], "id": 1} Request <-- {"jsonrpc": “2.0", "result": 19, "id": 1} Response
  37. 37. JSON-RPC --> {"jsonrpc": “2.0", "method": “subtract", "params": [42, 23], "id": 1} Request <-- {"jsonrpc": “2.0", "result": 19, "id": 1} Response --> {"jsonrpc": “2.0", "method": “update", "params": [1,2,3,4,5]} Notification (Request without “id”)
  38. 38. How to structure GUI Application with Electron
  39. 39. No best practices (yet) to build an Electron app.
  40. 40. In our case
  41. 41. Renderer Process Store View ActionReducer Flux Architecture
  42. 42. functionfunctionfunctionfunction functionfunctionfunctionfunctionfunctionfunctionfunction Renderer Process Store View ActionReducer Flux Architecture Common Lisp JSON-RPC server functionfunctionfunction functionfunctionfunction ← JSON-RPC over WebSocket →
  43. 43. Not only Browser Common Lisp
  44. 44. Coin Counter IC Card Reader Printer API Server
  45. 45. Benefits of Flux + JRPC Architecture • JavaScript part is just a UI renderer • Business logics are all in Common Lisp • Common Lisp functions are easy to test • Other components are also easy to test • Because they all talk in JSON-RPC
  46. 46. How to develop the app
  47. 47. Development • You can use your machine (Mac, Linux, etc) • Virtual devices are used while development • Easy to make a mock of components
  48. 48. Development 1. Run a Electron process (npm run dev) 2. Open REPL of the Common Lisp process
 from Emacs with Swank 3. Enjoy
  49. 49. Packaging 1. Run Windows in Virtual Environment 2. npm run package 3. Wait
  50. 50. Experiments
  51. 51. Coin Counter IC Card Reader Printer API Server
  52. 52. Coin Counter IC Card Reader Printer API Server Hard to share data.
  53. 53. “brain”, the central storage • All data(state) are in Common Lisp part • What service the user chose? • How much money is in the user’s IC card? • How many coins are in? • etc. • It’s just a hash-table (with thread-lock).
  54. 54. “Propagation Class” Metaclass for synchronize data between components
  55. 55. “Propagation Class” (defclass user () ((balance :initarg :balance :accessor user-balance) (coins :initarg :coins :accessor user-coins)) (:metaclass propagation-class))
  56. 56. “Propagation Class” (defclass user () ((balance :initarg :balance :accessor user-balance) (coins :initarg :coins :accessor user-coins)) (:metaclass propagation-class)) (defmethod on-update ((user user) slot-name) (declare (ignore slot-name)) (notify “browser” “user/update-state” user))
  57. 57. “Propagation Class” (defvar *user* (make-instance ‘user …))) ;; Notify this modification ;; to the browser implicitly. (setf (user-balance *user*) 1730) Bless the Meta Object Protocol.
  58. 58. So, Why Common Lisp?
  59. 59. Why Common Lisp? • We ♥ Common Lisp :) • Good for writing unknown/complicated applications. • Interactive development with REPL.
  60. 60. Thanks.

×