Smalltalk’s Productivity
medium.com
medium.com
As a Smalltalk programmer I certainly agree with having an increased productivity when programming in Smalltalk. But in my opinion this does depend less on the language and much more on the development environment. Having worked with multiple Smalltalk-like environments for JavaScript I can (anecdotally) report the same kind of productivity for programming in JS.
I think the right tooling around a PL influence productivity a lot, maybe even more than the language itself. Of course, certain tooling features depend on meta interfaces of the programming language and its runtime.
[1] https://en.wikipedia.org/wiki/Function_point
[2] page 9, http://www.ifpug.org/wp-content/uploads/2017/04/IYSM.-Thirty...
Static entities such as classes and methods (and depending on your Smalltalk implementation namespaces and object versions) can be modified at runtime, i.e. while your program is running you can make a change and get an immediate effect. This is now known as "live" programming, however, it is notably different from your typical "hot reload" implementation in that it knows how to apply changes for individual code entities. E.g. if you modify a method you don't need to reload the entire class or module or entire runtime. For me, this feature alone makes for a big productivity increase.
Dynamic entities such as stack frames can also be reified by the meta interface. This allows to inspect and modify runtime processes, e.g. inside a "debugger" [3]. Note that the debugger allows to modify and create new code while your are debugging. This is a powerful feature because it means that you get access to runtime objects inside of it. Ever wondered what object gets passed into your method at a certain point, what methods it knows, what properties it has? Just try it out and see for yourself!
An interesting analogy to describe this experience: [4].
For a deeper description about the ideas behind that see Design Principles Behind Smalltalk [5].
Also, most Lisp implementations provide the same kind of meta interface, and CLOS arguably provides a more flexible and higher level abstraction of these ideas [6].
As for similar environments I have worked on, there is Lively for JavaScript [7] and cloxp for Clojure [8]
[1] http://sdmeta.gforge.inria.fr/FreeBooks/ByExample/31%20-%20C...
[2] Chapters 16 http://stephane.ducasse.free.fr/FreeBooks/BlueBook/Bluebook....
[3] https://www.youtube.com/watch?v=1kuoS796vNw
[4] http://simberon.blogspot.nl/2013/01/swimming-with-fish.html
[5] https://www.cs.virginia.edu/~evans/cs655/readings/smalltalk....
Then it's not static.
What's with kids again not knowing basic computer science?
Another thing you can do that isn't explicitly mentioned above is "dropToFrame" where you can point to any one of the calling methods out of the call stack and have the process revert to a state so it is like it only just entered that method. I occasionally have debugged bugs that only surfaced rarely simply by having a tester call me when the problem manifests, and I spent a few hours with that function call live, repeatedly taking runs through to see what happened then reverting to a state where the problem was about to manifest but not so early that everything was lost.
You can also write debugging code of arbitrary complexity. You could write a 20-line query to do consistency checking of some data structure that is being operated on to satisfy yourself of various things you assume are true. You can make a special debugging subclass of some ubiquitous class, tell one particular instance of the class to become of the subclasses type which will then do all sorts of extra bookkeeping (perhaps recording stack frames every time it is invoked to see who asks it to do things).
You can execute a windowUnderMouse call to get an inspector on whatever widget is under your mouse pointer to make sure that the button you are looking at is in fact the one you think you are looking at. I used this to find a problem once where someone had subclassed some complicated window to add some functionality, and one of the buttons didn't work any more: turned out they were creating the same button again in the subclass constructor, which was overlaying the original's button (the one with all the event handlers).
I think some of this stuff might be more common in other languages now, but it wasn't in the mid-nineties. I know Java had a limited version of drop-to-frame a number of years ago, but it had some pretty cramping restrictions.
I don't think that's the case.
For one, the design and semantics of the language and overall environment force you to understand this and leverage those kind of features.
Second, Smalltalk being a niche language, it attracts programmers for its particularities and overall merits, and those are more likely to know and leverage those things than not. It's not like random corporate programmers are told to use Smalltalk and they use it like a C or Java. It's programmers who have sought after Smalltalk against the current trends that are using it today, and those know very well what it is.
I had to learn the interactivity stuff from people at the other company, which was staffed by people who'd been Smalltalk programmers for quite a while, and also people who had experience with other dynamic languages, particularly Common Lisp. That was where I really learned how to do the interactive stuff I mentioned above.
You might consider Smalltalk niche now, but in the short period of time before Java came around, it looked like Smalltalk was the future of enterprise computing. That is the period I am specifically talking about.
Imagine that your hot code replacement is also possible at any level of the JVM or CLR.
Would you expand on this? From a theoretical standpoint I can see how reloading only a single method could be more performant (and therefore more productive) than reloading an entire class or module. From a practical standpoint, if reloading a method ends up reloading a class or module to effect the reload, is there a noticeable difference or improvement? Or am I just misunderstanding?
(I happened to have spent part of day looking at cloxp and lively. Nice to come across you here as well. Nice work!)
I think that what the OP must have meant about this was that you can update a method without interfering with the program's current state, so while at a breakpoint say, you can fix a minor bug or perhaps add some debugging code or whatever, then resume, and all subsequent invocations of that method will use the new definition.
If the business functionality being provided is "deliver networked application to customer" then JavaScript would probably do well. If it's "create 3D rendering engine" then other language orderings are likely. How can you normalize the fact that different languages are appropriate for different domains? Do you have to come up with numbers that compare the business value of very different tasks.
There's nothing that makes Javascript especially appropriate for web apps, except for the fact that it's bundled as the default and only language on web browsers.
So there's always that. Such accidents of history play more important role on what ecosystem and thus perceived suitability a language has, than the language's own merits.
Judged purely on language merits, Smalltalk would have made an excellent language for web apps and more over JS.
Languages and runtimes can't be separated, because you can't just transplant a language to a different runtime and maintain the same experience.
Still a damn fine language.
That said, I don't think it's necessary to drop the standard library to make Smalltalk a web language, nor that it's "important that JavaScript never really had one".
It would have been much better if it came with a better "batteries" for all basic stuff (parsing urls, string manipulation, making requests, etc) from the start.
Ditto for the image -- one could very easily have web images, in fact that's part of what WASM would eventually achieve.
- Amber Smalltalk provides a Smalltalk layer on top of JavaScript: http://www.amber-lang.net/
- Indium adds JavaScript tooling support and runtime interaction to Emacs and brings a few Smalltalk features such as object inspection (the project creator and maintainer is a Smalltalker and author of Amber): https://github.com/NicolasPetton/indium
- Lively provides a Smalltalk-like environment (code browsing, editing) as well as object(-graph) persistence, similar to the Smalltalk image idea, and mixes in some ideas from Self: http://lively-next.org/
Lively's meta interface is separately usable via lively.vm and lively.modules: https://github.com/LivelyKernel/lively.vm https://github.com/LivelyKernel/lively.modules
[1] http://www.ifpug.org/wp-content/uploads/2017/04/IYSM.-Thirty...
I recall many VBA projects where I was flying along using my favorite toolkit / framework for a specific domain, until we hit something that wasn't "in the manual" - at which point, peering inside the beast became very hard. So 30% of time spend cranking out useful code and 60% of the time spent clearing some arcane roadblock because a client wanted something that didn't neatly fit the standard.
Python's standard library has always seemed much more flexible (and when necessary, comprehensible) in comparison...
Forth — 14,636
Haxe — 14,636
Lisp — 14,636
C++ — 12,697
Go — 12,697
Java — 12,697
PHP — 12,697
Python — 12,697
I wonder, is there a technical term for this bullshit practice of using pointlessly large numbers to make your measurements appear more accurate and detailed than they actually are?
Because if their metrics actually carried five significant digits' worth of information, there's _no chance in hell_ seven vastly different languages could share two scores.
Rank 1/Asm 6/C 26/Lisp 65/Smalltalk 78/Excel
Javascript productivity is likely incredibly variant as you have such a diverse set of tools/libraries/build-systems within it. At the top end you have people using async/await, Typescript, hot reloading, and a litany of libraries and patterns they have learned over years, test suites that encourage writing more tests more easily (Jest, Ava), and huge downstream efforts in tooling like the recent profiling improvements in Chrome devtools or profiling/errors in React.
In the end my best guess at what roughly equates to real-world productivity ends up being much more centered around the following metrics:
- Richness of developer debugging tools
- 3rd party library maturity
- Online community, documentation, examples (chat + q&a)
- Ability implement better design patterns easily
- Type systems
- Feedback loops (hmr, auto-restart, easy package writing)
Further, lines of code is a poor metric for effectiveness. As an example in JS, I much prefer a more explicit, less functional, and more spaced out style of code as it is really quite easy to read and debug and in effect takes no more time to write than the more dense functional style.
Caveat: I only skimmed the attached paper, but writing these thoughts to provide a counter to what I assume is the claim there.
That's one of the central arguments of the paper. The metric it uses is not LoC, other than as a comparison to other metrics.
Capers Jones measures these things in a fairly sophisticated way, and has been working on it since the late seventies. Spend some time and read his work before making these surface level comments that are refuted directly in the source.
The bulk of your argument is valid, but it's by definition included in what Jones' calculates as "productivity". It's a enormous red flashing light that says "I didn't read the linked references".
But it did give a different model of the world from a programming point of view.
For example if you're using c++ to implement an interface for some hardware then maybe you can just quickly follow a spec. But with lisp you're more likely to try and implement some sort of ai thing that requires a lot of stopping and thinking.
With respect to community size, if you have a bunch of people then you're going to get more accurate numbers but if you have a small community then you might end up with a lot of outliers.
Finally people are probably more likely to have a significant amount of practice with c++ vs lisp and that probably has an impact.
Then again, maybe we should use data to inform our opinions (inform, not determine), rather using our opinions to filter out data?
Take the number in table 16 from the cited paper for LISP. There is no explanation what this LISP actually is and what projects the 'data' comes from. One finds the same data in papers from two or more decades ago. There FLAVORS, an OO system from Lisp Machine Lisp from the 80s, gets a much different value. CLOS, the OO system of Common Lisp, gets another one.
These tables were in part computed/guesses from language variants which were looked at decades ago.
Thus without qualifying the numbers, the tables are for many languages just nonsense. The data behind it is weak and the conclusions are on shaky ground. This amounts to pseudo science.
As for your syntax error woes, I don't recall ever running into a massive issue like that, but then again by the time I was working at this company they had decades of time to figure out a stable MUMPS dev environment and even an internal IDE for it, and for the most part they seem to have succeeded. I still wouldn't say I like MUMPS; if it had first class functions and the ability to use an entire tree as a return value (or at least a pointer of some kind) rather than only the value of the root node then I'd probably say I like it.
e.g. Smalltalk, and many of the other languages that scored well, are generally older languages that aren't super-popular or trendy. e.g. Perl scores very well, much better than one would expect given the reputation Perl has (which I think is somewhat unfounded, but I'm in the minority in thinking Perl is a pretty good language for programming in the large). While Python scores relatively poorly, despite the fact that many consider it a very good language on most of the metrics this kind of ranking ought to reflect. Perl is used almost exclusively by old coders with a ton of experience, Python is relatively trendy and has a lot of new programmers working in the language. JavaScript is a perfect storm of newbies with little experience writing gazillions of lines of code, seeming to further support my theory; I'd wager there are more programmers with <2 years programming experience working in JavaScript than any other language, and probably a higher percentage with no formal programming education, as well.
Smalltalk, is, of course, an old language with a lot of old and experienced programmers working in it. Not many new programmers are taking up Smalltalk.
It seems almost as if this one thing can explain the ranking, or at least a big percentage of the difference. Even if they controlled for experience with the language, they may not have controlled for programming experience in general...which is, I think maybe even more relevant to the results. The best Python programmer I've ever worked with was a Java programmer for years, and hadn't really worked with Python at all until a year or two before I met him. Smalltalk people have been around. MUMPS people have been around. Perl people have been around. Eiffel people have been around. (Many of the languages that ranked high are also used in specific, stodgy, industries where the reliability requirements are very high...medicine and finance, for example. Those industries favor experienced programmers with credentials to back them up.)
There's occasionally studies about average developer salaries, as well, and they look a lot like this list, even though they seem to imply it's the language that's setting the price, I think it's the experience and age of the coders working in them. (And, based on this and other studies about relative productivity, the old timers pushing up the average salary for those older languages are probably still underpaid.)
In short: Is this really measuring the language or the programmers working in those languages? (It probably doesn't matter for the people reading this study, as they just want reliable software developed quickly and within budget, and choosing a language that scores well might get them the developers that make reliable software quickly within budget. So, cause and effect might be matched up so closely that it doesn't invalidate the study for it to actually be about the programmers rather than the code.
But, maybe they did cover this variable and I just haven't read deep enough to see it; I've only skimmed the paper, so I could be talking nonsense.
The answer is: where are the accomplishments?
Show me the Kafkas, the Cassandras, the Hadoops, the Kuberneteses, the nginxes, the jettys, the (a myriad of other projects)s.
After literally tens of years of claiming/boasting that they are the best, and that other languages suck, I’ve yet to see any of these claims turn into anything but empty posturing.
Quite often they are simply stuck with those languages. Because a non-IT manager got some consultants who promised them 100x results for 1/100 money.
As research/test beds these languages are rather invaluable.
Their other values are frankly overrated.
According to James Gosling, Java's object model is entirely based on Simula (http://bit.ly/2xc1XTA) and the concepts it introduced:- objects, classes, inheritance and virtual functions. Smalltalk's main differentiation in terms of object-orientation:- "messaging between objects, all the way down", is not reflected in major modern languages, other than perhaps Ruby.
Which system?
[1] http://www.cincomsmalltalk.com/main/successes/
[2] https://techcrunch.com/2006/03/11/dabbledb-online-app-buildi...
The financial world has a ton of Haskell.
Smalltalk has its successes but most of them are in the past.
Yeah, yeah, yeah. AXD301 is the only thing that keeps E going. It was the poster child 20 years ago, it still is the poster child today.
Quite sad if you consider Erlang's claim: Build massively scalable soft real-time systems.
Hint: you can't build a massively scalable system in Erlang any easier than in any other language. For reasons see the RELEASE project
> The financial world has a ton of Haskell.
The financial world has much more than a ton of other languages.
> Smalltalk has its successes but most of them are in the past.
Indeed.
With respect to Smalltalk: there's a long history of superior technologies losing the market to inferior technologies. The fact that it got displaced by Java is not really much of a criticism.
Why though? A one-time wonder that gets displayed as the project for 20 years hardly constitutes a proof.
> losing the market to inferior technologies. The fact that it got displaced by Java is not really much of a criticism.
I keep hearing about these inferior technologies. However, the only ones talking about "inferior technologies" are these marginalised languages that are so full of themselves: Smalltalk, Erlang, Haskell...
It comes down to a very simple thing: these languages are supposed to be superior to basically anything else. And yet... There's hardly anything made/built in these projects that can show the world that these claims are true. Except maybe some closed-source business cases. Having been on the inside of one of such a case, I now take these stories with a grain of salt the size of Jupiter.
OK, so you can't.
> marginalised languages that are so full of themselves
Ok, now your axe-grinding is clear to me.
Even if I can't, the success of AXD301 has never been replicated, has it? So it's rather a one-off wonder than something indicative of the platform's strength.
For the past 20 years Erlang has been advertising itself as the language to create distributed and scalable services, microservices etc. In 2018 if you really want to build something like that, you are much better off grabbing off-the shelf Java components because there are literally zero tools available in Erlang, and you will have to implement every single thing from scratch yourself.
While Erlang was busy boasting how great it is for distributed/parallel computing, and how other languages suck, other languages and platforms (primarily Java/JVM) caught up with it, and then surpassed. While Erlang stood in one place never moving forward.
Message switches (Twitter for instance), queuing systems (RabbitMQ) and so on all use Erlang under the hood.
Erlang and Java compare as apples to oranges.
The reason why Erlang to your perception has not moved forward is primarily because it was very good to begin with and because changes are typically incremental rather than revolutionary.
Despite Erlang's and Erlang community's claims to how good the language is, it is not that good.
While Erlang (and it's community) where telling everyone how far ahead in the future it is, other languages and platforms (especially JVM) have caught up to it, and moved way past it.
It's nearly impossible to implement anything on par with Hadoop, Kafka, Kubernetes, <countless other distributed frameworks/tools/libraries etc.> in Erlang because for every little thing you can think of you need to build it from scratch. Even Erlang's claim "build massively scalable distributed apps" is a sham: out of the box it cannot handle more that ~80-10-ish nodes[1]. In today's world Java (and Go, increasingly) trumps Erlang in nearly every aspect and claim Erlang might have.
There are so few and far in between systems that use Erlang under the hood that it leads me to believe they are mostly flukes and isolated tales of success than proofs/representations of the language's strength.
[1] For reference, see RELEASE project. Also, http://www.dcs.gla.ac.uk/~amirg/publications/DE-Bench.pdf, https://arxiv.org/pdf/1704.07234.pdf etc.
Our website runs on 75 nodes, with geolocated microservices, distributed database access, log aggregation, metrics, parallel deploys, etc. etc. etc. It's a huge overkill, and we're gonna scale it down :) But it was just so easy to do it. All in Python, Java, and PHP (!).
In all of Erlang's ecosystem you couldn't find a collection of tools that let you do 10% of that. And you would have to start with writing your own distribution layer on top of Erlang to handle those 75 nodes in three geographical regions.
Anyway, it looks as if you have made up your mind and no matter what examples I put forward you have your reasons for ignoring them so thank you for the exchange.
Let's head on to erlang.org, shall we?
"Build massively scalable soft real-time systems... Erlang is a programming language used to build massively scalable soft real-time systems with requirements on high availability... OTP is set of Erlang libraries and design principles providing middle-ware to develop these systems."
and so on and so on.
Half-truths at best.
The cost, C, to create app, A, that generates income I, varies with the pool of talent that will actually do the work. Also, consider the entropy of the system A targets, the C to modify A, and the time value of I. Once complete, if your org can live that long, if your A is faster, higher quality, more pleasurable to use, more cachet, more media coverage, more support, more money, more envy than a set of competitors, then the language it's written in becomes the next hot thing--if the word gets out.
Anyway, the ability for a junior programmer to pick up the code, create valuable improvements and grow with the organization (a super-specialized language requiring continual self-training is counter to that quality), and be productive, is a very important factor sometimes. So output can include very many, different things.
Function points may correlate to lines of code. If that's the case, then also consider the lines of code does not necessarily correlate with output. For instance, having to guess the correct search term to find the library you are needing to write that one line also takes time. Making sure the version of the library you are using plays nice with other libraries, the language syntax targets the version of the compiler, interpreter, hardware, architecture, platform, kernel, and standards also impacts output.
It is an interesting attempt to measure productivity with function point analysis. But, and you knew that was coming, there are so many more factors involved before you it is justifiably reasonable to draw a conclusion on productivity of a language.