Structure and Interpretation of Computer Programmers

I make it easier and faster for you to write high-quality software.

Thursday, October 30, 2014

Reversing the polarity of the message flow

On receiving a message with a parameter, sometimes an object just reverses the sense of what just happened and sends another message to the parameter object with itself as the parameter of this message. That’s a pretty hard sentence to read, but I couldn’t work out how to rewrite it, so here’s an example. A Smalltalk class might have a method like this:

  "Append to the argument, aStream, a sequence of characters
  that describes the receiver."
  description := self description.
  aStream nextPutAll:description.

I would do this as a matter of design: I can make it clear that I’m messaging one object and using another simply in a supporting role. It takes this:

foo doTheThing.
aStream nextPutAll:foo description.

and turns it into this:

foo doTheThing;

In Objective-C, this pattern has an additional use due to the nil sink for messages. Imagine formatting a string and appending the result to another string, but if the initial string is nil then you don’t want to add anything. It might look like this:

if (emailText) {
  NSString *quotedString = [NSString stringWithFormat:@"> %@", emailText];
  [output appendString:quotedString];

because I don’t want the phrase > (null) to appear in the output. But, with a bit of category magic, we can avoid the condition and make it clear that the email text is the important object.

[[emailText quote] appendTo:output];

I haven’t just hidden the conditional; it never appears. If emailText is nil then all the other messages will just get dropped, so neither quote nor appendTo: need to test for nil.

Sometimes, the messages are just flowing the wrong way, and clarity can be gained by reversing the polarity.

[Update: oops! I had read Kent Beck’s “Smalltalk Best Practice Patterns”, and apparently absorbed his Reversing Method pattern. This post is basically a discussion of that pattern, and credit should go to Kent for originally creating it. My addition is the Objective-C specific nil sink extension. Sorry, Kent.]

posted by Graham at 17:36  

Sunday, October 26, 2014

The Humpty-Dumpty Guide to OOP

Everybody knows that the best way to sound intellectual and demonstrate the superiority of your approach to that thing you do is to wrap it in a fancy-schmancy noun term. This works particularly well with a term that can be expressed as a three-letter acronym, or TLA. In programming we have a whole raft of different [A-Z]DD disciplines, the UML, CRC, and your DBA probably does SQL. It also explains why functional programming has taken so many decades to take hold: FP is 33% less appealing as a mere acronym of two letters (or ATL).

When your term is sufficiently arcane or abstract, you don’t even need to actually do the three-letter nouny thing. Just tell people that what you’re doing is the three-letter nouny thing, and let everybody fill in the gaps. In fact, they’ll probably agree that not only are you doing that thing but then so are they. Soon, everybody will be doing the nouny thing.

So it goes with Object-Oriented Programming. We can construct all sorts of definitions for Object-Oriented Programming the term, so that everybody can get in on this highfalutin concept without having to do anything. The best time to arrange for this wide collection of meanings is as early as possible. Let’s look at August 1981.

1. It’s all about messages.

The Smalltalk-80 system represents the current state of the object-oriented point of view as it has been reduced to practice by the Xerox Learning Research Group. The Smalltalk-80 system is composed of objects that interact only by sending and receiving messages. The programmer implements a system by describing messages to be sent and describing what happens when messages are received.

(“The Smalltalk-80 System”, Dave Robson and Adele Goldberg, BYTE Volume 6 Number 8 p.36)

2. Except when it’s not.

SIMULA allows users to create object-oriented systems, but uses the standard data/ procedure-oriented ALGOL language to provide numbers, booleans, basic data structures, and control structures.

(op. cit.)

3. Or maybe it is.

Instead of two types of entity that represent information and its manipulation independently, an object-oriented system has a single type of entity, the object,
that represents both. Like pieces of data, objects can be manipulated. However, like procedures, objects describe manipulation as well. Information is manipulated by sending a message to the object representing the information.

(“Object-Oriented Software Systems”, Dave Robson, BYTE Volume 6 Number 8 p.78)

4. Actually, maybe it means whatever you want it to mean.

The words “object-oriented” mean different things to different people. Although the definition given in this article may exclude systems that should rightfully be called object-oriented, it is a useful abstraction of the idea behind many software systems.

(op. cit., p.74)

5. But it definitely means garbage collection.

To be truly “object-oriented”, a computer system must provide automatic storage management.

(“Design Principles Behind Smalltalk”, Dan Ingalls, BYTE Volume 6 Number 8 p.289)

6. And definitely (this time, maybe) means message-sending.

This suggests a third principle for object-oriented design:

Messages: Computing should be viewed as an intrinsic capability of objects that can be uniformly invoked by sending messages.

[…]In most computer systems, the compiler figures out what kind of number it is and generates code to add 5 to it. This is not good enough for an object-oriented system because the exact kind of number cannot be determined by the compiler[…]

(op. cit., p.290)

7. This message-sending capability must be exposed to the UI.

An enabling condition for adequate flexibility of a user interface can be stated as an object-oriented principle:

Reactive Principle: Every component accessible to the user should be able to present itself in a meaningful way for observation and manipulation.

(op. cit., p.296)

[note: reactive programming woo]

So, you know what? Whatever you’re doing, it’s probably object-oriented. And whenever I say object-oriented, it may possibly mean whatever your meaning is.

posted by Graham at 18:37  

Thursday, October 16, 2014

Fuck. This. Shit.

Enough with the subtle allusions of the previous posts. What’s going on here is not right.

It’s not right that I get to pass as a member of the group of people who can work in technology, while others have to justify their very presence in the field.

It’s not right that “looking like me” is a pass to being considered for the best-paid jobs, while “not looking like me” is not.

[that last one took me a long time to understand. To me, it seems like I worked hard to get where I am, but I needed to understand that I was given the opportunity to work at the things I worked at. That all I needed to do was to work at it, not to work at it and convince everyone else that I was eligible to work at it.]

It’s not right that while I get a free pass into various fields of endeavour, others are told that they either slept their way into the field or are groupies or are unfuckable.

Previously, I avoided writing about this stuff because I thought I might get writing about this stuff wrong. Fuck. This. Shit. I’ve got social capital to burn; it’s much easier for me to get another job around this sector than plenty of people who are as good or better than me at doing the work. I might be worried about treading the line between being supportive and getting into trouble, but that’s not as bad as the line women, trans people, non-white people, non-straight people, disabled people have to tread between asking to be considered equally and keeping their jobs have to tread. I have one job: doing my job. I do not have two jobs: doing my job, and convincing people that someone like me should be allowed to do my job. If the cost of equality is giving up my free ride, then I give up my free ride.

The pipeline is not the problem, it leads to a vat of acid. No-one wants to lean in to a vat of acid. (Thanks to Cate Huston for that metaphor, it made a lot of sense to me.)

Our industry is exclusive, and needs to be inclusive. What should you do about this? I don’t know, I’m far from knowledgable. If your position is “I agree with the straight white guy that the world is broken, I should ask the straight white guy how to fix it” then perhaps you are the problem, just as I have been and am the problem.

What should I do about this? First step for me is to listen. To not tell people who are describing their experiences what my experiences are. To avoid thinking about my reply to people, and to think about what they’ve said. To stop looking for holes in arguments and to listen for opportunities to grow. Not just to grow me, but to grow others.

posted by Graham at 23:31  

Wednesday, October 15, 2014

More on Layers

I was told yesterday that entity-relationship diagrams can be OK as high level descriptions of database schemata, but are not appropriate for designing a database. Enough information is missing that they are not able to model the problem.

Could the same be true of layer diagrams? Perhaps they’re OK as stratospheric guides to your software, but not useful for designing that software as too much information is missing.

I don’t think that’s the case, though. Layer diagrams tend to be pretty much interchangeable between systems, so that I can’t really tell which system I’m looking at from the layer cake. Add the difficulty that I probably can’t tell how the layers communicate, and certainly can’t tell how the subsystems within the layers are composed. All I can tell is that you like drawing boxes, but not too many boxes.

posted by Graham at 09:02  

Monday, October 13, 2014

The trouble with layers

In describing Inside-Out Apps I expressed my distrust of the “everything is MVC” school of design.

[…]when you get overly attached to MVC, then you look at every class you create and ask the question “is this a model, a view, or a controller?”. Because this question makes no sense, the answer doesn’t either: anything that isn’t evidently data or evidently graphics gets put into the amorphous “controller” collection, which eventually sucks your entire codebase into its innards like a black hole collapsing under its own weight.

Let me extract a general rule: layers are bad. It’s not just that I can’t distinguish your app’s architecture diagram from a sandwich’s architecture diagram, or a trifle’s. The problem is in the boxes.

As Possibly Alan, IDK and I discussed recently, the problem with box-and-arrow diagrams is that the boxes are really just collections of arrows zoomed out. Combine that with something my colleague Uri told me, that “a package in the dependency diagram is just the smallest thing that contains a cycle”, and you end up with your layer cake diagram looking like this:

Layer Cake

Three big wastelands of “anything goes”, with some vague idea that the one at the top shouldn’t talk to the one at the bottom. Or maybe it’s that any of them can talk down as much as they like but never up. Either way it’s not clear how any of the dependencies in this system are controlled. Is it “anything goes” within a layer? If two related classes belong in different layers, are they supposed to talk to each other or not? Can data types from one layer be passed to another without adaptation? Just what is the layer boundary?

posted by Graham at 18:38  

Sunday, October 12, 2014

Yes, you may delete tests

A frequently-presented objection to the concept of writing automated tests is that it ossifies the implementation of the system under test. “If I’ve got all the tests you’re proposing,” I hear, “then I won’t be able to make any changes without breaking the tests.” There are two aspects to this problem.

Tests should make assertions about the externally-observable behaviour of the system under test. If you have tests that assert that a particular private method does its thing in a particular way, then yes, you are baking in the assumption that this private method works in a particular way. And yes, that makes it harder to change things. But it isn’t necessary.

Any test that is no longer useful is no longer useful: delete it. Those tests that helped you to build the thing were useful while you were building the thing: if they’re not helping you now then just get rid of them.

When you’re building a component, you’re probably thinking quite deeply about the algorithm it will implement, and how it will communicate with its collaborators. Thinking about those will mean writing tests about them, and whenever those tests are in the suite they’ll require the algorithm be implemented in a particular way, and that the module talk to its collaborators in a particular way. Do you no longer care about those details, as long as it does the right thing? Delete the tests, and just keep the ones that make sure it does the right thing.

posted by Graham at 21:38  

Thursday, October 9, 2014

The laser physics of software

I’ve worked in a few different places where there have been high-powered lasers, the sort that would make short work of slicing through Sean Connery in a Bond movie. With high-powered lasers comes mandatory laser safety training. At least, it does in the UK.

The first time you receive laser safety training it comes as a bit of a surprise. Then, the second (and later) times, you get to watch the same surprise in everybody else who’s watching it for the first time.

The surprise comes because you kind of expect to hear about cooked retinas, skin burns and all sorts of unpleasant nastiness. Which of course you do, but those aren’t the likely forms of laser accident. The surprising bit is the list of “popular” (not popular) ways to get injured by a laser:

  1. You electrocute yourself on the power supply.
  2. You ignite the liquid oxygen that’s built up around the liquid nitrogen cooling system, probably using the same power supply.
  3. You drop the laser (or indeed the power supply) on your foot.

So to programming. While we’re all donning our protective goggles of shiny new type systems and lack of mutable state, the “popular” (not popular) problems (we don’t know what we’re doing, we don’t know what we should be doing, we’re bad at treating people well) are not being addressed.

posted by Graham at 23:43  

Wednesday, October 8, 2014


That moment where you’re looking back through your notes to see that you’ve:

  • modelled charge carrier behaviour in semiconductors
  • built a processor from discrete logic components
  • patched kernels
  • patched operating system tools
  • written filesystems
  • written device drivers
  • contributed to a foundation library
  • fixed compiler bugs
  • performance-tuned databases
  • built native apps
  • built web apps
  • tested the above
  • taught other developers
  • mentored other developers
  • sold the above skills

and a thought occurs: someone who knows both PHP and JavaScript is called a full-stack developer.

Someone who tells you that programmers are rational actors who are above marketing is lying. Everything in the field is marketing, including the idea of rationality. Performing such marketing becomes easier when the recipients don’t think it exists, or don’t think they’re the sort of people who would fall for it.

I’m reminded of the audience reaction to this serial entrepreneur describing his recently-acquired startup’s technology (skip to 10:24 if the timestamped URL doesn’t do that automatically for you). He presents these four points:

  • DOS: 1 Analogy Unit
  • Mac + HI Toolbox: 5 Analogy Units
  • DOS + Windows: 7 Analogy Units
  • Mach OS + OpenStep: 20 Analogy Units

Listen to the applause for the unjustified number 20.

posted by Graham at 13:35  

Monday, October 6, 2014

More Excel-lent Adventures

I previously wrote about Excel as the most successful IDE:

Now what makes a spreadsheet better as a development environment is difficult to say; I’m unaware of anyone having researched it.

That research is indeed extant, and the story is well-told in A Small Matter of Programming. While Professor Nardi’s focus is on end-user programming, reading her book raises questions about gaps in professional programmer tools.

Specifically, in the realm of collaboration. Programming tools support a few limited forms of collaboration:

  • individual work
  • a team of independent individuals working on a shared project
  • pair programmers
  • code review

For everything else, there’s a whiteboard. Why? What’s missing?

posted by Graham at 22:22  

Sunday, October 5, 2014

What it takes to “win” a discussion

You may have been to some kind of debate club at school, or at least had a debate in a class. If so, the debate you had was probably a competitive debate, and went something along these lines (causality is not presented as its usual wibbly-wobbly self to keep the sentences short):

  • A motion is proposed.
  • Someone presents a statement in favour of the motion.
  • Someone else presents a statement against the motion.
  • A second statement in favour is made.
  • A second opposing statement is made.
  • Questions are asked and answered.
  • A favouring summary is made.
  • An opposing summary is made.
  • Somehow one “side” or the other “wins”, perhaps by a vote.

Or you may have been to court. If so, you probably saw something that went along these lines:

  • A charge is proposed.
  • Someone presents a case, including evidence, supporting the charge.
  • Someone else presents a case, including evidence, refuting the charge.
  • Questions are asked and answered.
  • A supporting summary is made.
  • A refuting summary is made.
  • Somehow one “side” or the other “wins”, perhaps by the agreement of a group of people.

Both forms of conversation are very formal and confrontational. They’re also pretty hard to get right without a lot of practice.

And here’s a secret that the Internet Illuminati apparently tries to keep shielded from many people: not every conversation needs to work like that.

Back in the time of the war of the three kingdoms, the modern party system of British politics didn’t exist in the same way it does now. Members of parliament would form associations based on agreements of the matter under discussion, but the goal of parliament was to reach consensus on that matter. “Winning” was achieved by coming to the best conclusion available.

And, it turns out, that’s a possible outcome for today’s discussions too. Let’s investigate what that might mean.

  • Someone wants to know what tool to use to achieve some goal. This conversation is “won” by exploring the possibilities and their pros and cons. Shouting across other people’s views until they give up doesn’t count as winning, because nothing is learned. That’s losing.
  • Two people have different experiences. Attempting to use clever rhetorical tricks to demonstrate that the other person’s views are invalid doesn’t count as winning, because nothing is learned. That’s losing.

Learning things, by the way, is pretty cool.

posted by Graham at 22:02  

Powered by WordPress