Collin Donnell

Freelance software developer from Portland Oregon.

Joel and I were lucky enough to be joined by Ethan Marcotte to talk about his new book, You Deserve a Tech Union. It's a fantastic book which I read in it's entirety before getting to interview Ethan on the show.

After the last year and the horrific treatment many full-time and contract tech workers have received, my thoughts on the idea of tech unions have really changed. I wasn't against them before, I just didn't know that it was a realistic thing that could happen. Ethan's book showed me that organized labor both has a long history in tech, and that there are companies with unions right now, like Kickstarter United.

If you're not into Ruby, I still recommend listening to this episode, since the entire discussion has nothing to do with Ruby at all, but does have to do with things all tech workers should be thinking about.

You can find the episode on our website, Overcast, Apple Podcasts, or anywhere else you can find podcasts.

Dash, a documentation viewer for macOS, just released version 7. I've been using Dash for at least nine years, and can't imagine why anyone wouldn't. What Dash does is let you have all of your documentation offline and with full text search. If you're familiar with the Xcode documentation window, it's like a better version of that, which also works for man pages, languages, web frameworks, whatever.

This version switches from a once a year upgrade to a $15 a year subscription, which seems insanely cheap for the value you're getting. If you're not already a user, you should go try it now.

If you use macOS, go put this into your zshrc or equivalent.

function xman() {
  open x-man-page://$1
}

Once you’ve done that, use it by typing things like xman grep to show man pages in their own window like this:

Terminal man page window

On macOS, Terminal.app handles the x-man-page URL scheme by opening a new window showing the man page you wanted. You can change how it looks by changing the “Man Page” profile in settings, but, why would you when the yellow looks so cool?

In 2018 I bought a Peloton bike. Since then, I think I’ve ridden it about 100 times. Always in fits and starts, too. I’ll ride it consistently for a few weeks here and there, then get sick or distracted and stop doing it. Based on that, I would say this has not been the investment I might have hoped it would be.

There are a lot of things to hate about working out. It’s boring. It takes time. It’s hard. Everyone says to find something you like, and it will be easy. That’s hard too. The closest I ever got to this was when I did Aikido for about a year and a half. Then I moved, felt like I regressed, started going less, moved again, and never found a new place to practice. Also, I never got good at the rolls, which is a real blocker in a martial art where large parts consist of getting through headfirst toward the floor.

Of all the things I hate about exercise, however, number one is how effective it is for improving my mental health. I can be sitting at home, unable to focus, having a bum out, thinking everyone hates me, get on the bike for twenty minutes, and feel 80% better. It’s pretty clear if I did this consistently enough to see real progress, my baseline mental state would be significantly improved.

Here’s another thing — I’m thirty-eight now. My blood pressure and cholesterol aren’t at the point of “we need to put you on medication,” but they’ve been hovering around “let’s keep an eye on this” for quite a while now. Regular exercise is pretty much guaranteed to improve that.

So, I got on the bike today. I’m going to try and get on it again tomorrow. I’m going to look into going to a boxing gym near my house. I don’t know if this time will be different, but I owe it to myself to try harder than I have in the past. Let’s see if I can cross 200 rides by the end of the year.

All my health stats are already tracked via my Apple Watch, and I’ve already been tracking my mood somewhat consistently. I’m going to try and post updates with any changes I see in order to give me a little bit of accountability.

If you're on Peloton, look me up as “FishermansPorch” and we can be friends.

Wish me luck.

#Fitness #MentalHealth

As part of my ongoing interest in the origins of object-oriented programming and design patterns like MVC, I started to think the best way to fully grasp these things was to go back to the beginning. While there are modern Smalltalk’s like Squeak, Pharo, and Cuis that retain a lot of the old-school vibe, they’re also pretty different.

I could go into detail on how all of those options aren’t quite what I’m looking for, but since I want to write about that later, the short version for now is that I started looking into how you could emulate the original Smalltalk-80 environment on modern hardware. That ended up being incredibly easy when I found this “by the Bluebook” implementation of it on GitHub.

After a couple minutes installing, I got it running and saw this:

Smalltalk-80 first run

At first glance, this looks incredibly similar to something like the desktop of the Apple Lisa or early Mac OS. It’s easy to see why people might think that Apple sort of stole the graphical user interface from it’s rich neighbor Xerox. It’s not true, though.

The first thing is that the Smalltalk environment wasn't really an operating system the same way something like Mac OS was. It’s more like an IDE that runs on bare hardware.

For example, there’s no traditional file system. Smalltalk environments were stored as images which contained the entire state of the system. That means all of the objects, code, data, whatever, were stored as Smalltalk objects. The creators of Smalltalk wanted to make a system where the person using it was also modifying and programming the system as they used it. That’s really cool as a programming environment, but not really how we think of normal people using computers today.

There’s also no desktop, icons, or pull down menus. The whole desktop metaphor isn’t really there, because that isn’t really what it was. It’s sort of pure in an appealing way. There aren’t many different categories of things there. Windows, pop-up menus, lists. Not a lot. You can collapse different windows you’re not using and organize them on your screen, but they’re all just still windows, as opposed to also having icons for files and folders and apps and other sorts of things.

Collapsed windows

If you want to do anything with a window, you might notice there’s no controls. All window operations are done modally, meaning you click, select what you want to do, and then do that thing. You can’t even move or resize a window by clicking and dragging. There is click and drag for scrollbars and text, but not for windows. Weird.

To resize a window you use the “frame” button

If you wanted to move this window you would select “move”, which collapses the window and ties it to your mouse location. You then move your mouse to wherever you want the window to be and click again to place it. Oh, and you can only click, because there are no key commands in this system whatsoever.

Looking at all of this together, yeah, the Lisa and Macintosh took a lot from Xerox. But, they also added a lot. The Smalltalk environment was a revolutionary GUI, but it was still a system you would have had to have been a computer operator or something to really use. It’s not a personal computer at all.

The fact Apple was able to see the potential and then figure out all of the metaphors and affordances which needed to be there for regular humans to use a computer like this, and that they got so many of those things right by the time of the original Macintosh is pretty incredible.

#programming #apple #smalltalk #ui

I really wanted to write something today, but I don’t think it’s going to happen. I’ve been feeling pretty anxious, which only got worse when I got a cold earlier this week. At this point, I can barely form any coherent thoughts. That’s why I’m not going to write anything.

Speaking about the anxiety thing — am I weird, or is everyone anxious most of the time, and they just don’t talk about it? The way things have been, and continue to be, it’s hard for me to imagine not having an underlying current of anxiety most of the time. Is everyone afraid they’re going to lose their jobs or have something go wrong at any moment? Maybe that says more about me than anything else. Maybe Swedish people?

I’ve wondered a lot about how living in a place that has a real social safety net affects the mental health of the people who live there. I’m sure it does. We talk a lot about how if we taxed rich people more in order to pay for doing that in the United States how it could disincentive investors.

That doesn’t make sense to me though. How many of us might try something they otherwise wouldn’t if the cost of failure wasn’t so high? It’s hard for a normal person to invest their personal capital in doing anything but continuing to do what they need to get by, that has to have an effect. Even if I’m totally wrong, I’d be okay with the risk of rich people taking fewer chances if it meant everyone else didn’t have to walk around feeling like this is the day everything might fall apart.

So yeah, that’s why I’m not writing anything today. Hopefully soon when I’m feeling a bit better.

#writing #anxiety

I’ve been thinking this week about how I write code and the quality I want to aim for. I’ve worked some pretty big and successful projects. I’ve seen things. So with that in mind, here’s what I’ve decided. There are only two times technical debt will ever be addressed: upfront or never.

What counts as upfront?

Upfront is anytime before the feature is “done.” I’m a pretty big fan of a style I call “getting in there and making a mess.” It’s actually one of the things I really like about SwiftUI. The whole style of writing SwiftUI encourages hammering out your view to the point where things are functional and then using the refactoring tools to break things up into components. Love that.

Figuring out what your abstractions are or where the objects are hidden is super valuable. It’s also generally only going to happen upfront.

You were probably wrong

I don’t care how many Uncle Bob or Martin Fowler books you read, your architecture is probably going to suck, you’ll never really fix it, and you’re going to spend the rest of time with it hanging around your neck. It’s that feeling where writing code in a project goes from being exciting to something where you mutter under your breath before starting each day once more unto the breach.

Your clean architecture you made super DRY will be the biggest piece of technical debt you have.

Eventually the other people at your job will start telling you why it’s actually a good thing. You don’t understand! We’re not like other companies, we’re cool and quirky and we needed to abstract away every API in the framework we use and put our own crazy thing on top of it. They’re wrong. Those people have been indoctrinated.

You don’t want to be the person starts talking about rewriting everything after their first week, but after a little while if everything still feels crazy and like it makes everything suck a little more, it probably does. Trust that instinct. Or don’t! Eventually you’ll be indoctrinated too. Or you’ll quit or get fired. One of those.

You never know less than when you’re starting

This is a truism that made sense to me as soon as I heard it the first time. The worst time to make decisions is upfront. You know so little. This is a terrible to commit to anything.

Wait. Didn’t I say that the only time decisions get made is upfront? Yeah, I did. Listen, life contains a lot of contradictions. Things aren’t always going to make sense. You should get used to that.

So what should you do?

The thing you can do upfront is refactor as you go (don’t overdo it) and make it as easy possible to change your mind later. Delay, delay, delay. Just make as few decisions as you can, so when you have to do the next thing.

Since I should probably finish this with something kind of actionable, here’s my recommendations.

The biggest thing I would think about is cohesiveness and getting an ability to feel out if things are remaining that way as you try and pull out your abstractions.

Avoid heavily abstracting away the API of whatever framework you’re writing on top of as much as possible.

Never (never, never) import a complex overarching architecture into your project. Do not. Especially not one that I promise you it will be terrible. My biggest red flag is anything that starts asking you to pass calls through multiple things to do one thing. Keep things as simple as you can as long as you can.

I get that this had some contradictions in it, but as I said, life is like that sometimes. The thing with technical debt is to minimize and delay. Also, don’t listen to thought leaders.

#programming #architecture

If you enjoyed my MVC Isn’t MVC post from a couple of days ago, you might also be interested in the latest episode of the Rooftop Ruby podcastJoel and I discuss our thoughts on the post before getting into more detail on MVC, the forgotten editor controller, and how we might be able to implement something closer to the original MVC on the web using modern technologies like morphdom and Turbo Stream broadcasts.

You can find Rooftop Ruby by searching for it in your podcast app or clicking the link above.

#programming #podcast #ruby

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.

Enter your email to subscribe to updates.