Collin Donnell

Freelance software developer from Portland Oregon.

In December of 1979 Tyrgve Reenskaug, an employee of Xerox PARC, published a paper called MODELS-VIEWS-CONTROLLERS about a design pattern he had invented for developing applications with a graphical user interface. The entire document was around 500 words long and described each component in it’s own section.

To summarize an already brief document, the components were described this way:

  • Models: The part of the application which represents the abstractions used for organizing the application’s data. Each part of the model should represent a part of the problem. Models notify views when their data has changed.
  • Views: A visual representation of a model. Views are updated by querying the model directly, and are notified by the model of updates. A view can update it’s model directly. A view should never know about things like keyboard and mouse events directly.
  • Controllers: Link between the user and the system. Arranges views on the screen, receives input from the user, passes messages on to views, and updates the model.

He also mentions a special kind of controller called an “editor” which you might be less familiar with:

  • Editors: A kind of controller which is temporarily inserted between the controller and a view for editing. If you imagine a contacts app, an editor might be created when the user hits edit, and then be discarded when they save or cancel, updating the model as needed.

When you put it all together, you get this kind of beautifully circular system:

MVC diagram

This makes a lot of sense to me, and I think I understand it pretty well. The thing, however, is that the MVC I’ve experienced writing macOS, iOS, and web apps doesn’t really match that description.

Apple-Style MVC

When I first started learning to write apps for Apple platforms around 2007, the way I learned model-view-controller looked like this:

In this version, models and views got dumber and controllers handle a lot more. The way I was taught was:

  • Models are dumb data containers.
  • Views display data and pass user actions to the controller.
  • Controllers manage the model, update views, get notified of user actions, update the model, and then also update views as needed when the model changes.

This is still sort-of recognizably MVC, but it’s most accurately described as a variation. The idea with this style is to decouple views and controllers. In Smalltalk-80, views had a reference to their controller and models notified views directly when their data changed. In Apple-style MVC, more responsibilities are pushed onto the controller, which decouples views, but also means controllers get larger.

The way it often tended to work was that the controller would set individual properties on a view (personView.nameLabel.text = person.name) which would then pass changes to a delegate (a helper object that conformed to a specific protocol), which didn't have to be, but was usually the controller. The controller would then update model.

It could also go the other way, where the model changes, and the controller updates the view. For example, in an app which spoke to a web API, the controller would start the API request, get the results, update the model, and then update the view. There could also be another class in there so your networking code wasn’t in the controller, but everything would still usually go through the controller.

Okay, so Apple-style MVC is still MVC, but kind of a different dialect with some different tradeoffs. Some things are less coupled, but controllers tend to get bloated. Cool.

Java, Model-2, and Ruby on Rails

In the late 1990s, Java developers writing for the web created a new variation of MVC to deal with the fact that web and desktop apps are different. It was called Model-2.

In Model-2, the cycle looks like this:

  1. There is a new HTTP request.
  2. The request is routed to a controller action.
  3. The controller renders an appropriate view.

In 2004, a Danish man released a new open source framework based on the Ruby programming language called Ruby on Rails which began the modern web as we know it. Rails used a Model-2 style architecture, but is generally just referred to as an MVC framework.

The difference here is that things tend to go through a request/response cycle and that they are optimized for CRUD applications. In this style, models tend to have a corresponding controller (User goes with UsersController), and each controller method maps to a “view”, which maps to the URL being requested.

It might look like this:

class UserController < ApplicationController
  def index
    @users = User.all
  end
	
  def show
    @user = User.find(params[:id])
  end
end

This is pretty different than either MVC or Apple-style MVC, but in a way that makes sense for the web. The components don't have references to each other, because nothing is alive. Each object is only around long enough for the page to be rendered, and then not again until another request happens.

If you squint you can still see it, though. Here's the chain of events:

  1. A GET request is made to /users/new.
  2. The request gets routed to the new method on UsersController, renders a page with a user creation form.
  3. The form is submitted, sending a POST request which gets routed to the create method of UsersController.
  4. UsersController creates the user using the request data and redirects /users/<user_id>.
  5. The request is routed back to the controller which gets the user from the database and renders the page.

Instead of the components having references or a delegate where different objects stay alive and talk to each other, each of those messages is mapped to an HTTP request. It’s still MVC, kind of, but if you think about it, it’s pretty different. It's taking something that was designed around stateful objects and adapting it to a stateless environment. It’s more like Apple-style MVC in that everything goes through the controller, but in this case it had to since things only get triggered when there’s a new request.

So again, recognizably in the same family, but still a variation of the original idea.

So what?

So what, indeed? Does any of this matter? I mean, not really. On the one hand, the two different styles I looked at are both pretty different versions from what was described in 1979, but, at the same time, how could they not be? 1979 was forty-three years ago.

There are aspects of the original design that could be applied and might be useful — models notifying views of updates while remaining decoupled using observable objects with SwiftUI in Swift or something like Turbo Stream broadcasts for Rails style web frameworks — but what is interesting to me is how an idea that could be described in a page and a half the year after Star Wars came out has managed to evolve and remain relevant in such different environments.

It’s a testament to how strong the original idea was, but also to the people who could adapt it to their needs while keeping it basically recognizable.

There’s a concept in urbanism and sustainability that I recently learned about from the CityNerd YouTube channel called the green transportation hierarchy, which looks like this:

Green transportation hierarchy

The idea is that things lower on the pyramid should defer to the things above them and that our environments should be designed to make more sustainable forms of transportation easier than less. It’s the difference between a pedestrian hostile strode and the kind of environment you might see in a place like Barcelona.

To me, this idea makes sense in a couple of ways. If you want people to make sustainable choices that make cities more livable, you need to make those choices more convenient than the alternatives. If getting across town on a bus takes ninety minutes and driving takes ten, it’s not hard to understand why people choose to drive.

So what’s the personal part of this? The thing is, between 2009 and 2017, I didn’t own a car at all. During that time, I moved from Portland, where it was kind of annoying but doable, to San Francisco, where having a car seemed like a burden more than anything else, to Seattle. I could have continued in Seattle, but it would have been more difficult than in other places I’d lived, and so I got a car a few months after moving there. I still took the train when it was more convenient but less than before.

The next place I lived was Silicon Valley, specifically Cupertino and Campbell. I’d walk or ride my bike when it made sense, but that area was not designed to get around without a car. At this point, I was driving more than anything else. After the pandemic started, riding a bus or on a train became something I wouldn’t do.

Since then, I’ve come back to Portland, and the options to get around without a car are better again. Portland has a pretty good bike share program, an above average light rail system, and an okay bus network. Plus, my neighborhood is pretty walkable, with a 73 walk score. I’m lucky to live in a place with all these things available and accessible to me, but after getting used to driving as a default, I haven’t used them as much as the last time I lived here (without a car).

Here’s my plan. If where I’m going can be walked to in under 20 minutes or so, I’m going to do that. I’ll bike if it’s further or I’m in a hurry. If it’s further than I’d like to cycle to, I’ll take the bus. Portland still has a lot of sprawl, so cutting out driving 100% would be hard. The goal is to reserve driving for when I need to get something I couldn’t otherwise take back or when taking public transit would take a lot longer than I have. I really want to break the habit of driving being my default mode of transportation.

I’ll let you know how it goes.

I’ve been thinking about this for a couple of days now, and I think Vision Pro is the make-or-break moment for VR and AR. Smartphones weren’t mainstream until the iPhone. Smartwatches weren’t mainstream until the Apple Watch.

The market for headsets like the Vision Pro feels like the market for smartphones and watches before Apple entered those markets. There are lots of headsets out there, but they’re really niche. They all suck in different ways and aren’t useful for much. This is the first one that runs what I’d call a “real” OS, by which I mean a headset that runs apps and is useful for things other than games — assuming you don’t get sick from playing them, which many people do.

Like the iPhone and Apple Watch, it will take a few years for the Vision Pro to go mainstream, and like those, people will probably make fun of it for the first couple. My thinking is still that if Apple isn’t going to be the one to do it after some number of years, the mainstream appeal of putting a thing on your face just isn’t there, or at least not until the technology of projecting things into someone’s eyes gets a lot better.

Enter your email to subscribe to updates.