There are only two hard things in Computer Science: cache invalidation and naming things.
Phil Karlton
Two hard things, but they are not the same kind of hard. Naming things we do it every day. And we read and re-read the things we name all day long.
This is a post about names. And ambiguity. And pain. And how to iterate on that to get something better at the end of the day.
And I’ll illustrate some ideas with the OSWindow project.
An OSWindow has a handle…
So, an OSWindow
has a handle
.

But let’s first start by saying what an OSWindow
is. An OSWindow
is an object representing an operating system window in an uniform way. Behind the scenes, an OSWindow
uses some backend like WinForms in Windows or Cocoa in OSX. The main backend implementation we have in Pharo uses SDL2, a cross-platform library, mainly designed for game dev, that can be used for windowing.
So, let’s start again. An OSWindow
has a handle
. From the explanation above, you may think the handle
is a pointer to a real window implemented in the backend framework. Actually, handle
is indeed the name we use in pharo to designate a pointer to some externally managed memory region. For those used to FFI, a handle usually designates an ExternalAddress
or pointer (And for those who aren’t you may take a look here).
However, regardless of our first impressions on this, reading the code shows another thing. The code manipulating this handle
does not use it as an ExternalAddress
, because the only thing we can do with external addresses is to read or write them (or operate with them, they are addresses after all). For example, let’s take the following piece of code from the OSWindow
class:
handle show
or even:
handle newOpenGLRenderer
So the handle
is finally not an FFI thingy as we thought! It’s more like a backend object representing the real window. Of course, the different native windows are manipulated through different sets of functions. And it seems it was decided to manage these differences as a composition of objects instead of inheritance, which we will not discuss nor argue today. Today we focus on names.
It turns out that these backend objects are also called handles. We have for example OSSDL2WindowHandle
, OSVMWindowHandle
, OSNullWindowHandle
. This seems consistent with what we saw before. So, an OSWindow
actually has an OSWindowHandle
and not an FFI handle. I think we now understand enough to keep reading more code…
Let’s now dive in the OSSDL2WindowHandle
class.
Wait! What!? WAT? The OSSDL2WindowHandle
has another handle
. But this cannot be an OSWindowHandle
, right?
Or maybe now we did arrive to an ExternalAddress
finally.
Again, reading the code tells us it is neither… For example the following pieces of code sending messages to the handle that are implemented in none of the classes we expect:
OSSDL2WindowHandle >> toggleBorderOn [
handle toggleBorder: true.
]
OSSDL2WindowHandle >> getWMInfo [
| wmInfo |
wmInfo := SDL_SysWMinfo new version: SDL_Version bindingVersion.
handle getWMInfo: wmInfo.
^ wmInfo
]
Following a bit the code, we can see this second handle is actually an SDL2Window
implemented as an FFIExternalObject
. And then I, used to uFFI conventions, know that FFIExternalObject
s have a handle themselves, the real handle we were looking for from the beginning.
So the handle
of the handle
is an external object, which has a handle.
the handle
has a handle
with a handle
. What could go wrong here? 🙂
I don’t know you, but I felt pretty lost when reading this code, because of this overloaded terminology. The same name is used to designate three different things. And those different things are in overlapping domains! So when reading handle
we need to actively think where we are and what it is designating here and now. And for worse, this problem of overloaded terminology does not stop at the name handle
, I’ve found also that window
could designate an OSWindow
or an OSWindowHandle
. So what do you think the following expression returns?
window handle
Take your pick 🙂
Getting the names on the handles
I decided to fix this name confusiology in this Pull Request by doing a couple of renames. I chose new names, that you may not agree with btw, following a couple of guidelines:
- avoid ambiguity: three different names for three different non-interchangeable concepts
- use generic names when possible, but staying in the domain terminology
- use concrete names when variables will only reference objects of a single type/class
Reading the code and understanding the domain helped a bit in choosing the names, which now make OSWindow domain read as:
An OSWindow has a backend window, instance of OSBackendWindow. An OSSDL2BackendWindow has an sdl2Window (no need to say the class ;)). Moreover, all objects designate OSWindows as window, and OSBackendWindow as backend windows .
Name the next step!
Do you agree with the names I choose? Please share yours! Discussing names is the only way to find better ones :). And we can always iterate and improve more. No design should be carved in stone.
In the meantime, I’ll keep improving OSWindow, we should have good support for multiple native windows soon.
I hope you enjoyed and that you give good names in your programs. For your future self. Or at least for me, if I have to read your code 🙂
Well done thanks!
LikeLike