Fork me on GitHub
#hoplon
<
2016-06-04
>
leontalbot02:06:14

Thanks ! I found the fix and had to go. Will try when I encounter another error... thanks a lot @micha

thedavidmeister09:06:49

@micha @leontalbot i was literally going to ask the same thing. Castra errors are very cryptic 😛

thedavidmeister12:06:40

@micha you should probably write something in the wiki about performance

thedavidmeister12:06:49

i see people constantly asking the same questions

micha13:06:44

it's a difficult thing to write about though

alandipert13:06:33

Everyone get flame retardant suits on

micha13:06:54

asbestos underpants on

micha13:06:52

man, i don't know why adzerk doesn't advertise on that subreddit

thedavidmeister13:06:43

also, i just wanted to say that i’ve done a few things recently quite fast in hoplon and with minimal bugs

thedavidmeister13:06:59

now that i’m feeling a bit more comfortable with it i’m feeling pretty productive 🙂

micha13:06:07

that's awesome to hear!

micha13:06:15

what kind of projects?

thedavidmeister13:06:21

i built a dashboard at work where i grabbed all the tickets and state transitions from pivotal tracker

thedavidmeister13:06:28

and all the ideas from prod pad

thedavidmeister13:06:47

and made a “conveyer belt” with live updates showing the in/out for each state

thedavidmeister13:06:01

so we could see any bottle necks in our delivery process

micha13:06:12

this is the dream unfolding

micha13:06:29

being able to bang out workflow type things

micha13:06:40

and not get bogged down in webapp nonsense

thedavidmeister13:06:05

i also made boot tasks to give cli tools to get the same info

thedavidmeister13:06:25

and made one to spit out all our release notes for anything deployed on a given day

micha13:06:14

that's sweet

micha13:06:37

that was pretty much how we started developing hoplon

thedavidmeister13:06:45

yeah, i did the whole thing in under a week, including general meetings and managing the team getting in the way as well

micha13:06:46

we needed almost exactly that type of thing

micha13:06:18

we were making different frontends for our php backend

micha13:06:25

and cli tools etc

micha13:06:44

we had a huge hairy ERP thing written in like 250K lines of php

micha13:06:26

modifying anything in there was a major hassle

thedavidmeister13:06:03

yeah, i’m still learning about how i like to do hoplon

thedavidmeister13:06:26

like, i tried a new file structure last week and that helped, although i had to refactor a bunch of stuff

thedavidmeister13:06:48

i now have a folder for each “thing” and stick dom.cljs, state.cljs and wire.cljs in it

micha13:06:40

yeah i still don't know what the best way to organize a large project source is

thedavidmeister13:06:02

well, i got the thumbs up from my gf when she wanted to do some sassing

thedavidmeister13:06:13

she said “oh great, now i can see which bits i’m allowed to change” 😛

micha13:06:16

i think once hoplon/ui is solid that will solve most of that problem for me

micha13:06:21

yeah totally

micha13:06:42

without a real ui kit like hoplon/ui i end up making ui kit stuff in the project

thedavidmeister13:06:51

well, if i learn how to use clojars

thedavidmeister13:06:03

i might start putting the “things” up

micha13:06:09

so then i have like general type components that can be one day separated out into a library, and ui stuff that's specific to the application, etc

thedavidmeister13:06:09

so i can pull them in on projects

micha13:06:20

yeah that's the real solution i think

thedavidmeister13:06:35

like, i have a spinny wheel where you can add and remove “things that are loading"

micha13:06:36

but when you're working to deadlines it's hard to keep it all organized at that level

thedavidmeister13:06:52

and it will gain a data attribute when at least one thing is loading

thedavidmeister14:06:02

that could be useful on any project really

micha14:06:06

yeah totally

thedavidmeister14:06:20

and i have another one that puts system messages in a datascript db

thedavidmeister14:06:32

and you can flag each message as “seen"

thedavidmeister14:06:42

with a little X icon

micha14:06:04

i think every real application needs one of those these days

micha14:06:15

since everything is a distributed system and asynchronous now

thedavidmeister14:06:38

and one that captures “last down” and “last up” keys pressed as the events bubble through it...

thedavidmeister14:06:49

so yeah, i want to move these somewhere at some point

micha14:06:54

the user needs to have an event log where they can see the progress of asynchronous processes

micha14:06:11

like in our application the user can request reports and things that might take some time to complete

micha14:06:20

they're processed via work queues and whatnot

micha14:06:29

and are subject to rate limiting and so on

micha14:06:55

so we need to have an event log like you made to give the user access to those jobs that might be running in the cloud

micha14:06:44

having a solid custom element for that would be very useful in all of the things we make

thedavidmeister14:06:48

atm, things that are just dom and state can probably go anywhere

thedavidmeister14:06:59

and it would be nice to get feedback on them and make them more general

thedavidmeister14:06:28

i gotta think about how something that has wire might be portable

thedavidmeister14:06:56

like, anything that goes remote

micha14:06:18

ah ok, like talking to the server or whatever

thedavidmeister14:06:36

even if i’m not using castra, i take the cell approach as much as possible

micha14:06:56

i have found that defining that kind of thing in terms of a more abstract state machine helps

micha14:06:22

like i made this form-machine thing

micha14:06:36

a state machine for mediating access to a backend service

micha14:06:49

i use it for talking to a castra backend

micha14:06:55

but that part is abstract

micha14:06:09

the form machine just calls a function you provide when you create it

micha14:06:17

and that function calls out to castra

micha14:06:32

so the actual work is not done by the machine

micha14:06:43

the function just returns a jquery promise

micha14:06:54

so really any async function can work there

micha14:06:32

and the form machine exposes its state as javelin cels

micha14:06:56

and protocol methods on the machine instance

micha14:06:07

so you can wire it up to any ui element via attributes

micha14:06:36

the form machine handles the statefulness of talking to the backend

micha14:06:45

like retries, errors, and so on

thedavidmeister14:06:02

so i haven’t got anywhere near that complicated

thedavidmeister14:06:38

i spend most of my time in state and dom

thedavidmeister14:06:48

and just put the bit that will probably break in wire

thedavidmeister14:06:59

so at least i know where to look when something breaks 😛

micha14:06:43

and hoplon helps keep things sane by exposing all the knobs as attributes that can take cells or functions as values

micha14:06:51

it's hard to get things too coupled that way

micha14:06:18

like as long as you provide a cell with the same type of values you'll be portable in other apps

micha14:06:38

i mean in the ui layer

micha14:06:48

and how it is wired to the application state

thedavidmeister14:06:59

yeah actually that’s true

thedavidmeister14:06:14

i can just provide instructions on how to put the data coming from your wire into my state

micha14:06:39

yeah in hoplon attributes are sort of like methods on the element itself

micha14:06:49

when you set the value that method is called

micha14:06:56

so the attributes form the API for the element

micha14:06:21

hook the attribute up to a cell and the method is called whenever the cell's value changes

thedavidmeister14:06:26

that’s not useful outside this project at all

thedavidmeister14:06:14

but if it actually was, you could totally BYO wire and hook it into project.state/all and project.state/current

micha14:06:33

exactly yes

micha14:06:21

there is of course a pretty clear distinction between "application" and "supporting library code" that evolves over time

micha14:06:47

if you are the type to refactor things when you add new features, as i think most people who like lisp are

thedavidmeister14:06:13

lol, i refactor things to achieve new features

micha14:06:33

some people will find any way to just add more code without refactoring anything

micha14:06:45

this php app was like that for many years

micha14:06:14

but clojure encourages refactoring when new knowledge comes to light i think

micha14:06:28

not as much retyping of boilerplate

thedavidmeister14:06:37

i’m finding clojure and hoplon very natural to the way i like to think

micha14:06:38

and not as many regressions introduces

thedavidmeister14:06:42

now that i know how it actually works...

thedavidmeister14:06:12

i was basically doing a lot of this stuff manually and buggily in js for years

thedavidmeister14:06:20

reinventing the same wheel >.<

micha14:06:53

man i tried all the js things, up to knockout.js

micha14:06:00

each time was the same depressing experience

micha14:06:12

like i'd start on the project and be all excited and confident

micha14:06:20

like ok now i know the pitfalls to avoid

micha14:06:28

this one is going to be good

micha14:06:44

but then i'd make the demo and everything is still all organized and nice

micha14:06:01

and the various "stakeholders" would start proposing changes that i never imagined

thedavidmeister14:06:36

yes, this is very normal for web dev...

micha14:06:42

like "why does this button show up in this state, that's confusing. we should move it over there when the user has done this weird thing, and over there when the user did this other thing"

thedavidmeister14:06:53

although today i was saying to my gf “yeah, just tell me whatever you want and i’ll build it, no worries"

thedavidmeister14:06:02

which was refreshing

micha14:06:06

so i'd start making modifications, but it would end up ruining the architecture

micha14:06:40

and in the end i'd have a crappy thing that wasn't really a result of an architecture, more like an organic mass of special cases

micha14:06:01

but with clojure and cljs and stuff i don't have that anymore

thedavidmeister14:06:52

at the same time though, it’s hard to get the right info on hoplon as a n00b

micha14:06:06

knockout.js and angular.js, when those came out and still didn't solve things that's when we decided to just make hoplon and see if it would help

thedavidmeister14:06:08

i knew zero cljs when i started, so reading through the codebase wasn’t an option

micha14:06:47

it's weird how difficult it is to document properly

micha14:06:08

i don't find it easy to write docs for newcomers

thedavidmeister14:06:17

i can write docs 🙂

thedavidmeister14:06:35

i’ll try to find some time to write up something tomoz

micha14:06:42

that would be awesome

thedavidmeister14:06:19

i got a few things on my todo

thedavidmeister14:06:24

there’s the same performance q's

micha14:06:41

i want to revive the missile-command game

micha14:06:53

to illustrate the performance concerns

thedavidmeister14:06:15

i think the summary should just be “cells in memory are faster than dom, and they stop propagation as soon as they can, so stop stressing, it’s faster than your hand coded special cases"

micha14:06:50

yep and also ui elements that encapsulate their own state means that you don't need to touch them as often from your application

micha14:06:05

which also makes things more efficient

thedavidmeister14:06:05

and i want to write about the confusing things that happen if you don’t explicitly reset cells to a default case, so kind of “default states, and dosync"

micha14:06:33

the missile-command game is a good example of how encapsulation of local state makes things perform well

thedavidmeister14:06:33

because that really confused me for ages, and it tripped up a bunch of people in chat too

thedavidmeister14:06:55

and i want to write about storage atoms too 🙂

thedavidmeister14:06:35

actually, @micha do you have any information about how cells work with animation frames, etc.

thedavidmeister14:06:07

is there anything going on there, or in jquery?

micha14:06:36

no, that's the cool part i think

micha14:06:56

we for missile command you have missiles that are coming in from outer space toward your cities

micha14:06:19

and you can click anywere to launch a anti-ballistic missile at the incoming missile

micha14:06:30

you click wher you want the defense missile to explode

micha14:06:53

if the icbm is in the radious of the blast from your anti-missile then you destroy the icbm

micha14:06:07

so the problem is that you can have many missiles incoming

micha14:06:14

and many anti-missiles outgoing

micha14:06:26

and you need to manage collisions and explosions and sound effects

micha14:06:37

the way we did it was by making stateful custom elements

micha14:06:42

using svg in our case

micha14:06:49

so we had a missile element

micha14:06:04

it has an attribute whose value is a trajectory

micha14:06:25

we can animate that trajectory using svg animations and transforms etc

micha14:06:49

so those animations will run at 60fps no problem, directly from the gpu

micha14:06:14

the game's "render" loop ran at 100ms intervals

micha14:06:17

which is very long

micha14:06:21

60fps is like 16ms

thedavidmeister14:06:28

and you did that in hoplon?

thedavidmeister14:06:35

i hadn’t thought of canvas elements

micha14:06:46

our render loop just updated the cells that contain the missile trajectories

micha14:06:55

and the collisions

micha14:06:11

so as the user would interact with the game, launching missiles whatever

micha14:06:28

every 100ms the trajectories of all the things in motion would be updated accordingly

micha14:06:46

but we delegate the actual rendering and animation and so on to the custom elements

micha14:06:53

like the missile elements and whatnot

micha14:06:14

that encapsulation of state in those elements allows us to leverage the gpu as much as possible

micha14:06:30

the game logic doesn't know anything about how to render a missile

micha14:06:36

or how to animate anyhting

micha14:06:39

it doesn't need to

micha14:06:49

and that's kind of the central theme of hoplon performance

micha14:06:02

you delegate those things to dom elements

micha14:06:36

like if we needed to update the position of every missile via javelin cells we would get terrible performance

micha14:06:46

javelin cells are way slower than atoms

micha14:06:06

but because of the dependency graph and so on that cells provide you can use higher level abstractions

micha14:06:17

so that kind of low level rendering is unnecessary

micha14:06:25

that's what's difficult to explain i think

micha14:06:38

because performance comparisons are apples-to-oranges

thedavidmeister14:06:41

you probably need both

thedavidmeister14:06:48

you probably need the high-end tech demo

thedavidmeister14:06:53

that makes perfect sense to me

thedavidmeister14:06:14

and you probably need the “nobody got fired for choosing hoplon” style summary/disclaimer

thedavidmeister14:06:18

i feel that’s reading between the lines of the constant performance questions

thedavidmeister14:06:31

it’s like when you eat something delicious you assume it must be bad for you somehow 😉

micha14:06:36

ahah right

micha14:06:57

also it's the worst when you don't see performance problems until you have a huge application with a lot of time invested in it

micha14:06:02

and then you need to shitcan it

micha14:06:18

so i can understand people being worried about that

thedavidmeister14:06:18

yeah, i’m still hoping that doesn’t happen to me

micha14:06:29

we have a pretty huge app at adzerk now

micha14:06:41

it's way faster than anything comparable

micha14:06:46

i mean in terms of experience

micha14:06:59

our app is comparable to like the aws console

micha14:06:13

very similar problems and workflows

micha14:06:31

all talking to distributed systems and so on

micha14:06:39

like in our app everything must be paginated

micha14:06:58

like we have maybe 1 or two <select> elements in the whole app

micha14:06:12

because users can create millions of anything via our API

micha14:06:15

things like that

micha14:06:32

so we use typeahead everywhere, with pagination and so on

micha14:06:43

and it's all instantaneous

thedavidmeister14:06:54

i’m not building anything that complicated

micha14:06:11

we didn't really need to optimize anything to get good performance

thedavidmeister14:06:25

i’m trying to make an app to help people estimate how much work goes into something

thedavidmeister14:06:31

so it’s not on that scale, i don’t think

micha14:06:31

a lot of the efficiency comes from the pooling of elements in loop-tpl

micha14:06:59

once we create the application it needs to do very little additional work when you interact with it

micha14:06:07

but it does take like 5-10s to load

micha14:06:13

similar to slack

thedavidmeister14:06:34

i’m working on an overlay to make it a bit friendlier

micha14:06:53

yeah i have a gist of what we have for http://app.adzerk.com

micha14:06:58

if that would help

thedavidmeister14:06:28

oh, actually it’s super easy, the overlay

thedavidmeister14:06:47

i’m just using an if-tpl on a “things are loading” cell

thedavidmeister14:06:55

very similar to the spinny wheel

thedavidmeister14:06:04

but it looks like shit 😛

thedavidmeister14:06:11

so when i say “i’m working on it"

thedavidmeister14:06:16

i mean “i’m waiting for the pretty"

micha14:06:35

we're loading a ton of css, so we ran into issues with flashing unstyled content and whatnot

micha14:06:54

but we were able to fix that with prerendering

thedavidmeister14:06:20

i’m really not too bothered by the idea of an overlay like what you have

thedavidmeister14:06:29

i think it’s getting more and more normal

thedavidmeister14:06:41

i see it around the place

micha14:06:02

yeah, our app is used by people who start it up once and then work in there all day

micha14:06:05

like gmail

micha14:06:12

so the cost is amortized

micha14:06:35

or like slack

micha14:06:40

slack takes some time to load

micha14:06:08

the bad thing is taking a long time to load and having memory leaks so you need to refresh all the time lol

thedavidmeister14:06:34

if you put the loading screen

micha14:06:36

loop-tpl helps there too

thedavidmeister14:06:39

it better be fast once it loaded

thedavidmeister14:06:41

you have to pick

thedavidmeister14:06:59

it’s either a traditional page refreshy site

thedavidmeister14:06:10

or you have a loading period and then keep things snappy after that

micha14:06:25

if you're loading js, there is no way to speed that up

micha14:06:31

other than by writing less code

micha14:06:45

but then you need to refresh more to load different small pieces of js

micha14:06:16

like either one large js program and few refreshes, or many tiny js programs and refresh a lot

micha14:06:32

an interesting spectrum

thedavidmeister14:06:22

surely cljs can fix this somehow

thedavidmeister14:06:29

with the whole “code is data” thing

micha14:06:41

yeah, the hard part is imagining a good model

micha14:06:47

like abstractly

micha14:06:12

i'm confident that anything that can be imagined can be implemented in clojure

thedavidmeister14:06:32

i just did a release

thedavidmeister14:06:37

and it works with a real db

thedavidmeister14:06:44

ah cells are cool

micha14:06:46

💥 🍾

thedavidmeister14:06:22

i got a “current project” cell, and then a function that gets all the data for a given project

thedavidmeister14:06:27

and a cell= hooking the two up

thedavidmeister14:06:20

(j/cell= (if  (and sente.state/ws-first-open? project.state/current)
              (fetch-all! (:id project.state/current))))

thedavidmeister15:06:41

anyway, i’m gonna cruise now that i have that up

thedavidmeister15:06:14

@micha one day i’ll bug you about how to put things on clojars, then we can share “things"

micha15:06:36

you can see the hoplon build.boot

micha15:06:57

doesn't take much configuration to get clojars working

micha15:06:45

like for hoplon i can make a clojars release with boot build-jar push-release

mhr16:06:13

@micha, I read the todomvc for all of the examples in https://github.com/gadfly361/cljs-todomvc, and hoplon's seemed to be the most elegant and straightforward! Brilliant!

micha16:06:30

i wonder if it would be good to refactor it a little to use custom elements?

micha16:06:05

like make a todo-item component and so on

mhr16:06:28

also if you do make that change, don't forget to update the todoFRP-html demo as well to match it

micha16:06:45

wow some of those things are pretty out-there

micha16:06:52

8 cljs namespaces

mhr16:06:23

oh you mean in those todomvc library examples

mhr16:06:00

yeah, I was really surprised to see that much namespacing for that example

mhr16:06:23

especially since you'd think of todomvc as relatively simple, why would all that be necessary?

micha16:06:14

it's interesting, because i think something small like todomvc is useful as a sort of yardstick

micha16:06:53

because being able to do simple things simply, without a lot of boilerplate nonsense is the key building block for making more complex things

micha16:06:11

if you can't do a simple thing simply, then you won't be able to build a more complex thing out fo simpler things

micha16:06:38

this is kind of the issue i have with all the inversion-of-control approaches i guess

mhr16:06:07

whenever I try out a new tool or technique I always search for a todo-mvc equivalent to probe for that kind of property

micha16:06:54

ah, it just links from https://github.com/gadfly361/cljs-todomvc to the hoplon demos repo

micha16:06:10

so the change would only need to be made in one place

mhr16:06:42

please let me know if/when you make that change, I'd like to see