Elm and Phoenix/Elixir in Production for France TV
vincent.jousse.org
vincent.jousse.org
I know the Elm team is capable of all of these—I just haven't heard of anything yet. While they're "nice to have" now, these features might become crucial and important.
Another interesting thing about Elm is its progressive removal of features (I think the infix operator was or is going to be removed soon) in order to make the language more approachable. I actually support this because if you need "true" ML/Haskell features, there's PureScript.
Anyway, glad to see Elixir and Elm being used productively!
The container can be <body>, but you can just as well attach to some <div> in the footer and the rest is rendered independent of Elm.
Regarding dead code elimination: yeah, elm doesn't do it yet. But the code generated by elm-make is very predictable and therefore easy to process. I just tried uglifyjs:
raw elm-make output; 196kb
uglifyjs -m -c: 68kb
tar czf: 20k
The inventor of elm is very deliberate in the project's development. I believe his argument is that including dead code elimination now is premature, because it adds a lot of maintenance work, especially at a time where the language is still evolving. Once the raw js is no longer a moving target it shouldn't be too difficult, and until then uglify and similar do a good job.
I love Clojurescript as a language, but using it alongside existing js libraries is awkward and error-prone, and getting the build process to work smoothly takes way more time than it should. Cljs gets a lot right too, but it shouldn't be held up as an example in this regard.
There was a DCE branch at one point but it never got finished.
This is what bothers me about Elm. In the next few months, I'll be starting on a site project, and I've been fiddling with Elm and I don't see how I can create progressive web apps with it. It doesn't seem to play well with service workers for an offline mode, and there's no fallback if Javascript is disabled. Either it loads or it doesn't.
I want to use Elm, I don't want to use JavaScript, but I also want a progressive web app that will offer some functionality offline. I guess there's a way to do some server-side stuff with Phoenix, but then the front-end / back-end division isn't so clear and I'd end up using JavaScript for the service workers anyway.
I've not looked super deep into this, so I'd be happy to be corrected if I've got the wrong end of the stick here.
Of course it would be nicer to be able to write everything in Elm, but I find having the majority of your app in Elm with a bit of JS is significantly nicer than having the whole app in JS.
You can make it nicer still by using Typescript instead of Javascript, and defining interfaces for the data going through the ports, giving you type safety across the whole stack.
I'm using this approach right now in a mobile Elm/Typescript app with great success.
Yet I worry about adding Elm to new projects, mostly because it raises the level of developer I need to hire to maintain it. I'm not in SV or in a tech hotspot at all, so maybe I have to think about this more than the average HN reader.
Personally, I'm actually not the biggest fan of the design philosophy behind Elm, but I do have to admit it's easy to learn with some great introductory learning materials. Getting somebody motivated up to speed on maintaining Elm is not an issue.
For what it's worth, I think the same is true of Haskell-style languages in general: with a bit of guidance, it's not hard to make new programmers productive. That's the experience IMVU[1] had when switching several internal projects to Haskell from PHP, if you want a case study. I met the lead engineer who wrote that post once and he explained that it actually took about as long to train an incoming developer (with no FP experience) in Haskell as it did to train incoming PHP developers on IMVU's in-house PHP "flavor" (frameworks, code organization... etc).
Picking up Haskell or Elm is a bit difficult by yourself for a few reasons: there's no clear path on what to learn, the learning materials are a bit hit-or-miss and there's a lot of incidental complexity. However, if you provide a bit of guidance (ie curate libraries) and help overcome some of the incidental complexity (ie install the compiler and tools) it's surprisingly accessible.
[1]: https://engineering.imvu.com/2014/03/24/what-its-like-to-use... (see "Training" section especially)
When it comes to dead code elimination, it is true that the compiler currently does not have that. Luckily, the compiled js is just a series of functions (namespaces is a part of the function name, like namespace$functionname) and so a tool like uglify has no problem removing dead code. A minified Elm app is smaller than a minified React app.
Hardly. Server rendering remains at best a novelty, and "progressive web apps" are not coming back anytime soon.
http://tech.noredink.com/post/126978281075/walkthrough-intro...
I'm sorry to be so negative but I really hope your comment doesn't remain the top comment as it's not very well-informed at all.
One little comment. At the beginning of the post, you make it seem like the app needs to scale with the number of viewers, when in fact it doesn't. I think you should clarify this to avoid confusion.
Also being a functional language it is easy to crank out features in an afterthought, e.g. we added an Undo/Redo feature for operations the user does in this single-page client app. And being side-effect free this "merely" boils down in wrapping function calls in an "undo/redo" function.
So Elm is really exciting stuff. But still the Api is not completely stable, yet. So you have to invest some time to adapt to these (small) Api changes. Also interoperablility with so-called "Native" JavaScript browser functions, e.g. JavaScript typed arrays is possible but not finalized, yet.
Scala gives you the options to do it right, but Elm enforces it. Heck, because of how the application type works, its pretty much impossible to make an Elm app that doesn't follow proper architecture. It just won't compile.
Another cool thing is the option to use either a pure expression-based functional approach or a OOP approach, or even a mix between the two.
On my side, if i have the choice between boilerplate or having to debug runtime errors, I'll pick the boilerplate any day. If my product manager thinks its worth it to push a feature earlier (and risking having it blow up), well, I'll go work for someone else ;)
On the Javascript side, the Elm `app` is like an event emitter where you listen for updates and send it data.
var app = Elm.Main.embed(...)
app.ports.gameState.subscribe((data) => ...)
app.ports.tileClick.send([x, y])
On the Elm side, you subscribe to incoming ports and map them into Msgs. And you emit to ports with Cmds from your update function. -- Ports.elm
port gameState : Json.Encode.Value -> Cmd msg // Outgoing
port tileClicked : ((Int, Int) -> msg) -> Sub msg // Incoming
-- Main.elm
update msg model =
case msg of
Tick ->
-- Define `encode` to Json.Encode the game state
(model, Ports.gameState (GameState.encode data))
TileClicked (x, y) ->
-- Handle tile clicks sent in from Javascript
subscriptions model =
Ports.tileClicked TileClickedWhat I'm concerned about is the case when I want to call a Javascript function from deep down inside, say, a computation function. Do I have to split my computation into two halves, one which sends the event which calls the Javascript function, and another which receives the result of the function? How do I pass the in-progress computation state from one to the other? Normally in a functional language I'd get around this by simply passing a function reference into the Javascript function which the handler would then call, so allowing me to have both parts of the computation in the same place and operating on the same data, but apparently in Elm function references don't survive being passed through Javascript.
Plus, each port only has a single incoming event, so if I'm calling the Javascript function from multiple places I can imagine it can very easily turn into a labyrinth of state passing code.
How do you avoid this?
Then there's synchronous 3rd party library stuff where you just want to execute a Javascript function, like a math function that you aren't going to reimplement in Elm. In that case, I wrap the function with a native module and call it like an Elm function. Since you talk of computation, is this what you're talking about?
The Elm community highly discourages native modules. For one thing, they aren't very well documented and the API seems to have recently changed. But I'm not sure what the alternative is.
I am a big fan of functional languages, but I don't take for granted that they allow us to crank out any additional feature easily. The ease of adding of undo/redo functionality is a common selling point, but it seems to fall out directly from a preference for immutable data.
Do you miss this in the backend with Elixir?
I would love to do it in Elixir with Phoenix, but this would mean the team has to learn another tool. Go is really easy and fast to pick up. Here the Go Toolchain/Ecosystem matters, which is easy to grasp, and you get a type system, which is not as sophisticated as in Elm, but fits the job.
An older project was done with Grails/Groovy. This was fun and fast to iterate. But after a while, when you come back to the old project code, it is hard to get the dynamic types into your head. So actually I would prefer a static type system. I know there is some tool for Elixir to handle this. But I did not look into this.
I love it.
This is nonsense. There's a much greater pool of talent familiar with javascript than Elm.
Using Elm might be marketable ("come work with Elm here!"), but it's a riskier bet for a developer given it's relative immaturity and adoption.
Saying all of that, Elm is pretty nice and I really enjoy using it for some of the same reasons I enjoy Elixir.
The language and ecosystem are an amalgamation of industry lessons from the past three decades on what it takes to build robust networked applications. It's the most painless programming experience I've had.
These days other languages feel like museum pieces when I have to jump back into them.
Not to mention being able to run dozens of services, background jobs, and API in a single box as one "umbrella application"!
(Well... not quite competitor. A similar product to ours, but which deals with the management of electricity.)
So yeah, there's quite a few startup using Elixir already :) and a handful established companies as well. -- Pinterest, for example: http://venturebeat.com/2015/12/18/pinterest-elixir/ :
> The notification system runs across 15 servers, whereas the old system, written in Java, ran on 30. The new code is about one-tenth of the size of the old code.
I'm curious to know how the author will recruit developers, specially in France. My last company migrated all its backend in Node this year, ONLY because it was the easiest option to recruit full-stack developers. The market is completely saturated here (there are a lot more offers than developpers), you spend months to recruit a front-end developer or a full-stack developer with front-end knowledge, and I don't see how you can attract someone with Elm. Having 1 or 2 years of xp in Elm on a resume is not really usefull when all the companies use JavaScript. You don't even know if Elm will still be there in 2 years.
Question: Did the app receive millions of visitors or was it basically 1 visitor with millions of viewers via the television showing a recorded screen?
At first I thought Phoenix was used because of scaling reasons but now I'm not so sure.
Either way, nice work and thanks for the write up!
I know HN gets a lot of hype for X new tech every month, but I'm really liking Phoenix. Ignore the "Phoenix is the future/saved our lives/best thing ever!!" Medium posts and try it out. It's actually pretty good.
People who started after Rails was released don't see it because they haven't seen how it was done before. But it's incredible how many conventions DHH created with rails that have since entered the basic repertoire of all web frameworks: migrations, its take on MVC, :belongs_to, the router DSL, the asset pipeline, generators – while you can probably find prior art for all of them somewhere, it's the implementation in Rails that, 10 years later, is still the blueprint for new frameworks.
Rails was also the best teaching tool ever invented in the space. Code quality was atrocious, people were reinventing "clever" solutions for every project, testing was probably rare (I never saw it, but it must have been around, right?) I distinctly remember a templating system that turn .xls into a perl script that would write php. If you changed projects, you'd usually be greeted by a directory tree 8 levels deep with the main config.php in /[..]/tmp-2008_b, along with config.inc, main.html.php.old and construction.gif~2.
(Not that Phoenix doesn't add lots of refinements that make it a pleasure to use)
Chiming in with Elixir+Clojurescript. It's what I've been using for most of my projects these days and absolutely love it. Pure functional programming on both, server and client, with the server concentrating on well distributed concurrency and parallel processing with GenServers and the client on immutable front-end code while using Go-blocks for async stuff.
Sorry Vincent, you lost me there. Elm is interesting for sure, but it's far from having a low entry barrier. Something has basic has having a button play a sound takes forever to figure out. You almost have to learn everything all over again. It's a cool project and I'm glad it's working out well for you, but Elm has a serious learning curve.
Paradigm wise: Yes functional programming can seem strange and hard if you haven't done it before. But that really isn't the fault of Elm, elm makes FP as simple as it can.
Language wise: Yes, the Elm architecture takes a bit to grok, but for me it was just an afternoon. Once you grok it, there isn't really much else you need to learn - you can hit the ground running, look up what you need when you need it.
Tooling wise: Just some basic tooling you get will get you very far, no setup either, just install and use.
If you do js interop, yes that can be cumbersome, but it is intentional. Elm strives to keep js out and write libraries in Elm. This is so we can have more of the guarantees that Elm provides. (no runtime exceptions!)
I'd rather say: "Elm has a low entry barrier for a FP language". One of it's main goal is to bring FP to the masses after all. :)
(I'm a functional programmer, so yay for them!)
I would like to see the results of the two other guests.
At work I don't see it happening though, we're a PHP shop now addind nodejs (to my despair) and maybe some Go. I think there is a Haskell fan and that's it.