What is Software Architecture?

Even in the best books (POSA, POEAA), “software architecture” is pretty loosely defined. In POEAA, Fowler says:

I tend to look at “architecture” as one of those impressive-sounding words, used primarily to indicate that we’re talking something that’s important.

And (emphasis added):

There are two common elements: One is the highest-level breakdown of a system into its parts; the other, decisions that are hard to change. … In the end architecture boils down to the important stuff—whatever that is.

“Whatever that is.”

Let’s break down what Fowler actually says there, because it’s probably the best definition we’re going to get.

  1. The highest level breakdown of a system into it’s parts. This seems obvious. From the very beginning of, say, going through a RoR tutorial or some other framework setup, you are assembling these parts together: in a web application for example, you’ll probably need a database. You definitely need a web server. If you’ve chosen RoR or a similar framework, it is assumed that you are going to have models, controllers, and views, and you are encouraged to organize things in a certain way. But there are other choices and components as well. Will there be background jobs? Are there external components, services, or APIs which you must query or update periodically? Is user authentication part of your system, or is it dependent on some external service, like Twitter or Facebook Oauth, an LDAP server, or something else entirely? Will this change later? I think if we’re just plowing ahead without asking these question, we aren’t thinking about software architecture. If you are stopping to ask the questions, you are thinking about architecture.

  2. Decisions that are hard to change. Some decisions are (hopefully), easy to change. Ideally, in an MVC framework, it is very easy to change your views without changing any other part of your application (if you don’t think this is true, you might not be doing MVC as intended, as this is one of the explicit goals of an MVC architecture). Again, if you need to change your datasource, hopefully this is an easy thing to change. This is dependent on a few things, but let’s at least say that theoretically, if you’re changing from one relational database to another, that shouldn’t be a crazy impossible task: it should be moderately simple to switch from, say, MySQL to Postgresql.

Other decisions are not so easy. If you commit to a framework or language, making a change probably means a complete rewrite. If you choose Rails, or whatever, and then later on, when your app is more or less complete and functional, you think that maybe you’d like to use Ember or Meteor or a Clojure framework: congratulations. You’re likely going to be rewriting the whole application.

Knowing which decisions will be hard to change is a mixture of common sense and experience. Some things might be immediately obvious even to a new programmer, while other times it maybe be obvious only to a senior developer that there are dragons in those waters.

So that’s sort of it. Architecture, in and of itself, is not really arcane or esoteric.

Highest level breakdown.

Things that are hard to change.

There’s a certain amount of experience needed in order to identify these things, of course, but I honestly feel like that experience can be accelerated by exploring these ideas earlier in your software career. If you do that, you can hopefully see these things in your own code and in the applications you’re working on and contributing to sooner than you might otherwise see them.

Install Go on Mac OS X


I’m just going to talk about installing Go on Mac OS X, because that’s the machine I have.

The actual installing couldn’t be simpler. If you visit http://golang.org/doc/install, you’ll see a nice friendly link to the Go Downloads page. You’ll see a batch of those which are for OS X 10.x+; choose the one that best fits the Mac you’re using. Choose the pkg download, unless you have some reason to want to install from source.

The pkg will open a typical Mac OS X installer wizard-style program, and it will install Go in /usr/local/go, which is where Go expects to be found.[^1]

Go does expect a few environment variables to be set.

$GOROOT is set to /usr/local/go by default, so you’d only need to change that if you installed Go in some non-standard location.

You’re not quite done. Go expects code to be organized in workspaces. All that means is you’ll want to create a directory for your Go work, and put your various Go projects inside it. Then Go needs to know where this workspace is.

For example, assuming you did mdkir ~/go, you would put into ~/.bash_profile

A little more

Go also assumes that you’ll be working with projects stored in source control, and wants us to use the repository’s root as our base path. If I’m creating Go projects and planning to put them in my github.com account, I’ll want to put them in a structure like:

I’ll leave some basic _hello world_ing up to you; I would recommend going through How to write Go code. It shouldn’t take very long, you’re already set up.

uncommon is alive

uncommon is alive!

I’m proud to have had a part in the inception of this project, though other responsibilities prevented me from taking a larger role in helping to create it. I hope I’ll be able to contribute some more in the future.

You can see what it’s all about here:

Uncommon in Common is the online home for a community of kind and curious people like you, a front porch for the Internet. It’s a place to share our favorite things and the best parts of our week, a place for meaning and wonder.

Right now, it’s only open to the founding members, people who joined the mailing list and made a small contribution early on in the project’s history. As I understand it, soon each member will be able to invite another soul for a year’s membership. At some point (I’m not sure when?), it will open up for membership. Stay tuned. It’s going to be a wonderful thing.

Refactoring with code blocks in Ruby

I came across this situation the other day. I had a method which already existed on one model: let’s say it ran through all of that models associations and did a thing, a notification, for example.

Seems okay. Turned out, I had another method, somewhere else, which also wanted to notify all the groups members–but it also wanted to do a little more logging. Let’s say, something bad happened: we need to put the Group in a different state, and then not only notify all the members, but do some logging. This is logging that we don’t need to do in the normal notify_members method. We could duplicate behavior:

But other than the extra things that we do, now we have two methods, which both iterate through our group’s members and notify them. Seems to violate DRY a little bit. It’s not the end of the world, but it could be better.

Enter Ruby blocks. Instead, we could do something like this:

Now our second method simply uses the first method, but adds some extra logging into the mix. We can yield the member up to the block, which is necessary because in this (contrived) example, our Alert creation and our logger message both want to specifically call out the member for later reference.

Code blocks. Spend some time with them. They can make your life better.

Responding to :js in Rails

There is an underused feature in the way Rails allows you to write respond_to blocks in your controllers, I think: specifically, in that you can (if you like), tell your controller action to respond directly to JavaScript with more JavaScript. Not simply responding with JSON, though you could do that; I mean you can write complete AJAX-y workflows and let Rails do most or all of the heavy lifting for you.

Let’s assume we’re going to have an action that might be called from a regular link OR it might be called via an ajax request. So we’ll want

Now if we link to our action like:

we’ll get an attribute in the resulting anchor tag that looks like data-remote='true', and Rails will handle clicking on that link as if it were an ajax request to whatever the target url is, which in this case, will go to our action. It will fall into the format.js block, and since there’s nothing there, will try to execute the_thing.js.haml (or erb or whatever).

Let’s try something extremely simple just to see that it works.

Let’s make a new rails app and a controller.

That’s a lot of files. Let’s talk about what’s going on.

For starters, if you try this, when you click the “foo” link on the index page, a js alert dialogue will appear. Not only that, but it says “It’s working, Dave.” It worked! But how?

In blatant disregard of rails convention, we created a custom route with our other actions for the foos controller. Having done that, we told that action (in the controller) it could respond to js. We created a js template in the views folder with the same name as our action, so it’s the template that rails tries to run. When we click the link, rails does run it, and because it’s an erb (or haml or slim) template, we can put Ruby in it, too. This is pretty awesome.

That’s really all there is to it. Using just this mechanism you could submit a form with data-remote => true and then save a record and have the resulting js template replace the form with a different partial.

I’m considering putting together a more extended, practical example of this type of technique. Is this interesting? (Y/N) Let me know.

Yoyo, so you can yo while you yo


Things I learned: Yo has an api

Yoyo is a gem1 for you to… call the Yo API. So. Well. That’s a thing you can do, now.

The API is pretty interesting, and (I guess) not surprisingly is very limited. You must setup an API account, which cannot be the same as your normal YO account. With your new API token, you can make POST requests to:

  • YO at some specific user.
  • mass YO to all your “subscribers” (anyone who has every YO’d your API account).

There doesn’t seem to be any way to ‘unsubscribe’ from a YO api account, other than you can (of course) block any given YO account from within the YO app.

Also, you can supply an endpoint to YO, which they will send a GET request to every time someone YOs your API account. In other words, if you want stats, the onus is upon you to set up an endpoint to keep track of exactly when and how many times other YO users have YO’d you.

That’s about it, I think.

  1. I’ve made a few gems in the past, but it’s been awhile. I referred to the quite excellent How I start by @steveklabnik. Recommended, if you, like me, were rusty on Ruby Gem assemblage.