Opening 10 Nov 2018, Taipei
Beat Streuli is a Swiss visual artist. (Summicron-M 50mm f/2, Leica M10)
Gray Area 26 Jul 2018, San Francisco
Naut Humon is the Founder and Artistic Director of Recombinant Media Labs. (Nokton 35mm f/1.2 II, Leica M10)
Creative Commons Global Summit 16 Apr 2018, Toronto
Reviving Democracy 15 Apr 2018, Toronto
Lawrence Lessig is the founder of Creative Commons and a professor at Harvard Law School. (Heliar 75mm f/1.8, Leica M10)
Object Lessons of History 29 Dec 2016, Hanoi
If the hardest thing in Computer Science is naming things, then a corollary rule is that misnaming things must be the easiest.
One of the more evocative similes in my field is Ted Neward’s notion that “Object/relational mapping is the Vietnam of Computer Science.” It’s an analogy for the mismatch between the representation of data in object systems (in terms of OOP languages) and relational systems (i.e., relational databases) and the hazards of translating between them.
The thrust of the metaphor is that the O/R-M problem, like the Vietnam War, is a quagmire that might have started as planned but quickly got bogged down in complications with no solution and no exit strategy in sight.
It’s rueful to think on this problem from Hanoi, where the real Vietnam War was experienced from the opposing side, and known by another name entirely, as Kháng chiến chống Mỹ, or the Resistance War Against America.
Neward later acknowledged that his analogy might seem strained and even offensive. I don’t wish to defend it, or dismiss it. Nevertheless, an analysis of his argument, like the War itself, would benefit from a similar shift in perspective.
Neward’s stance on the O/R-M problem takes an object-oriented approach for granted, rather than deconstructing it; much like his metaphor of the Vietnam War assumes its name and meaning in an American context.
It has been over a decade since The Vietnam of Computer Science was published. In that time the industry has had a chance to learn its own lessons from history, such as the advantages of message-passing, share-nothing, process-oriented architectures (like Erlang) which make better object systems than OOP does; and functional languages which manipulate lists and sets of data in a way that is aligned with the operators of relational algebra.
Neward proposes one solution to the O/R-M problem that he can’t accept in the end, to give up on objects entirely. Ironically, it is the same conclusion that the U.S. came to in its prosecution of the war effort in Vietnam: abandonment.
Phoenix is not your App. Is it even MVC? 26 Dec 2016, Hanoi
It turns out that Elixir’s popular MVC web framework doesn’t need Models, Views, or even Controllers.
I’ve never been an adherent of the MVC pattern in web applications, even though it has been a productive concept for full-featured server-side software. I might use Webmachine or an equivalent program in Erlang, Ruby, or Clojure; or I might not require an HTML template engine or a database wrapper. I often prefer building up a web app piece by piece, instead of committing up-front to an opinionated framework.
When working in Elixir, Plug suffices for the piecemeal approach. Nevertheless, it is tempting to use Phoenix Framework, which adds many features without sacrificing flexibility or performance.
Although I can generate a Phoenix project without Models, or else encapsulate them in a separate OTP application from my web app; and although I can avoid Views by sending responses directly using Plug; I didn’t think I could escape from Phoenix’s Controllers (without completely replacing the Router). Soon I would find a way.
Spelling W-E-B with M-V-C
Model–View–Controller (MVC) is a software design pattern that developed out of early (desktop) graphical user interfaces but was later adapted to describe web application frameworks, such as Ruby on Rails and, more recently, Phoenix.
For server-side web software, MVC denotes the components that manage data (Models), media representations (Views), and HTTP request/response behavior (Controllers). Nevertheless, the MVC pattern does not name its central component, the Router, which dispatches each request to the code that will handle the response.
Take a basic request line such as:
GET /some HTTP/1.1
In Phoenix, a GET
request for /some
resource is matched using a router
macro:
get "/some", SomeController, :index
This get
macro call is equivalent to:
match :get, "/some", SomeController, :index
Here, the arguments comprise an HTTP verb, a URL path, a Controller, and an action function. These four terms together determine a “route” in Phoenix. But do they have to?
The Controller Pattern
The match
macros in Phoenix Router are not limited to using a Phoenix
Controller.
Instead, the routes will accept any module that follows the Plug
specification.
match :get, "/plug", SomePlug, []
So, if a Phoenix route does not require a Controller, does that mean we can drop the last letter of MVC?
Not necessarily.
Because the role of the Router is often elided when we talk about Web MVC, it’s
easy to miss its significance.
The Controller part of MVC is not just a Controller
module that includes one
or more action functions.
Rather, it is a particular contract, enforced by the Router, for matching a
request with the code that will handle the response.
We have already seen this contract in the API for Phoenix’s match
macro:
# Generates a route match based on an arbitrary HTTP method
match(verb, path, plug, plug_opts, options \\ [])
I argue that the real Controller pattern in Web MVC matches a verb and path, and executes a module/function in the context of a request.
For most CRUD apps, the Controller pattern suffices. But it does not work for resource designs such as:
- An echo server that replies to all requests for a path (for any HTTP method)
- A REST-based framework where the HTTP methods supported by each resource are encoded in the connected Plug, and not the Router; e.g., PlugRest
Breaking the Pattern
I brought up method-agnostic Phoenix routes again in a closed issue on the GitHub project page. After some discussion, Chris McCord offered that Phoenix already supports this behavior by way of a catch-all verb:
match :*, "/any", SomePlug, []
The feature exists for use with the forward
macro, but had not been publicly
endorsed for use with match
.
Fortunately, it seems this feature may be documented in the next release of
Phoenix.
This finally allows us to drop the Controllers from our “MVC” web app.
Doing It Wrong?
I was curious about the initial reluctance to fully support a catch-all match
macro in Phoenix Router, and how it could be “abused” or “introduce bad
behaviors”.
I have a hunch it stems from a decision in Rails to deprecate “match”
without an explicit method (resolved in this commit).
Rails warns about the danger of unintentionally putting “state-changing” code
that manipulates resources on GET
-accessible routes.
The documentation advises that “You should not use the match
method in your router without specifying an HTTP method.”
Egor Homakov is even more blunt, writing:
You always know which HTTP Verb is used for specific “controller#action”! If you don’t - you are doing it wrong.
This assumes, of course, that we are using the Controller pattern. This may be a fair assumption for Rails, but it shouldn’t be for Phoenix.
It’s still possible to match all HTTP methods in a Rails route using an explicit
via: :all
option.
Fortunately, Phoenix offers us the same escape hatch.
Game, Set, Match
Phoenix’s flexibility and openness to multiple, co-existing patterns for structuring web applications is just one more thing to recommend the framework.
Phoenix is only MVC if you want it to be.
Linking each webpage to its code 02 Dec 2016, Taipei
I recently wrote about why I use static site generators. Approaching blogging as a coder inspired another feature that makes this site easier to use and share.
You may have noticed I include a [ source ] link at the bottom of every page. Since this is a static site hosted on a web-accessible Git repository, it is simple to link each page to its counterpart source file.
I’ll explain how I do this using Jekyll, but the same technique should work with any static site generator that can output the path of the current file relative to the root directory, and with any Git web host that preserves this path for viewing.
For example, the page.path
for the current file is _posts/2016-12-02-go-to-the-source.md
, and its
corresponding page on GitHub is here.
First, I add the repo URL to the config file. For GitHub, this takes the form:
# _config.yml
source_url: "https://github.com/USERNAME/REPO_NAME/blob/BRANCH/"
Then, in the layout, I build and render the source link:
<!-- _layouts/page.html -->
<a href="{{ page.path | prepend: site.source_url}}">
source
</a>
These source links are the very definition of free software, to let you use, study, change, and share this work. They also serve as shortcuts for the lazy or forgetful!
Calling All Plugs 28 Nov 2016, Taipei
Plug v1.3.0 has just been released. Read on for a couple of interesting new features.
Plug is a simple specification and powerful library for writing composable web modules in Elixir. While it underpins the popular Phoenix Framework, it also tends to get over-shadowed. And yet, Plug is very capable on its own, and has a couple of new features that are helping it to pull even.
Here is an example of a module that satisfies the Plug spec. It only needs to
export two functions: init/1
and call/2
.
defmodule HelloPlug do
import Plug.Conn
def init(opts) do
opts
end
def call(conn, _opts) do
send_resp(conn, 200, "hello")
end
end
Routers
The centerpiece of most web frameworks is the router. It provides the bridge between the framework’s code and the user’s by dispatching each request (identified by a URL path) to a designated resource implementation. In most Elixir web frameworks, the router provides an approachable DSL for defining the routing structure. Plug is no exception here.
Since version 1.0, Plug’s Router has had a DSL reminiscent of Sinatra. It defines a macro for each HTTP verb, which matches a URL path and executes a body of code operating on the connection.
defmodule MyApp.Router do
use Plug.Router
plug :match
plug :dispatch
get "/hello" do
send_resp(conn, 200, "world")
end
end
In contrast, Phoenix’s Router is more in the style of Ruby on Rails. It dispatches each request to an action function in a Controller module.
defmodule MyApp.Router do
use HelloPhoenix.Web, :router
get "/hello", HelloController, :show
end
Underneath, both Plug and Phoenix’s routers implement the Plug module specification. However, in the case of Phoenix, an extra bit of cleverness lurks behind its MVC facade: Controllers are Plugs! In fact, the router macros will accept any Plug module. We could, for example, change the route to:
get "/hello", HelloPlug, [an_option: :a_value]
Plug’s Router has been deprived of a feature like this, until now. Starting in v1.3.0, you can dispatch requests directly to a Plug module:
get "/hello", to: HelloPlug, init_opts: [an_option: :a_value]
This is equivalent to:
get "/hello" do
HelloPlug.call(conn, HelloPlug.init([an_option: :a_value]))
end
While a seemingly small change, this feature will make it both easier and more likely for us to build Controller-like patterns directly on top of Plug Router. With it you can factor out the code that handles each route into separate modules, rather than filling up your router with function bodies.
Path Params
Plug Router’s routes have always supported dynamic path segments, such as:
get "/hello/:name" do
send_resp(conn, 200, "hello #{name}")
end
The :name
parameter can be used directly as a variable in the function body
passed to the match macro. In order to make these values available generally in
the connection, Plug 1.3 has added a conn.path_params
map to hold them. They
will also be saved in conn.params
, a behavior which will be familiar to
Phoenix users.
The Plug Router docs have all the details.
P.S. The reason I decided to blog about these new Plug features is because I wrote them!
The spark of static site generators 25 Nov 2016, Taipei
What would happen if I approached blogging from a software development perspective?
—Tom Preston-Werner
The Dynamic, Static Web
I made the website where this post is published using Jekyll, a static site generator written by Tom Preston-Werner. Jekyll is probably the most commonly-used software in its class, since it drives GitHub Pages.
Although the very first website comprised plain hypertext documents, today much of the Web runs on dynamic software and data stores. This makes the recent renaissance of static websites look like little more than a novelty.
(This graph charts the Google search interest in “static site generator” since 2008.) source
There are very real, practical advantages to making websites static, specifically in terms of increased performance, security, and ease of deployment and maintenance.
For these reasons, static websites make eminent sense from a business or operations perspective. However, I do not believe this entirely explains the popularity of static site generators. The best justification, in my mind, is the one that announced Jekyll.
Blogging Like a Hacker
Tom Preston-Werner introduced his new static website generator in 2008, in a post titled Blogging Like a Hacker. At the time he wanted to improve his personal writing and publishing practice, but found that the contemporary blogging engines and services were too complicated or encumbered.
Instead of giving up or giving in, he figured out an approach to the activity of blogging as an author not just of prose but of code. To this end he created a tool that worked the way he did, namely:
- write with a text editor
- manage from the command line
- do not repeat yourself
- make things customizable and extensible
- store and distribute using version control
Finally: release it all and let others hack on it.
The upshot is to treat the blog as source code, using the same tools and techniques. I believe this is the real reason that static site generators have become and remain popular (if niche). They allow hackers to write the way they work best: with code.
Activists in Syria 10 Oct 2016
every so called activist in #Syria who was jailed for a month or two is now trying to make a hero of him self. I'm sick of that #Syria
— Bassel Safadi (@basselsafadi) January 31, 2012
Bassel sent this tweet just weeks before his own arrest. It would read like dramatic irony if not for the real tragedy that Syria has suffered.
Of course, Bassel’s arrest did not last months, but rather years. He was detained on March 15, 2012. Then one year ago he was taken from Adra Prison in Damascus and disappeared for good.
Bassel did not want to be a hero. But for us he became one.
the people who are in real danger never leave their countries. they are in danger for a reason and for that they don't leave #Syria
— Bassel Safadi (@basselsafadi) January 31, 2012
Our efforts to find and free Bassel continue at freebassel.org.
self source license