2020-04-10

Powerful tools, non-locality, and learning curves

Powerful tools can make you a more efficient programmer. Powerful languages provide abstractions, facilities for encapsulation, and syntactic sugar that helps cut down on interconnections and expresses what you want to do rather than how it should be done. Meta build systems reduce the hassle of providing cross-platform support. Code comprehension tools catch simple errors, support auto-completion, and support re-factoring.

But all this power is not without its cost. The same object oriented language facilities that provide encapsulation combined with easy access to super-class facilities means that you can't tell from the code fragment obj.feature() where you should look for the definition of feature().1 The notion of inheritance has introduced a degree of non-locality into your code: not all the behavior of a software artifact is necessarily defined in scope where the object is defined.

"We can solve any problem by introducing an extra level of indirection."
David J. Wheeler

I learned to program in a series of pure imperative languages (Basic, Pascal, C, and '80s era Fortran) plus a little assembly (which is the very antithesis of abstract and expressive). When I first started using C++, the non-locality of definition gave me fits even in the C-with-classes style of code I was encountering and producing.2 I'd read enough that I knew what I was suppose to be getting in return for my confusion, but I wasn't experienced enough to always realize the gains.

…except for the problem of too many levels of indirection
Anonymous commentary

You can imagine how appalled I was when I started bumping into slightly more sophisticated applications of object-oriented design (i.e. the gang-of-four "command" pattern) without any preparatory grounding in the techniques. Now the meaning was scattered over even more parts of the code base!3

I had a strong impulse to avoid those kinds of tools and roll my own solutions using the techniques I was familiar with, and sometime gave in.

But I was reading a little around the internet and bits were sinking in. I started reinventing some of the basic principles (and reinventing all the ways to screw up, natch). And of course, having "thought of it" myself I could appreciate the reasons better. That's one way to climb the learning curve and it has its advantages if you have the time, but I suspect that a more organized (or even formal) approach is generally better.

In any case, the point is that powerful tools can seem like a step backward until you get to know them.

GUI designers


Now consider GUI designers in general (and Designer component of Qt Creator in particular). They are powerful tools that can write a large volume of repetitive boilerplate code for you. And one of the specific features that Qt Creator provides is the ability to plumb together the signals and slots of multiple components that appear in a single form.

Which is great, but it means that there is a new place to look for information about your program (in the form designer view or in the generated code). And for the signals/slots feature of Qt you have to look into a specific view as that stuff doesn't show in the design view.

So you end up with part o the description of your widget in the class you write and part in a generated file which you can read but isn't really intended for that. And to find the data about the generated code in a form intended for your perusal you have to look in a different tool than your text editor (and a complicated tool at that). Non-locality writ large.

All in all, it's not surprising that one of my team members is resisting using the designer; not withstanding that (as far as my searches about the web can tell) most experts suggest using designer tools when practical rather than hand-tooling your GUIs.4




1 Though of course it is another powerful tool (the code comprehension facilities found in IDEs) that eases the burden.

2 I didn't help that I was using bare emacs without even the very basic code comprehension tools that were available for the editor at the time. Not so much as ctags.


Closeup of the Hunt–Lenox_Globe showing the legendary legend. Due thanks to Wikipedia.
3 Not withstanding that the familiar C library functions bsearch and qsort work on similar principles. But at least the presence of function-pointer served as a clear warning in C. In an object oriented context this stuff can sneak up on you as it only requires the combination of polymorphism and either reference or pointer members (polymorphism is equivalent to function pointers of course, but it doesn't look like them).

4 Mixing some hand tooled code and some generated code in the same project is, in my opinion, generally worse that choosing either case and sticking to it. If only because now you can't even anticipate which search path you will have to follow and you have to know all about both ways of finding stuff.

No comments:

Post a Comment