Phoenix – Elixir Web Framework
github.com
github.com
The reason though is that Elixir 1.0.2 includes some bug fixes that affects Phoenix in development.
(I say this as a fan, btw! I just think that it's important to get the pros and cons out there. I also think that a lot of Ruby/Rails folks are VERY curious about Elixir generally and Phoenix specifically, lately...)
Pro - Concurrency: I really love Ruby/Rails, but what led me to Elixir in the first place was constantly dealing with lack of concurrency in Rails and being unable to do anything like websockets in a sane way. For example, in Rails we can't really block in the controller without killing throughput, so we go to great lengths to background everything. This makes simple problems like "Make a remote API request through a controller" way harder since we now have to throw it in a worker queue, then poll from the client on the status of the job, then finally return the result. In Elixir/Phoenix, we can block in controllers without a blip on throughput, do our work, and return the response.
Pro - Error Handling / Fault tolerance I won't go into too much details here, but the Erlang/OTP way of building applications around Supervisors and responding to failures has really blown me away. Erlangers have been sitting on this innovation for the last couple decades so it's battle tested and has proven its merits. Look at WhatsApp, 1-2 million connections per server, 400 million users ~ 30 engineers.
Pro - "Realtime" / pubsub: Phoenix also ships with a realtime layer that we call "Channels" for doing pubsub/realtime events to clients. Our goal is to make building realtime applications as straight forward as building REST endpoints. We include a `phoenix.js` browser client, but we are targeting multiplatorm support and have a working Swift client internally. So Phoenix aims to go beyond a typical "Web Framework". The Web is more than just html apps (but Phoenix excels as just that). Imagine a iOS game publishing on Phoenix channels to other iOS clients, and a Web front-end reporting world events, player lists, etc. Phoenix can power all of it. By virtue of the Erlang VM, we also get cluster support For Free. You can run multiple phoenix nodes on a cluster and PubSub Just Works. No need for redis in b/w or worrying about sticky sessions. Concurrency in Elixir is location transparent. A process is a process regardless of machine it runs on in a cluster.
Cons - Packages, Training: My goals are to wholesale replace all my Rails work with Phoenix, but obviously we have a ways to go. The main cons are lack of off-the-shelf community packages like in Rails land. We are also not yet at 1.0, so you have to be willing to put up with breaking changes until we're ready to brand a 1.0 release next year. I'm using it for prod systems, but this is an upfront reality as we march towards 1.0. Other cons would be having to train folks new to Elixir, which often means learning a number of new paradigms at the same time. There's a helpful Elixir community for newcomers, but it will take more upfront work to get up to speed if you're coming from an OO background.
Hope that helps. Ruby folks might find my RailsConf Elixir workshop helpful as a place to get started in Elixir: http://www.confreaks.com/videos/3488-railsconf-workshop-all-...
freenode #elixir-lang irc is also a great resource for questions.
I created a distributed PubSub for the Scala/Akka/Play toolchain a while ago so just wondering how it compares: https://github.com/alexanderjarvis/dubsub
Is some form of hypermedia supported or built in? If not, is it planned?
These may be answered in the presentation. I hope to watch it soon.
Secondly, I hope that the original dev team sticks around too. The Erlang web framework - ChicagoBoss - has had its development slowed down ever since Evan Miller stepped down.
I worked with the new Node.js framework called Koa.js. It has an interesting way of dealing with middlewares (would be Plug in Elixir world, I assume). Request and response are passed through the middleware chain downstream, and each of them can take the response from previous middleware(s), modify it if needed, and pass to the next.
Either the response reaches the last middleware, or one of middlewares returns immediately, the response goes back "upstream" through the middlewares again. Then it is replied to the client.
During the flow, each middleware can also yield to the next one, so that it can handle the updated response when it goes upstream.
Imagine the cache middleware. Request comes in, this middleware checks if there is a cache of that request. If not, it yields to the next middlewares that will retrieve and transform the data, then cache the response body before returning to client.
For me, this flow offers a lot of flexibility in request and response handling. Is there anything similar to Phoenix?
From what I understand, once a Plug chooses to reply, the response ends at that Plug.
> From what I understand, once a Plug chooses to reply, the response ends at that Plug.
In Phoenix, we halt the connection when you use most of our functions that send a response, because there is little you can do afterwards. The Plug response API itself never halts when a response is sent.
Like Scala being on the JVM.
Web Framework is just that a web framework.
From what the creator have commented on, it seems like it will be influenced by Ruby on Rails framework.
Now, I know Erlang much better than Elixir, and I worked with Cowboy before and I needed to make this app quickly, which resulted in me not spending too much time on learning Phoenix. Between controllers, routes, views and channels I got an impression that Phoenix has too many moving parts and that it would take me too much time to fully understand what's going on. Especially because I really didn't need most of these, just a static file server and a single WebSocket.
However, I see Phoenix potential for more complex projects, where investing the time to learn it is going to be worth it. It looks like Phoenix provides an awful lot of conveniences and makes a project much better structured than my "a couple of files in a single directory" approach.
I guess what I want to say is that I almost used Phoenix this time and that I would probably use it if it had better docs - especially a solid tutorial(s) for use cases similar to mine. And that, while I didn't use it this time around, I'm certainly going to keep an eye on it and consider it next time I have to write something similar. It looks very promising and - like Elixir itself - very interesting, I hope for it to only grow in the future :)
I am also coordinating the Phoenix Guides project which, while still incomplete, is adding information all the time. https://github.com/lancehalvorsen/phoenix-guides
Sorry these didn't help for your last project, but maybe they'll help for your next one. :)
I don't think there's a plug for websockets out of the box, but it's not hard to hook them on Cowboy directly.
That said, I would love some websockets stuff refactored out of Phoenix into a Plug so that it can be used even without Phoenix. I'm not sure about the amount of work that would require.
I used to dislike Rails, since it seemed to be too much abstraction that would require time to learn. I now have the same feeling about Phoenix. I could put up a simple web app quickly with Erlang and Cowboy. With Phoenix, I needed to read documents and the source code to figure out what all the imports are doing.
Because if the latter, it feels like a web framework isn't for you. But you should definitely consider Plug (http://github.com/elixir-lang/plug), which has all the pieces and you just need to put them together (a simple router, a bunch of "middleware", etc).
As someone with a Phoenix app running in production, I can tell you that this framework hits the sweet spot of providing lots of value without requiring the user to learn too much. The abstractions it provides, especially the router and rendering layers, are very welcome. And I'm saying this from the perspective of someone who has built a few smaller vanilla plug applications.
Let's not throw the baby out with the bath water here just because rails went a little too far with the magic.
Definitely would recommend trying it out if you haven't. It was a breath of fresh air from where I was in node.js/python land.
Also, how's your test suite? :)
I guess compared to django (and rails..), it's absolutely a smaller framework, so it's easier to reason about what's going on, and when you don't understand the source is much easier to follow. Diving into the django source to figure out a problem was a nightmare.
In terms of actually using it, the biggest strength is the concurrency model.
It handles blocking much better than rails or django where you typically have a fixed number of workers, and if you block and fill up those workers then you're SOL. Yea there are workarounds here, but they're pretty ugly. python and ruby don't really have nice solutions for this, which brings us to node. In node, you always need to be actively thinking about handling async IO with callbacks or promises or whatever, and you can quickly end up in callback hell if you aren't careful.
In elixir (and erlang), BEAM handles all that hard stuff. The result is your code is easier to write and read. Every phoenix http request is in its own elixir process. There's no weird request context like you get in flask, no way to abuse request state, and no callbacks to deal with. You can block a process all you want and throughput will be the same. The code looks like it executes sequentially, even though it doesn't.
For a small app like the one I wrote, it also has the advantage of being able to start a bunch of little services in the background to handle longer running tasks (which would typically be handled by a message queue with django/rails) and they're super easy to deal with since it's just standard elixir process messaging. These services handle things like performance logging, emailing, as well as (in the case of my app) looking for vulnerability disclosures and resolving them to package specs.
Anyway, sorry for the rambling response, but I hope it gives a general overview of why elixir and phoenix made building something way more pleasant than what I'm used to.
Why do you ask about the test suite? Did you find a bug? :)
No, but there may be one already, lying hidden, unless you have a good test suite haha
If you have time and want to see a very well run open source project in action, I recommend you read through present and past discussions on the Phoenix GitHub project: https://github.com/phoenixframework/phoenix/issues
Enum.map [1, 2, 3], fn(x) -> x * 2 end
or: receive do
{:hello, msg} -> msg
{:world, msg} -> "won't match"
end
The "do" syntax is in fact syntactic sugar for keyword arguments, which is suprising and a little disappointing, especially when you realize that constructs like "if", "case" and "receive" are in fact implemented as functions. Sacrificing syntactic elegance for consistency ("everything is a function") might be clever, but is it an improvement over hard-wiring this stuff into the language as first-class keywords? I personally don't think so.It's a minor point, and not major enough to make me not use Elixir, but when someone goes this far in putting a nicer skin around Erlang, it's disappointing to find newly-invented blemishes that are as weird as the ones it aimed to smooth over in the first place.
As a newbie coming into Elixir without either Ruby or Erlang background, I didn't find anything in the syntax to be a real pain point (although understanding optional parenthesis usage in CoffeeScript did help).
I have mentioned before this is often the most unrewarding aspect of designing a language because, it doesn't matter what you do, you will always get an opposing opinion. Here are some examples of what I have heard or read multiple times throughout the years:
* Using the brace syntax is seen as catering to common languages (like C and Java) which would arguably cause a lot of confusion when added on top of a functional language
* Going with Lisp is always a matter of love or hate. Some people will love it and some people is going to really hate it
* The same with space-based indentation. A lot of people praise its conciseness, a lot of people curse the code being extremely hard to move around (this was honestly my second choice but it would get complex inside quoted expressions)
* The do-end blocks gets some praise for being readable (less punctuation characters) but also a bad rap for being verbose
To be clear, I am not calling you out, the point is exactly that everyone will have their preferences and if I was not writing this comment to you, I'd definitely be writing it to someone else. :)
However, it's quite obvious that you are hugely influenced by Ruby's syntax. What I don't understand is why, in copying Ruby's overall flavour of syntax, you decided to make it a little worse.
My hypothesis is that you discovered that this syntax allowed an elegant, unifying structure to the internal implementation, which is fine — but as a user, it comes across as an annoying wart. The parser should know perfectly well that after "def" comes a function name, so why does it need the "do" to demarcate the function body? It would have been just as ugly in Ruby, which goes for terseness in the common case (eg., "if" can take a "then").
Criticisms aside, I should add that this is the only thing so far that has annoyed me about Elixir.
Elixir's do/end blocks actually enhance the syntax it inherits from Ruby by making it very, very consistent. Defining any type of entity takes a do/end block - def, defmodule, defmacro, defprotocol, defimpl, and probably some that I have forgotten.
Your hypothesis is almost right. The important bit is that it is not about an internal structure, it is about a public structure that is accessible to macros. It is about the language AST.
Before there was syntax, I had defined I would like to have Lisp-style macros in Elixir. For that we need to have a regular syntax because when you are composing AST nodes you don't see keywords.
As an example, imagine you have code generation where you may generate a function called `add` and we treat `def` as a keyword. You would do something like:
quote do
def add(x, y)
x + y
end
end
Now let's say the function may be public or private. You would try to write it like this: kind = :def # or :defp
quote do
unquote(kind)(add(x, y))
x + y
end
end
And now the parser would be unable to parse the code above because there is no longer a `def` or `defp` keywords where the parser would know it could skip the `do` bit. Therefore having an uniform syntax means you can generate and transform code without worrying about special cases, without evaluating strings and without resorting to special functions/methods for dynamic code definition. You can just compose code!I also believe this matters a lot to the end-user, positively, for two reasons.
1. Consistency. The language is consistent and you can extend it in a consistent fashion. For example, Elixir code is written inside modules. `defmodule` is not a keyword, it is an identifier as any other in the language:
defmodule MyModule do
end
We also have defprotocol, which is implemented as a macro, and looks exactly the same: defprotocol MyProtocol do
end
If we made defmodule a keyword, we would put ourselves into a corner as we would either have to make defprotocol a keyword too (for consistency) or have defmodule and defprotocol looking slightly different (causing confusion).2. The second reason is that enabling such AST macros allows us to extend the language in different and interesting ways you can't do cleanly with other languages. One example I like to give in talks is the assert macro in our ExUnit test framework:
assert foo == bar
Different to many unit test frameworks, we don't need `assert_equal`, `assert_more_than` and friends. As a macro, `assert` navigates the AST, which is quite uniform, and extract information from the code.Another example I gave at my talk at ElixirConf is that we could even extend language constructs like our for comprehensions. Someone can implement a `parallel` macro that transforms a regular for comprehension into one that runs in multiple Elixir processes (leveraging multicore):
parallel for user <- users do
fetch_user_data(user)
end
This only works if parallel can look at the code and transform it in multiple ways.TLDR: The unifying syntax is an important part of Elixir macro system which brings consistency and provides an extensible foundation to the language that can be leveraged by its users.
I'm really interested to see where Elixir is going, and to try building something real with it. I'll probably use Phoenix, just because it's the most active, mature framework. (I like the look of Dynamo - https://github.com/dynamo/dynamo - but not sure how active it is.)
> Dynamo is currently in maintenance mode for those who are already using it in production. Developers who seek for an actively developed framework are recommended to look for other alternatives in Elixir.
It is possible to write an Ecto adapter for Riak, with some workarounds. I tried it once, but the motivation to continue...
Rather than try to give examples, take a look at their Github page: https://github.com/elixir-lang/ecto
I think most frameworks should follow that model: provide a flexible ACL system but let the developer figure out auth.
I actually think the model it's better suited to a functional language. I'm working on a similar extension to the Haskell snap framework.
Many people dislike python whitespace though but I think brackets are still better than end.