Building GUI App with Electron and Lisp

Post on 05-Apr-2017

2.698 views 3 download

Transcript of Building GUI App with Electron and Lisp

How Building GUI App with Lisp The Case of Pocket Change, Inc.

LISP MEETUP #50 Mar 27, 2017

I’m Eitaro Fukamachi @nitro_idiot fukamachi

Joined Pocket Change in Feb 1

Pocket Change

http://www.pocket-change.jp

Available at Haneda Airport

Today’s topic

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

Touch Screen

Coins BillsIC Card Reader

Receipt Printer

API Server

Touch Screen

Coins BillsIC Card Reader

Receipt Printer

API Server

Building the next version of this software is my work.

How to build Pocket Change

• Windows OS (Rich!)

• Fullscreen GUI application

We decided to use Electron

https://electron.atom.io

by

Web Server (Express)

Main Process (Node.js)

Open

Web Server (Express)

Main Process (Node.js)

Open

Web Server (Express)

Main Process (Node.js)

Renderer Process (Chromium)

React.js

Open

Web Server (Express)

Main Process (Node.js)

Bidirectional Communication

Renderer Process (Chromium)

React.js

Why Electron?

• Easy to deploy

• Can package into a single EXE installer

• Can build GUI with Web technologies

• Embedded Chromium

However

The language is JavaScript. 👎

Why can’t we use Common Lisp?

None (just a launcher)

Main Process (Node.js)

+ Common Lisp

Open

None (just a launcher)

Main Process (Node.js)

+ Common Lisp

Open

None (just a launcher)

Main Process (Node.js)

Renderer Process (Chromium)

React.js

+ Common Lisp

Open

None (just a launcher)

Main Process (Node.js)

Renderer Process (Chromium)

React.js

Spawn

+ Common Lisp

Open

None (just a launcher)

Main Process (Node.js)

Renderer Process (Chromium)

React.js

Common Lisp Process (SBCL)

Spawn

+ Common Lisp

Open

None (just a launcher)

Main Process (Node.js)

Renderer Process (Chromium)

React.js

Common Lisp Process (SBCL)

Spawn

Bidirectional Communication

+ Common Lisp

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

Looks a quite easy trick, huh? :)

How communicating between CL and Browser

Open

None (just a launcher)

Main Process (Node.js)

Renderer Process (Chromium)

React.js

Common Lisp Process (SBCL)

Spawn

Bidirectional Communication

+ Common Lisp

Open

None (just a launcher)

Main Process (Node.js)

Renderer Process (Chromium)

React.js

Common Lisp Process (SBCL)

Spawn

Bidirectional Communication

+ Common Lisp

Communication between CL and Browser

• MUST be bidirectional

• MUST be asynchronous

• MUST be easy to handle with JavaScript

• SHOULD be real-time

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

JSON-RPC--> {"jsonrpc": “2.0", "method": “subtract", "params": [42, 23], "id": 1}

Request

JSON-RPC--> {"jsonrpc": “2.0", "method": “subtract", "params": [42, 23], "id": 1}

Request

<-- {"jsonrpc": “2.0", "result": 19, "id": 1}

Response

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

How to structure GUI Application with Electron

No best practices (yet) to build an Electron app.

In our case

Renderer Process

Store

View

Action Reducer

Flux Architecture

functionfunctionfunctionfunctionfunctionfunctionfunctionfunctionfunctionfunctionfunction

Renderer Process

Store

View

ActionReducer

Flux Architecture

Common Lisp

JSON-RPC serverfunctionfunctionfunction

functionfunctionfunction

← JSON-RPC over WebSocket →

Not only Browser ⇔ Common Lisp

Coin Counter IC Card Reader PrinterAPI Server

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

How to develop the app

Development

• You can use your machine (Mac, Linux, etc)

• Virtual devices are used while development

• Easy to make a mock of components

Development

1. Run a Electron process (npm run dev)

2. Open REPL of the Common Lisp process from Emacs with Swank

3. Enjoy

Packaging

1. Run Windows in Virtual Environment

2. npm run package

3. Wait

Experiments

Coin Counter IC Card Reader PrinterAPI Server

Coin Counter IC Card Reader PrinterAPI Server

Hard to share data.

“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).

“Propagation Class”Metaclass for synchronize data between components

“Propagation Class”

(defclass user () ((balance :initarg :balance :accessor user-balance) (coins :initarg :coins :accessor user-coins)) (:metaclass propagation-class))

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

“Propagation Class”

(defvar *user* (make-instance ‘user …)))

;; Notify this modification ;; to the browser implicitly. (setf (user-balance *user*) 1730)

Bless the Meta Object Protocol.

So, Why Common Lisp?

Why Common Lisp?

• We ♥ Common Lisp :)

• Good for writing unknown/complicated applications.

• Interactive development with REPL.

Thanks.