Structure and Interpretation of Computer Programmers

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

Sunday, December 31, 2017

AROS

I spent the weekend teaching myself some Amiga GUI (Intuition) programming using AROS via the Icaros Desktop distribution, their developer guides, and the Amiga developer CD. It’s a nice enough system to program in that works like most other GUI systems; GUI events are sent to your process as messages that you receive, handle, and reply to. GUIs are built out of gadgets attached to windows displayed on screens.

As a system to use, it feels efficient and fast. AROS is, as the Rhapsody developer releases were, a platform displaced in time: someone designed it to run on a 680×0 with a couple of megabytes of RAM and a floppy drive, and here we are with our modern CPU, gigabytes of RAM and solid state storage. It starts near-instantly, responds quickly (even though it’s running in VirtualBox under a Windows 10 host), it’s beautiful. And it’s not overloaded with widgets and gewgaws added by vendors who are keeping up with the Joneses by adding every new feature to every platform they support. No notifications ask me whether I’m interested in a tour of all the latest features that I’d be unable to find myself.

As I write this post (in the Odyssey Web Browser in Icaros Desktop, of course), I wonder whether I need all of the other things I would get if I were doing this directly in Windows, or in macOS, or a modern Linux distribution. Give me a compiler long enough and a place to save and I shall move the Earth.

posted by Graham at 16:07

Wednesday, December 27, 2017

Computing’s fundamental Principle of No Learning

I haven’t used Taligent’s frameworks or operating systems directly; what I know of it comes from their documentation and the book Inside Taligent Technology. I put some small effort into finding out whether it’s possible to use the Taligent system legitimately on a modern computer, couldn’t find a way, and didn’t get too sad about that.

The Taligent frameworks look – assuming they were ever as complete as the documentation promised – like fairly standard 1990s OOP-in-C++ which almost certainly makes them less fun to use than modern Qt. What I got from considering Taligent was a reflection on trends in modern computing platforms, that discoverability is killing power user features, and the app icon is killing complex workflows.

There is a false dichotomy at work in modern app design: the drive is for apps to be so simple you can use them as soon as you’ve tapped the app icon, but this is taken to mean that there doesn’t need to be anything more to do in the app than what you can see when you have tapped the app icon. As an example, the bookmark manager app on my iPad shows me a list of my bookmarks, and there’s an “add” button. If I click on a bookmark, I can view it. That’s it. That’s “managing” bookmarks, app-style.

But I would suggest it’s not just the apps that are doing it, it’s the platforms too, and that’s how Taligent entered this story. Their central desktop metaphor was called People, Places, and Things, based on the idea that I might want to focus on those things mediated by a computer, rather than on applications that support particular use cases.

A particular example of the People metaphor is that I might want to show a photo of my cat to my sister. Back in the days of the real world, I would do that by showing the photo of my cat to my sister. In the brave new world of the app, I look at my phone to see what messaging apps I have, try to remember which ones I have her as a contact on, which ones she will actually check, whether they send pictures and if so, what that costs or how it futzes with the picture. I launch that, go to the conversation with her (or start one), add an attachment, try to think about whether this needs to be a Camera, Gallery or File attachment, and so on. This is made most painful when using the in-car voice UI on my smartphone, which seems able to transcribe messages well but unable to listen when it asks what app I want it to use to send the message. Like I care, cost and picture-futzing aside (though I’m not usually taking photos with the in-car voice UI).

The Places metaphor is particularly interesting. Each “place” is a virtual gallery, town hall, office lobby, project office, or whatever that contextualises a given group of People and Things relevant to the place. In implementation, it’s a sort of context-sensitive desktop management. In concept, it makes me think of the PARC Ubiquitous Computing principle and how a location-sensitive computing environment could adapt as I sit at my desk, join some colleagues in a meeting room, or collapse on a beanbag at home. It makes me think of the Eudaimonia machine and how a context-sensitive computing interface could support shallow-and-broad to narrow-and-deep work environments. Then I consider how the static home screen on my smartphone…does not do those things.

An important part, I believe, in the downfall of People, Places and Things is what it means for software. Rather than buying “an application” from a vendor that shows me their beautiful, crafted icon until I’m ready to launch it, I buy a capability that extends the ways in which I can interact with the People, Places and Things represented on my computer. My computer does not become Photoshop, rather I gain Photoshopness by adding it to my computer.

It seems that any shift from app-centric to goal-centric computer interfaces – PPT, OpenDoc/OLE, NeXT Services, scripting/automation tools, the spatial desktop – is going to violate the Fundamental Paradox of App Marketing: my app is so intuitive and easy to use that it just fades into the backdrop of your life, however it must never fade so far that you do not see its name or its icon, and are not reminded who we are and how much we help you.

Similarly, they violate the Principle of No Learning discussed above: I must be able to see how to do everything, and I must only be able to do everything that can be seen. The desktop metaphor allows for spatial arrangement of your work, just like strewing papers around a real desktop, but you need to work out what those funny line-and-square icons mean and which bits of the window frame are draggable, so that goes. Drag-and-drop makes for a visual placement metaphor letting me “put” work from one document into another, but you can’t obviously see that it’s a thing (nor indeed what it will actually achieve; Drag and Drop seems intuitively destructive, sometimes is, but sometimes surprisingly isn’t. What’s the metaphorical outcome expected when you try to put your Hackers DVD in the Trash?). Therefore drag-and-drop is replaced with “Share Sheets”. Scripting not only requires learning a new application – the script editor – but a whole new user interface for existing applications. Forget it.

The Paradox of App Marketing is merely misguided self-aggrandisement, but the Principle of No Learning is one of computing’s big, stultifying, patronising, antiethical mistakes. It makes out that computers are simplistic tools that can do the things delivered unto the users by the app makers, and nothing else. It hides the magic behind the curtain by removing the curtain and the magic.

posted by Graham at 21:28

Thursday, December 21, 2017

Functional programmers like to claim that you can’t reason about mutable state programs. Some thoughts:

• the first half of the book A Discipline of Programming by Edsger W. Dijkstra tells you how to do it. That half of the book is approximately 100 pages (the remainder of the book is worked examples).
• object-oriented programming breaks a software system up into separate systems running miniature, message-driven programs as if on separate computers. Therefore the consideration of “mutable state” can be split in two: the state internal to the object and the state external to the object which sends messages to the object but is ignorant of its internals. If you can’t split the state that way, you have bad encapsulation.
• The reasoning done about the external and internal behaviours had better match at the interface. Design by contract probably helps here.
• Given a state S, an operation O can be defined as $$O(args \times S) \rightarrow (R \times S’)$$, i.e. it returns a result R and updates the state to S’.
• However, Bertrand Meyer introduced Command-Query Separation in the 1980s, so you only need to know $$O(args \times S) \rightarrow (R \times S)$$ and $$O(args \times S) \rightarrow (\emptyset \times S’)$$.
• Various history “traces” can be considered equivalent and therefore a lot of knowledge about the historical state transitions elided, simplifying the reasoning. For example, given a well-designed stack, it is impossible to distinguish the history of stack.push(3); stack.pop(); stack.push(7) from stack.push(7).
• Various operations on the state are irrelevant to the behaviour of an operation under consideration. In reasoning about the final operation in a = 3; b = 7; c = 9; stack.push(2) you do not need to consider the assignment operations (and indeed their presence may indicate a cohesion problem in your design).
• The one remaining source of difficulty is aliasing; I do need to know about the elided operations in the sequence x = 7; *y = &x; ...; z=f(x). This is aliasing, not mutable state.
posted by Graham at 20:07

Tuesday, December 19, 2017

All the things

It’s been a long time since I had a side project, or one that didn’t get abandoned very early on. I tend to get sidetracked by other thoughts about computing, or think “while I’m doing this, I’m leaving that unsolved” so nothing gets very far.

In an attempt to address that, to clear all of the different thoughts I have about the matter of computing out of my head, organise them, identify conflicts, and prioritise what I work on, I spent this evening jotting down the big points and a brief abstract about each one. I’m hoping this will cut the Gordian knot by letting me see it all in one place and start to make choices.

The format I chose to represent this braindump is this personal Technology Radar, based on the Thoughtworks build-your-own tool. It seemed like a good place to see everything at once, and look for clusters or trends.

You’ll notice that almost everything in this radar is fairly old tech! That’s mostly a matter of taste, as I enjoy learning about things that were tried, what succeeded or failed, and what can be learnt from that to put to use today. I’m not good at novelty for novelty’s sake.

I expect to get some mileage (for my own benefit, you might like it too) out of expanding on some of the entries in this radar over a few more posts, so I’ve created a techradar category in this blog that you can filter on/out.

posted by Graham at 21:34

Thursday, December 14, 2017

Against our values as a company

I’m going to pick on Patreon, not because they’re special, but because they’re typical. Here is a quote from a blog post in which they Back-pedalled a change to their pricing structure:

We overstepped our bounds and injected ourselves into that relationship, against our core belief as a business.

What I think they want us to hear is “this was a surprising event that normally wouldn’t happen because it’s important to us that other things happen instead”. What I actually hear is that management at companies like this is at best asleep at the wheel, at worst Github/Uber levels of arrogant and ignorant. Either way, new management is needed.

It’s fine to mistakes. It’s fine for someone acting in what they believe to be the best way aligned with their company’s goals and mission to do something out of step, that gets detected and corrected. That’s good management: trust, but verify. On the other hand, this is not an intern sending out an off-tone tweet. For a whole organisation to pivot its business model, create the marketing message, release the marketing message, and schedule the implementation of the new model…either management were involved and didn’t notice or care how broken it all was, or management are not involved and the whole company works around them.

posted by Graham at 16:57

Sunday, December 10, 2017

• There is no ethical impact of my job; I build technological systems and it’s up to others how they use them.
• Software is a purely technical discipline.
• There is some innate affinity for computer programming which you must be born with, and cannot be taught.
• Allowing people who are unlike me to program can only be achieved by “lowering the bar”.
• Compiled languages are always faster.
• floating point calculations will introduce non-deterministic errors into numerical results.
• OK, they introduce some errors into numerical results.
• alright I understand that floating point calculations are imprecise not inaccurate, Mister Pedantic Blog Author, but I cannot know what that imprecision is.
• at least the outcome of integer maths is always defined.
• fine, it’s not defined. But whatever it was, the result of doing arithmetic on two numbers that each fit in a data register itself fits in a data register.
• every computer on sale today (2017) uses two’s complement notation for negative numbers.
• every computer on sale today uses a register width that’s a multiple of eight bits.
• the bug isn’t in my code.
• the bug isn’t in the library.
• the bug isn’t in the operating system.
• the bug isn’t in the compiler.
• the bug isn’t in the kernel.
• the bug isn’t in the hardware.
• bug-free computer hardware is completely deterministic.
• the lines on the hardware bus/bridge are always either at the voltage that represents 0 or the voltage that represents 1.
• if my tests cover 100% of my lines of code then I have complete coverage.
• if my tests cover 100% of my statements then I have complete coverage.
• if my tests cover 100% of my conditions then I have complete coverage.
• if I have complete test coverage then I have no bugs.
• if I have complete test coverage then I do not need a type system.
• if I have a type system then I do not need complete test coverage.
• no hacker will target my system.
• information security is about protecting systems from hackers.
• if the problem is SQL Injection, then the solution is to replace SQL; NoSQL Injection is impossible.
• my project is a special snowflake; I can reject that technique I read about without considering it.
• my project is much like that unicorn startup or public company’s project; I can adopt that technique I read about without considering it.
• people who do not use my language, technique, framework, tool, methodology, paradigm or other practice do not get it.
• any metaprogramming expansion will resolve in reasonable time.
• any type annotation will resolve in reasonable time.
• OK, well at least any regular expression will resolve in reasonable time.
• can you at least, please, allow that regular expressions are regular?

I’m sure there must be more.

Update The following were added later; where they were supplied by others there is citing link. There are also good examples in the comments.

• You need a computer science degree to be a good programmer.
• A computer science course contains nothing useful to programmers.
• Functional Programming is a silver bullet.
• Rust is a silver bullet.
• There is a silver bullet.
• There can be no silver bullet.
• Rewriting a working software system is a good idea.
• I can write a large system in a memory unsafe language without introducing vulnerabilities.
• I can write a large system in a memory safe language without introducing vulnerabilities.
• Software is an engineering discipline.
• Software is a scientific discipline.
• Discourse on a topic is furthered by commenting on how I already knew a fact that was stated.
• A falsehood about programming has no value unless the author of the falsehood provides supporting evidence to my satisfaction.
posted by Graham at 08:56

Friday, December 8, 2017

Considered harmless

Don’t like a new way of working? Just point out the absurdity of suggesting that the old way was broken:

Somehow, the microservices folks have failed to notice all that software that was in fact delivered as monoliths.

What the Rust Evangelism Strike Force doesn’t realise is that we’ve spent decades successfully building C programs that don’t dereference the NULL pointer.

This is a sort of “[C|Monoliths] considered harmless” statement. Yes, it’s possible to do it that way, but that doesn’t mean that there aren’t problems, or at least trade-offs. “C considered harmless” is as untrue and unhelpful as “C considered harmful”; what we want is “C considered alongside alternatives”.

posted by Graham at 11:19