## Cross Platform Awesomeness
### by Henry Widd
![alt text](/images/plumbing-brain.svg "How apps should be")
we understand that the aim is to write pure functions and have them wired together by the plumbing
the pure functions are the decision makers, the brains of the app
pure functions accept and return data:
no async constructs: promises, core.async channels, manifold deferred's etc.
no mutable objects - e.g. atoms
any IO is out - that stays at the edge of the system
database connections etc -
library/framework gunk: re-frame, lacinia resolvers, interceptors
### Question: Is all your brains code cross platform?
(in .cljc files)
Could it be?
### Why Do that?
Clients keep asking me to build apps that involve both server and client components.
Prefer to avoid Node for the server platform if possible
Often the case you need shared brains on server and client
- some brains need to be on the server
- responsive app, server does the validation
- server needs to generate similar data views to the ui - e.g. send in email
- client needs to construct queries and the server deconstructs
Nice to have aspect, keeps me honest - not forced to do this by Clojure
Work with the same data (and specs) by default -
avoid... oh, camel case here because come via our rest service and snake on the server, or big 2-d result set on server and different on client
ns containing decisions about some concept, another with the specs for that concept
## What gets in the way?
(IOW What forces us to include more reader conditionals?)
### Platform Differences
Concurrency model etc not an issue for what we're talking about here
Need to drop to native string, date functions
Reminder: We're not doing IO for this bit
Not total fidelity between the two (e.g. no equivalent of clojure.core/extend in ClojureScript)
.... ah, libraries. Thankfully, there are lots of cross-platform libraries since the introduction of cljc
and quite a few that aren't yet.
## Every application .cljc file ever
#?(:clj [clj-time.core :as ct]
:cljs [cljs-time.core :as ct])
to date... the only way to do cross platform date logic
Most applications I write involve significant date logic
this works ok for some use cases
cross platform or not, chances are you are using these either directly or indirectly
A replacement for the clj-time and cljs-time libraries
clj-time - wrapper over Joda-Time (well loved)
Ubiquitous in clj land
joda-time improved upon by java.time - which comes with the platform (so now common ground for libraries etc)
cljs-time - partial fidelity with clj-time fns, wrapper over js/Date
- locals not fully supported, and wrapping platform date
- timezones not supported
need a way to convey date info on wire
aside - what boxes does the wrapper tick (functional api, clojure-y api (less verbose), add features)
#### java.time (jsr310) date objects
![jsr310 domain](/images/jsr310-domain.svg "jsr310-domain" )
easier to grok than joda time
separation of machine and human time
* Intuitive api for jsr310 domain
* Interval Calculus
* Data literals
* ... for Clojure and Clojurescript!
compose, decompose, shift etc etc
see docs and Malcolm's clojure exchange talk for info on intervals
data literals handy for the repl, storing dates
drop to java.time when you need to. stackoverflow friendly. applies to cljs
## Tick Origins
* brainchild of and mainly authored by Malcolm Sparks
* originally scheduling focused
* now full api for working with java.time + intervals
* I started work on cljc'ing clojure.java-time in early 2017 (then abandoned)
* ... later I teamed up with Malcolm to make Tick cross-platform early in 2018
* and create data literals
### The Ecosystem
![alt text](/images/tick-ecosystem.svg "Tick ecosystem")
* API for jsr-310 domain
* JVM only
* Additionally has
* conversions to/from joda-time and java.sql objects.
* extension for threeten-extra
## Future Work
* spec fns (and generators, along the lines of s/inst-in)
## Start using it!