On Static Frameworks

There's been a lot of great and thoughtful discussion on Swift and Cocoa recently, as well as some angst and worry (some of it from me).

It really does need to be said this isn't an anti-Swift argument for me; Swift is a truly great language and we need to credit the Apple engineering team for their past and current work and trust they will continue to do excellent work in the future, as admonished by none other than Wil Shipley. His opinion carries weight.

I thought it might be useful to talk about some concrete examples of how a language and a static or a dynamic mindset can effect a framework.

Two Takes on a Web Framework

I have experience with both ASP.NET from it's humble beginnings using the PageController though various flavors of MVC, a project inspired by Ruby on Rails, and Rails itself.

It's instructive, I think, to compare the effect the mindset of the framework authors has on the design of the frameworks. Let's start with Rails.

Routing in Rails

I'm cherry picking here, but let's examine how RESTful routing is done with Rails. We start with a resource – we'll use "photos" from the Rails Guide. We would like to map a set of HTTP verbs and URLs to a controller that can handle these routes. It begins with a definition in a routes file:

resources :photos

What's happening here? There's a lot of convention at work, but we're saying that a thing named photos is being described as understanding seven different routes, one for listing or searching a set (GET /photos), one for getting a specific item (GET /photos/:id), one for creating a item (POST /photos), and so on.

The framework is then expecting there will be a class called PhotosController that has certain methods called index, show, create, and so on that take specific parameters and know how to retrieve, create, and return photos. That class will look pretty simple, too, something like this:

class PhotosController < ApplicationController
  def index
    @photos = Photo.all 
  end

  def show
  end

  def create
    # ... more app stuff
  end

  # ... more methods, but you get the idea
end

It may respond with HTML, JSON, XML or any number of other payloads. There are helper methods that can build routes and all sorts of goodies.

This is just scratching the surface, but the point is the framework is leveraging language features like symbols and mixins and dynamic dispatch to build up a framework that makes creating a web app that can do everyday things elegantly and simply.

Whether you love or hate Rails, agree with the "magical" conventions or not, I think it clearly demonstrates how someone who thinks in Ruby approaches a problem like this.

Routing in ASP.NET MVC

The ASP.NET team has been evolving the framework steadily and there have been various ways of accomplishing routing, so I'm going to just pick one that's fairly recent. My example isn't definitive any more more than my Rails example is, but I do believe it is representative and fair.

Now, the ASP.NET team could have taken the Rails approach and implemented it more or less identically. The facilities exist within the language using reflection to do exactly the same thing. After all, ASP.NET MVC was inspired by Rails. They did not, though; they approached it with a static language mindset and in the spirit of the larger .NET framework.

I'm not suggesting that's wrong. They should implement their framework in the style and accent that's natural for them. What I want to point out is how differently a static view of the world can be.

First, because this example is using attributes to decorate the classes and methods, we can let the framework discover them:

RouteTable.Routes.MapMvcAttributeRoutes();

There's nothing implied here at all, other than go inspect all the controller classes and build up a route map from their attributes. You could instead do this manually, but in that case we're not.

Now we can create a controller.

namespace PhotosApp.Controllers
{
    [RoutePrefix("Photos")]
    [Route("{action}/{id:int}", Name = "PhotosRoute")]
    public class PhotosController : Controller
    {
        [Route(Name = "GetAllPhotosView")]
        [Route("Index")]
        public async Task<ActionResult> Index()
        {
            return View(await db.Photos.ToListAsync());
        }

        public async Task<ActionResult> Details(int id)
        {
            // ... app code
        }

        [Route("Create")]
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Create([Bind(Include = "Id,Name")] Photo photo)
        {
            // ... more app code
        }

        // ... more app code here, too

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}

Notice we're being specific with the controller and its methods about what URL paths to respond to, why kind of verb, even how to inflate another class with data. There are some funky looking return types that are unique to this framework, but at various points in the code you'll need to think about your model types and how they are projected into and out of various representations not shown here. There are other ways of doing this, as well. This is just one way.

Is this bad? No, it's actually an improvement over previous versions that required a lot more boilerplate. But it's still kind of fussy to my eye. A lot more ornamentation, things needing to be specified and peppered around in different places, things you need to bounce to different places not shown to understand; just general brittleness and heaviness. And this is the version with some "magic" sprinkled in.

OK, So You Like Ruby More Than C# ... So What?

Yeah, that's true. I don't deny that. I also like Objective-C more than C#. Yes, I'm weird. I also like vanilla more than chocolate. My tastes aren't yours.

Personally, I love the kinds of frameworks that come from languages like Ruby. The are, to my eye, beautiful and the apps people build with them are better.

With Swift, we could design frameworks that aren't much different from the way Cocoa is now (and I'm not hung up on target/action). But, we probably won't. We'll have new minds that approach it from a Swift inspired, static viewpoint.

We could end up with things that look like ASP.NET MVC. Some folks would love that and I can't fault them. ASP.NET MVC is a perfectly rational and reasonable web framework.

Personally, I'd rather we get things more like Rails, though. I'm not sure what a beautiful, elegant, static framework would look like because, frankly, I haven't really seen one yet.

But, if anyone can do it, I bet Apple can. Fingers crossed ...

EDIT: Well, I may have found an example of what an elegant, static web framework might look like over at Vapor.

Home