What Makes Smalltalk Unique?
Exploring the implication of software development without files
Smalltalk is not the first programming language centered on image-based development. In fact, image-based development was pioneered by the LISP programming language. However, Smalltalk is the language which has exploited all the opportunities made possible by image-based development.
By now, you wonder: What exactly is image-based development?
No, it does not mean you are drawing images to create programs. Instead, we use the word image to mean a serialization of data in memory. You can think of programming Smalltalk much like an interactive session in a read-evaluate-print-loop environment, or REPL for short. If you have programmed JavaScript, Python, Ruby, Julia, or Lua, you should be familiar with REPL-based development already.
Smalltalk takes the idea of a REPL development and supercharges it. A Python or Ruby developer may copy-paste individual classes and methods into a source code file for later usage. That means managing a collection of files and directories with source code. A Smalltalk developer does not do this. She will instead dump the whole REPL session to an image file. That sounds kind of crazy. How do you locate previously coded classes and methods to modify them?
The most similar experience to Smalltalk development you may have encountered in the past is working with an SQL database. You write SQL statements which modifies the state of your database. Usually you can bring back code written in the past defining tables, views and triggers.
Smalltalk development is centered on a very similar idea. You work in a graphical environment manipulating an object database containing you classes, methods and instantiated objects. In fact, the entire interactive environment, your IDE, is itself written in Smalltalk and part of that same environment.
Here is how it works: At the bottom you have a virtual machine (VM), which loads an image, which is basically an object database. This image contains the entire Smalltalk development environment itself. Through the IDE, which itself exists within the Smalltalk image, you perform actions which add more objects to the very same image.
The screenshot below is from a modern incarnation of Smalltalk, called Pharo. It shows a typical Smalltalk code editor. The leftmost pane of the window shows a list of packages. In the next pane, you have a list of classes defined within the package selected in the previous pane. The following pane shows method categories for the selected class. And finally the rightmost pane shows all the methods in the category selected in the pane to the left. In short it is a GUI helping you to drill down to the method you want to edit or read the code of.
The large lower part of the window shows the code for the currently selected method.
Keep in mind that this code is stored as data within a class object. It is not stored in a text file. Think of the code for an SQL trigger. Unlike a source code file you cannot scroll further down and see the next method. Each method is viewed separately, because they are separate entities.
So, what are the implications of storing class and method definitions in this manner? Why does it matter? What benefits does this approach give us?
It means that in a Smalltalk IDE has a full, always up to date, in memory representation of your code. Your classes are not just text but actual live Smalltalk objects you can interact with. Both you and the IDE can traverse all your classes, objects, and methods. It makes supporting method completion trivial. It is what gives Smalltalk IDEs such powerful refactoring tools. Doing things such as renaming a method or moving a method isn't a text substitution operation like in other IDEs. Instead, it is an object manipulation. You manipulate live objects.
The classes, methods and objects making up your development environment can be browsed in the development environment itself. Let that sink in. The IDE lets you modify the IDE. Because all modifications in Smalltalk are live there is no step where you recompile and restart the IDE. No, the changes you make take immediate effect. They are immediately observable.
You can change the behavior of existing IDE functionality or add new functionality. In fact, even the compiler itself is written in Smalltalk, so you can even change how your classes and methods are compiled. Now we are getting metaphysical!
This means that the first time you use Smalltalk, it can be a bit confusing. E.g. Pharo begins with a simple launcher program where you select the image to launch. This is natural. Otherwise, how would we deal with you screwing up your entire image, since that could mean your whole development environment no longer works.
Fortunately, Pharo has numerous tools for saving images, restoring them, resetting them and performing version control. Version control is interested in Smalltalk, since theoretically, there are no text files. So, how would you use for instance Git and GitHub with Smalltalk? In Pharo it is solved with a special Git manager called Iceberg, shown in the screenshot below:
Iceberg will export the Smalltalk image to a format Git can deal with. The Pharo solution is to turn classes into directories and store each method in a separate file. This approach allows you to use Iceberg to track code changes at the level of individual methods. Personally I think that is a really cool feature. It makes tracking changes at method level far easier.
It is important to understand that I am describing an export format. You cannot run Smalltalk code organized this way. Iceberg is used to import changes back from Git.
Image-based development gives plenty of interesting opportunities. You can for instance, store your image in the middle of a debug session, and later reload your IDE and resume from where you left off. Text file based development is limited to storing static properties. They cannot store the state of a program during execution.
You can also export the state of your debugger to a separate file. Furthermore, you can attach this to a bug report and let another developer pickup debugging where you left off. Pretty neat huh?
This story is part of a series of articles where I am exploring eight different programming languages and describing a unique feature or idea that each language exposed me to. While Smalltalk has many interesting ideas I am not covering here, I choose to focus on image-based development because that is what really separates Smalltalk from all my other programming experiences.