1. 7

  2. 10

    I have not read the entire paper. Just the first 5 pages and the conclusion.

    I’d like to point out that there are significantly different ways for creating computer programs and this analysis seem to implicitly assume that the “static way” is the only way.

    In the “static way”,

    1. the programmers write large chunks of code in an editor (sometimes with some tests written beforehand),
    2. the code is sent to a compiler which help point out errors,
    3. if it compiles, the programs runs and the programmer observes the output
    4. the programmers makes updates as needed. Eventually adding other large chunks of code.

    (There are of course many variantions on this. Please correct me for a more accurate description.)

    In the more “dynamic way” of programming, a programmer is not only created in small pieces but potential new lines are tried out in the interpreter before deciding to add them or not. It is typically characterized by a short feedback loop.

    1. the programmers write a statement or line,
    2. this is sent to the interpreter,
    3. the programmer observes the result,
    4. make modifications and go back to 1 and/or add/keep some that line for the final program.

    Usually, there are lot of (language and IDE) features to make the 1-3 loop as fast as possible.

    In the Samlltalk IDEs, its possible to even run programs with mostly missing methods and Classes and fill them in at runtime (without ever restarting). To make such workflows possible, “superfluous” dynamic features are absolutely needed but will never be seen in individual codebases in the final product.

    The main reason I think this article assumes a strong static view is that they never discuss this aspect of dynamic languages (in the pages I’ve read).

    We started our analysis by looking at all 1850 software projects stored in Squeaksource in a snapshot taken in early 2010.

    They don’t look at dynamic feature use during the program creation phase at all, just the final product.

    One issue is that its always possible to program in a more static way in a dynamic language and IDE. And the see the lack of help from the compiler as a hinderance. In one never uses the dynamic features then it is easy to conclude they are a hinderance. But these features aren’t there solely for the purpose of being included in the final program.

    They found that the Python program in their corpus made a heavier usage of dynamic features during their startup phase, but that many of them also used some of these features during their entire lifetime.

    Of course, to perform any kind of study, some kind of assumptions need to be made. But they don’t say that this aspect is ignored to simplify the study.

    There are also things that can be done which can improve a language on one of the static/dynamic axis without regression on the other, especially at the beginning.

    As a final note, I’d like to mention one last use of dynamic features: to learn about a new module. I’ll usually read the high level readme of a new module and then immediately start playing with its objects in the interpreter without reading the documentation for individual classes and functions.

    Reflexive methods allow me to quickly find out what’s available and try things purely based on their names. I’ll send mock inputs to functions to try and figure out what their inputs and outputs are, observe the results and update my hypothesis about what they do.

    I find this gives me a much better and certain understanding of foreign modules and its a lot of fun to just poke around instead of just reading!

    Now I’m wondering if I should make a screencast of this.

    1. 9

      I completely agree with your point here, and I had the same reaction to the paper. I don’t program in Smalltalk anymore, but when I did, one of my favorite demos was what I called “debugger-driven development.” I’d start by just writing some code that would be what I wanted an API to look like–e.g., for a fortune program, maybe Fortune loadAll randomFortune–then execute DoIt, bringing up the debugger (since that class doesn’t even exist)–and then I’d add recursively add the missing methods until the original line completed. This leverages a whole swath of metaobject and reflective capabilities that the final code wouldn’t need, but without which, the entire Smalltalk development experience would be neutered beyond recognition.

      My other common demo was pretty different, but also did a great job using metaprogramming and reflective capabilities during development not needed in prod: I’d find a web API that was pretty cleanly designed and relevant to the audience I was speaking to. Next, I’d show how to write a kind of generic catch-all implementation via #doesNotUnderstand:, like what you might do in Ruby or Python. But then I’d modify it to generate the missing methods on-the-fly, and then (using a deliberately-made mistake in my first implementation) show how things like method modification timestamps and reflection could find the improperly-generated methods and regenerate them. (Sometimes, I’d even demo regenerating them as-needed with #perform: if I felt like it.) Finally, when we were done, I’d delete the #doesNotUndestand: implementation, customize a route or two, and be done. The final product didn’t use reflection, metaclasses, #doesNotUnderstand, or any of that kind of stuff, but the entire development process did. And unsurprisingly, a lot of the code for development did use things like self basicNew, foo perform: (a, b) asSymbol, and so on, even though the final wouldn’t.

    2. 2

      Interestingly, the ANSI Smalltalk committee viewed reflection as being used so rarely it was omitted from the standard:

      The vast majority of Smalltalk application programs do not utilize the reflective capabilities available in traditional Smalltalk implementations. For this reason, we view such reflective capabilities as artifacts primarily used in the implementation of incremental program facilities and do not mandate their presence in all Smalltalk implementations.

      They also refused to standardize the addition of new selectors to classes:

      Because symbols and selectors are defined as supporting different protocols and because the standard does not define any messages that generate selectors from text strings it is possible to build an implementation that can analyze the program text to determine which methods have selectors that are not used by the program.

      Taken together, this also removes from ANSI-standard Smalltalk things like metaclasses (which is also mentioned in the standard).