Sunday, April 28, 2013

Controllers ... again

I realized there was a problem with the controllers the other day, and I've been trying to figure out a way of fixing it. Technically, I have two very similar problems.

First is that users would probably like to be able to control which methods in a module are actions. Currently, if a function exists in a module, then it gets applied to the request and run. I could use the private / public status to control which methods are visible, but it's not terribly elegant.

The other problem is that there's no way to restrict HTTP verbs for an action. Currently only GET is implemented anyway, but that's ratcheting ever higher on my list of things to fix. Once that happens, I'll have to figure out some way of being able to restrict an action to a specific verb.

Interesting side question: does it make any sense to be able to set multiple verbs on an action? I suppose that makes sense from a REST type perspective - you'd one to decide what action to take based on what verb was passed in. Okay, so...  multiple verbs.

There are quite a few different ways to approach this. First, you could just add a constant to the module that contains a list of actions. The framework would only call functions that are in that list.

That is what's known as "ugly as hell".

Plan B: define a DSL like Sinatra does:

module MyApp
  module MyController
    actionize!

    get 'foo' do
      # controller action
    end
  end
end

The actionize! call is there for a very specific reason. Since we don't have a base class to derive from, we have to hack our way in from Ruby's Module class. Adding 'get' and 'post' functions to every module would be a bad and possibly hazardous thing to do, so we add a single unique method that adds the required functions to this specific module instance.

So that works, it looks pretty clean, and it has the added benefit of being a pattern that many people use and like. (i.e. Sinatra)  It's also extensible, in that we can add options after the action name, the same way that Sinatra does. It also handles multiple verbs on an action cleanly, since you're not actually defining a function per say.

The downside is that you have to understand the paradigm in order to build a controller. It's built around the language.

Plan C - The last way I thought do to it was more annotations-based:

module MyApp
  module MyController
    actionize!

    action :verb => POST
    def foo
      # controller action
    end
  end
end

What I like about this plan is that it's using generic Ruby methods. We could default the verb to GET and much of the boilerplate goes away. The options we could pass in for plan B could also be passed in here. We could do interesting things like look at the function parameters and pull those parameters out of the params hash - syntactic sugar, but nice to have. It seems like some fun things could be done here to make these actions easier to work with.

One downside is that since it's a ruby method we can't really overload it. We could pass an array of verbs in to the action, but now we'd have to put a big ugly switch inside the function to handle each verb. It's also an extra line that is not grammatically attached to the function definition - it could get lost or deleted and the code would still parse.

I think the Sinatra DSL plan is probably the best plan. It's simpler and easier to see what is being built. I'll keep thinking on it, but that is probably the route I'll end up taking.

Tuesday, April 23, 2013

Controller verbs

Messing with the framework today, I remembered that controller actions currently only respond to GET. Which is not a terribly complex problem to solve from a framework perspective - I can simply add a Sinatra handler for the other verbs that routes to the controller actions the same way that GET does.

The question is, should I?

If I do this, then all controller actions will respond to all HTTP verbs. Which is not the typical way of working with one of these frameworks. Rails routing makes each routing action very specific to a given verb. In MVC.net you annotate the controller methods with the particular verb.

We're really talking about a filter here. What I don't want is the framework user to have to build in boilerplate code for each controller that filters out verbs that they don't want to deal with for a given method.

There's probably some nifty Ruby language feature I could use to filter these methods. But that would be adding configuration, I think. Also, the ways I can think of do build this filter would be a little bit fragile.

What I'm actually thinking about is building the filter into the name. If the action function starts with "get_", then it's a get method. If it starts with "post_" then it's a post method. If it doesn't start with a verb, then it would handle any verb. The url for the action would not include the verb, of course.

Interestingly, that would actually allow overloads of a given action - you could easily have a put version and a get version, which would normally not be allowed in Ruby.

The only real downside I can think of is that now you could not have an action that began with a verb. There's probably a way around it (explicit routing would be one option) but I have trouble thinking of a reason why you'd need to start an action with a verb.

I think I like this plan.

I also need to remember ... the thing that I forgot. crap.

Thursday, April 18, 2013

Github tasks

I've been quite distracted over the last week, and haven't really gotten anything done since Saturday.

But today I put all the outstanding issues I could think of into the github repo. Even checked off a couple easy ones. I've got two milestones - a basic "get the key features working" and the bigger "kick out a 1.0 release".

The next tasks to knock out are documentation and some examples. Right now, anyone looking at the gem is going to be very confused unless they go to all the trouble of reading the code. If there's documentation than maybe a few people will start using the gem and find me MORE features to implement.

Monday, April 15, 2013

It lives!

Kul v0.0.1 is up on rubygems.

The damned thing actually works. Probably less than a hundred hours of development time, and I've developed a fairly full-featured web application server.

The biggest feature missing at this point is any sort of authentication. There's probably a rack middleware for that though. Yup - omniauth. In order to get that working a person would have to hack into the router pretty deeply though. Something to work on for the future though.

I've tested the gem on both Win7 / JRuby and on Ubuntu / MRI. It worked in both places, although I did have to install nodejs on the linux box in order to provide the javascript runtime for coffee compilation.

I also noticed that the default website points back at the rubygems site, which is something I hate whenever I hit a gem page. It's been changed to github, although I'm not bothering to update the gem since nobody's using the thing.

Need to add a history file now.

I'm giddy now. My app server works.

Sunday, April 14, 2013

Kul controller design

Controllers are a love/hate relationship for me. They're a great place to put code that brings the models to the views. They're also great for figuring out what to do with a given request. All of those things could probably be done implicitly, but the rules would be hard to understand, I think. Or would break the code up into many small distributed chunks which would be painful to read / follow / debug.

I hate controllers because they don't make sense. What is the life cycle of a controller object? In most frameworks, it's the lifetime of the request. It exists only so that you can do dynamic dispatch from the request parameters. You could put initialization code in the controller, but in most frameworks, the controller constructor can't take parameters, so you're limited on what initialization you can do. So most of the time the controller exists only to hold similar functions together, and is really a stateless object. Stateless objects seem like a bad design choice to me. (Stateless does not equal immutable. Immutable objects are good design - particularly in threaded environments.)

Saturday, April 13, 2013

Surprising things in Ruby #1

Try this in your irb:
irb(main):001:0> def foo
irb(main):002:1>   'hello world'
irb(main):003:1>   end
=> nil
irb(main):004:0> 'a'.foo
=> "hello world"
If you're not used to Ruby, this may seem surprising. This may help make it clearer:

Thursday, April 11, 2013

Rich internet applications

Looking at a webSockets implementation this evening, I was hit with the light.

The app we're building at work is not really an HTML page. That is the underlying transport layer, but really what we have is a javascript application that has its UI written in HTML. There is a single page, and different parts of it are loaded and unloaded in response to a user's actions. When the application needs data, it AJAXes back to the server for some JSON, and occasionally an HTML template or some new script.

This paradigm corresponds with a number of MVVM frameworks that are very popular these days, such as Backbone, Knockout, or Ember. Your web layer is really a javascript application running in the browser, and the app server just feeds it the data it needs to run.

What bothered me is that I felt that was unwieldy. Most of the really good app layer frameworks are MVC. You put an MVC framework on the app server with an MVVM framework in the client and you have way too many layers. I've been working on Kul as kind of a way of making simpler MVC frameworks, but it still feels to me that adding MVVM on top would be more complexity than you need.

Then I thought about web sockets. If you think of hitting a website as the initial application download, then web sockets become the data connection for your application. You could open a web socket, keep it open for the life of the app, and have that be your data connection.

That's really what Google does with docs and gmail. It's no longer a webapp, it's a heavy client app with a continuous server connection and a HTML UI.

You could build your app on top of something like Ruby's EM-WebSocket, or maybe something simpler like SinatraWebsocket. The possibilities are endless, really. Instead of building huge rest interfaces for a web app that doesn't need it, build a client application! It's a horrible practice to re-use that structure for a rest client, anyway.

You can completely minimize your web app footprint, have better testing methodologies, and build a much less complex webapp this way. Instead of having AJAX calls scattered about your javascript (and you know they all work slightly differently) you streamline your server communication through one point. Data all gets requested through the same pipe.

I'm sure this is old hat for the rest of the world, but I thought it was amazing when I realized the benefits. This is the right way to do RIA.