Thursday, July 12, 2012

My favorite ideas in the Go ecosystem - a usability perspective


At the Meet the Go Team session at Google I/O 2012, a question that brought a bunch of different responses from the main people working on Go was ‘What is your favorite Go feature?’. But I lie. The question was actually ‘What feature or design decision of Go had the most surprising effect on how code was written?’. Ken Thompson thought it was slices, Rob Pike thought it was interfaces, Robert thought it was packaging and the single executable, and Andrew thought it was the structuring of packages.

But considering the question myself later, my thin memory seemed to have modified the question. And there I was evaluating my favorite things in and around Go. Apart from an overall love for the language, is there a dimple, or two, that makes it just a little more attractive? So I’m clearly not answering that IO question, but indulge me here.

It got me thinking back about my initial exposure to the language. There were many times when I was initially figuring out Go where I would compare and contrast against existing languages I used to be proficient in, which was mostly object oriented languages but also included C and perl. During these times there were many ‘aha’ moments of understanding. Interfaces was definitely a multiple aha moment. Without having much of the baggage associated with OOP, when I wrote small samples that gave me similar results with a much simpler programming system, I was surely impressed. Slices was a concept I’d already seen in Perl and so it didn’t particularly blow me over. But clearly it was a significant plus over Java and C# for a compiled language. Similarly the package structure, concurrency, etc. But they’ve all been claimed by others. Yet, do I have any others that tug at my heart?

Daniel Kahneman in his book ‘Thinking Fast and Slow’ and Malcom Gladwell in his book ‘Blink’ talks about chess players who are known to group arrangements of chess pieces as a single snapshot in the brain, recognizing the entire layout immediately from familiarity the next time they see it (some call it that abused word ‘intuition’ also). I do not know this for sure, but I’m thinking that if there are smaller number of pieces there might be less information to store in each snapshot and probably we are able to store more of it.

The naming conventions of variables, functions, packages, and also files. I think this is adorable. Small, sweet, and working. Again this was an idea that I had to change. Coming from languages like Java and C#, I was used to long variable names. My argument for following that was that it cost nothing to have long variable names, especially with auto completion and powerful IDEs but it probably was a learned habit. With Go I realized that it was not only unnecessary but probably also wasteful. I still use medium sized variable names for primarily global variables, but inside a function a few keystrokes per variable is the norm. Now my statements are much cleaner, quickly readable, and usually take up only about half the horizontal code window as opposed to wrapping around a few times.

Not directly as a consequence of only size of names, but there also seems to be a large decrease in the number of lines of code written and also the number of files. (Check the oauth implementation in Java and Go. Also do compare the number of files in the entire source tree.) This has helped both readability and understanding as I’m able to see, not so much chunks of variable names, but chunks of functionality. When I see code, I seem to scan through it seeing blocks of code, not follow it line by line, picking up operations that are happening - function calls, comparisons, math operations, evaluations. I look at a block and think, oh such-and-such must be what it is doing - pattern recognition against snapshots rather than following a mental flowchart of line by line code flow. That code text is ordered and small is very helpful. That’s why it is third on my list.
Additional note here: when I go back to coding Java or C#, I seem to revert back subconsciously into the accepted style of longer variable names. So I suppose the culture of the programming language affects one’s style irrespective of whether one consciously knows an alternative.
Author’s confession: Re-reading the above section, I get the feeling that I’m extremely biased towards Go. So if you have better examples that prove it wrong I’ll be very glad to re-examine this section and rewrite it.

When all else fails, standardize. I’ve spent some time in four countries, two in which they drive on the right of the road and two in which they drive on the left. And I’ve never had an issue switching between the two. Yes, I would be cautious at the beginning when landing in the country and picking up a car, but once you sink into the defined order, the rest is automatic. It didn’t matter that much that we had to drive on the right or on the left, but just that everybody was doing the same and knew what the other person was expected to do.

Gofmt. In my personal experience, there were a few times, but I must claim very few times, that I attempted to impose a specific coding style. I did insist with teams however that we pick up the accepted way of writing code in that language and universally adopt it across the project to aid readability and maintainability. But if flame wars on the internet are to be understood, people want to stamp their individuality on an otherwise quite irrelevant topic. And apparently, you have to pick a side. Over time it seemed to be as inconsequential as the editor wars. Though I do claim vim as my favorite editor and nowadays SublimeText in vim mode - there I did it too! gofmt, in my opinion, saved the world of go from inconsequential discussions and that it is built into ‘save’ on SublimeText with the GoSublime plugin takes it off my sight and mind also while being effective. That’s a winning idea. And second place in my list.

One of my favorite books of all time is Donald Norman’s Design of Everyday Things. I’ve bought it in three continents and handed it off to others and have recommended it enough to give Don a considerable profit. And one example has stuck to me for ever. Doors. Have you noticed how certain doors have a particularly insidious quality that makes the normal person look idiotic - pushing when you have to pull, pulling when you have to push? Most people end up looking foolish, appearing clumsy, or worse yet, annoyed. I have even known large glass doors shattering under the impact of an attempted opening in the wrong direction. Well, there is a clearly marked PUSH and PULL sticker on the door you say. But that is a symptom of the problem that you have to label things to know what needs to be done.

The problem is mainly that these doors tend to have handles on each side, and the natural thing for a person to do on a handle is to pull it. So is there a possible solution? Think of fridge doors. And how you interact with it. One usually opens it via the handle - an action of pulling. And closing it? You usually push the wide front of the refrigerator door - the handle is almost never used, or at least I don’t. Now rethink your door without labels. What could you do? On the PULL side, keep the handle. On the push side? Just remove the handle. That’s it. Nobody can pull on that side now. Of course, you can replace it with a flat metal plate if you don’t want to dirty the door, or with a pushable security mechanism, but you get the idea. The solution here includes a subliminal non intrusive clue which gives you an idea of its functionality without requiring you to read a separate label or figure it out through trial and error.

Also see some special cases: hyper-norman door and an etched label door.

What then is my favorite idea within Go? It is … drum roll … the first letter capitalization of variables to indicate external visibility. With one elegant swoop it has eliminated the need for public/private keywords and made reading code easy. It provides a non intrusive, non thought-breaking, and very importantly, functional clue to the behavior of the variable. Of course, IDEs could provide differently colored variables to designate the visibility and scope of variables, but then it would depend on the IDE and also increase the number of color mappings we have to hold in our brain. There is both the “knowledge in the head" and the “knowledge in the world". Knowledge in the head is fast and efficient, but it takes much longer and repeated practice to get it there. Moreover there is apparently a limited memory we can hold for certain types of data. Then the best way is to visually represent itself in the real world. Exactly like the first capital letter (or not) to indicate external visibility (or internal visibility). Ding ding ding! Winner!

There is information in the world that we instinctively recognize (system 1 thinking, as per Daniel Kahneman’s book Thinking Fast and Slow) and others that we evaluate (system 2 thinking). System 1 thinking is instantaneous, automatic, effortless (imagine solving the problem 2+2 or having a conversation in your native language). System 2 thinking is more deliberate and blocks other mental resources (imagine solving the problem 33x27 or having a conversation in a foreign language that you are only partially familiar with). I doubt that the book says that explicitly and I have no data to back it up, so let me at least say that it seems practically difficult to do more than one system 2 task at the same time - can you do 33x27 at the same time as 41x39? Chances are that the average person will have to do them one after another.

A really functional design, in my opinion, should avoid requiring system 2 evaluation and would tie in design elements with one’s instantaneous system 1 expectation of the world.

If there is one neat idea that newer languages or even best practices for other languages will adopt from Go, the first will be the capitalization of variables to indicate public access. At any point in the code you can look at a variable to see its visibility. You don’t need to scroll up to the top of the page for the definition or hover over it for a second in a modern ide to bring up its definition in a popup. In fact, it is so elegant that it will appear automatically to you. That then, value at around zero cost, is a great idea and is numero uno on my list.

2 comments:

  1. It just so happens that I have been working to learn Go over the last few weeks and recently picked up Kahnemann's book (I'm maybe 1/3 of the way through).

    I'm not a programmer, but an engineer who sometimes needs to program. As such, it is difficult for me to train System 1 up for a complex language. I tried Java a decade ago, wasn't really happy with it, looked at C++ but there was too much to learn and then found Python - and soaked it up happily (until they added the metaprogramming nonsense anyway). Python let me do things I wouldn't have had the time (or maybe patience) to do otherwise, and other engineers that I exposed it to often felt the same way. However, seasoned programmers didn't seem to get so excited. It didn't impress them the way it did me, I think because the things I was happy to be able to do easily in Python they could already do in language X, and if they switched to Python, they would have become slower. They had already put in the 10,000 hours and had System 1 trained up.

    I on the other hand am not going to get there in a large and intricate language due to my part-time programmer status, but Go, like C (and like Python in it's younger days), is small enough for me to grok.

    A good tool is powerful but imposes a small cognitive load, does not require 10,000 hours for proficiency, and leaves as much bandwidth as possible to the actual problem domain.

    ReplyDelete
    Replies
    1. David, I think your comment/experience is valuable enough to warrant your own blog post. :-) Still, I am working on another article for a free online publication and your response and the reminder of the 'expertise at 10,000 hours' idea gave me an interesting phrasing of a point that was at the edge of my thoughts but eluding me. Thanks a bunch.

      Delete

If you think others also will find these tutorials useful, kindly "+1" it above and mention the link in your own blogs, responses, and entries on the net so that others also may reach here. Thank you.

Note: Only a member of this blog may post a comment.