As promised, here is the first case study I did comparing the “stylings” of C# and Smalltalk. I used C# 1.0 code on the .Net CLR 1.0/1.1. I set up a programming problem for myself, creating a business object, and looked at how well each language handled it. I was inspired to do this by Hacknot’s “Invasion of the Dynamic Language Weenies,” (it has to be viewed as a series of slides) where he said there was no discernable difference in lines of code used in a static vs. a dynamic language, nor were there any advantages in programmer productivity (my response to his article is here). I figured I’d give it my own shot and see if he was right. Up to that point I hadn’t bothered to question my impressions.
What follows is the programming problem I set up for myself:
Create a program that records name, home address, work phone, home phone, salary, department, and employment class of employees. The program must store this information in some fashion (like a data structure).
On input, it must validate the department and employment class of employees when their information is entered. The departments are as follows:
The employment classes are as follows:
– MidLevel <- Management designation
– Executive <- Management designation
Workers with “Employee” or “MidLevel” class designations can be placed in Manufacturing, Sales, or Accounting departments. They cannot be placed in the Board department. Executives can only be placed in the Board department.
The program will restrict access to the employee information by the following criteria. “all access” means all employment classes may see the information:
name – all access
home address – MidLevel and Executive only
work phone – all access
home phone – MidLevel and Executive only
salary – Executive only
department – all access
class – all access
No elaborate keys are necessary. For the purposes of this exercise using the labels “Employee”, “MidLevel”, and “Executive” as “access tokens” will be sufficient evidence for the information store that the user is of that employment class, and can have commensurate access to the data.
Edit 10/18/2017: Here are the two versions of the project. I use DropBox to host the files. DropBox will say that the files cannot be previewed, but will display a blue “Download” button. Press that to download each file:
C#/.Net 1.x Employee test
Smalltalk Employee test
The C# zip file contains the test project I used.
The Smalltalk zip file contains the “file out” of the Employees-Test package I created, the test code (as a separate file), and the test output I got. It contains two sets of these files. The files in the main directory have been converted to use CR-LF for easy reading (by you) on PCs. They have the suffix “.txt”. The Squeak folder contains the files in their original format, which use LF as the end-of-line character This will be human readable on Unix-compatible systems, and within the Squeak environment. They have the suffix “.text” or “.st”.
For those not familiar with Squeak, the “file out” operation causes Squeak to create a single text file that contains the source code for a package, plus its metadata. A package is a collection of classes. The only code that a programmer would normally see in the Squeak environment are the class definitions, class comments, the method names and parameters, and the method code and comments. There’s some other code and comments that Squeak puts out when it does its file out operation. This is done so that when the code is read by Squeak (or some other Smalltalk system) in what’s called a “file in” operation, it can reconstitute the classes and their methods as they were intended. Normally code is accessed by the programmer strictly via. a “code browser”, which is the equivalent of a developer IDE within the Squeak environment. All classes in the whole system, including this package, are accessible via. a code browser. There’s no need to look up code via. directories and filenames. Code is accessed via. package name, category, class, and method.
The code that carries out the test for the Smalltalk version is included in a separate file in the zip, called “Employee test data.text” in the Squeak folder (“Employee test data.txt” if you want to display it on the screen on a PC). The test code for the C# version is included in main.cs in the C# project zip file.
I timed myself on each version, evaluated how many lines of code (LOC) it took to accomplish the task in each one, and I looked at code readability. I’ll comment on the other factors, but I’ll leave it up to you to judge which is more readable.
As I said earlier, the Smalltalk version came out slightly ahead in using fewer lines of code, despite the fact that a little more code had to be written for it to accomplish the effect you get with enumerations in C# (validating that a symbol–rough equivalent to an enumeration–is in the set of legal symbols). To keep things fair between them I did not count comments, or lines of code taken by curly (C#) or square (Smalltalk) braces. I also did not count test code, just the code for the business object and helper classes. Within these parameters I counted every line that was broken by an end of line character.
I wrote the C# version first. It came to 75 LOC, and took me 125 minutes to code, debug, and test.
The Smalltalk version came to 70 LOC, and took me 85 minutes to code, debug, and test. Another way of looking at it is 93% the LOC of the C# version, but I wrote it in 68% of the time.
A possible factor in the shorter time it took with the Smalltalk version is I wrote the solution first in C#. I can’t deny that doing it once already probably factored into the shorter time. I made a point, however, of not looking at the C# code at all while I was writing the Smalltalk version, and I wrote them on different days. Though I didn’t break it down, my guess is that debugging the code may have taken longer in the C# version. Since I haven’t worked in .Net for a while I’m a bit rusty. Despite having worked out the basic scheme of how to do it the first time, I was writing it in a different language. So I don’t chalk it up to me just repeating what I had already written.
This is my first crack at doing this. I hope to present more test cases in the future. Since I consider Smalltalk worth evaluating for real world uses, I think it should be evaluated seriously, which means taking measurements like this. Though this isn’t scientific, I’m doing this for me, to check my own perceptions. I just thought I’d share it with the reading audience as well. Something I’ll try in the future is writing a test case in Smalltalk first, and then in C#, and I’ll see if that has an impact on how much time it takes me with each. What I may also do is do future C# test cases in C#/.Net 2.0, just to be more current.
If you’d like to try out my sample projects:
I explain below how to run the Smalltalk and C# tests. Smalltalk first.
I wrote and tested my Smalltalk code using Squeak 3.8.1, from Ramon Leon’s site, onsmalltalk.com. I’ve tested it on the standard Squeak 3.8 version as well (which I got from squeak.org), and it works. Ramon has updated his public version of Squeak to 3.9, which still works with my Employee test package. So you can use any of these versions.
The best thing to do would be to unzip the Employee test files into the same directory as where you installed Squeak. My instructions below will assume you have done this.
Here’s a little Squeak primer. For those who are new, you’ll need this to try out the Employee test. These instructions will work on PCs and Unix/Linux machines. For Mac owners, I’m not sure how this would work for you. My guess is clicking the single mouse button would be equivalent to left-clicking.
When you run Squeak you will see a new desktop interface appear. It’s inside an application window frame supplied by your operating system. As long as your mouse stays inside this window, and the window has focus, most of your mouse and keyboard actions will be directed at objects and activities in the Squeak desktop space.
What follows are instructions for helper applications which you’ll be asked to open in the Employee test instructions (below), to load the necessary files, and execute the test.
File list – This is kind of like Windows Explorer. You access it by left-clicking on the Squeak desktop. This brings up what’s called the “World menu”. Within this menu select “Open…”. A second menu will appear. From it, select “file list”. You will see a new window open, which is the File list app. It has a top row which contains a text box on the left where filter expressions go, and then there are a series of buttons. Below this are 3 panes. The middle-left pane is the directory tree of the drive you’re running Squeak on. The middle-right pane is a listing of all the files in the currently selected directory. The lower, 3rd pane contains the text of whatever file is selected in the middle-right pane.
Workspace window – This gives you a text workspace to work in. You can work with code, and assign variable values within it, and it will keep them persistent for you (the variables won’t disappear when you’re done executing a task), for as long as the window is kept on the desktop. You bring up a Workspace by clicking on the right tab on the Squeak desktop (called “Tools”). You should then find the Workspace icon, and click and drag it onto the Squeak desktop.
Transcript window – This is like an active log viewer. It’s basically output-only. You carry out your tasks in the Workspace window, but the output (for this test) goes to the Transcript window. You bring up a Transcript window by clicking on the “Tools” tab. You should then find the Transcript icon, and click and drag it onto the Squeak desktop.
DoIt (action) – This is how you interactively evaluate an expression in Squeak. It’s a universal command. Anywhere, in any window on the Squeak desktop, where you have legal Smalltalk code, you can select it with the mouse, just as you would with text in your native operating system, and hit Alt-D. This will evaluate the expression, carrying out the instruction(s) you selected with the mouse.
Running the Smalltalk Employee test
Run Squeak, and open the File list. Go to the middle-left pane and click on the small triangle to the left of the currently selected directory’s name (this is the Squeak directory). This will expand its directory tree. Select the Squeak sub-folder (this came from the zip file), and select “Employees-Test.st” in the middle-right pane. You will see a button appear in the top row of the window that says “filein”. Click on this button. This will load the Employees-Test package into Squeak.
Click on “Employee test data.text” in the middle-right pane of File list. Click on the lower pane, where the text of this file is displayed, then press Alt-A, and then press Alt-C. Open a Workspace window from the “Tools” tab, and then press Alt-V. (Note that many of the keyboard commands are the same as on Windows, but they use Alt rather than Ctrl).
You should also open a Transcript window (from the “Tools” tab).
Select the Workspace window. Select and evaluate every line of code in the Workspace. You can do this by pressing Alt-A, and then pressing Alt-D. This will “select all” of the text in the window, and evaluate it, which will initialize the collection of Employee objects, and run the test. Look at the Transcript window. That’s where the output will be.
The employee class symbol (in the last line of the Workspace) is set to #Executive. This will output all of the input data to the Transcript window. You can change the employee class symbol (to #Employee or #MidLevel) to get different results. All you need to do hereafter is select and evaluate the very last line of code in the Workspace to rerun the test.
Running the C# Employee test
Unzip the project files into a directory, load the project into Visual Studio.Net (2002 or 2003), build the project, and run it. The output will show up in a console window. The test code is initialized to use the Employee.zClass.EXECUTIVE enumeration. This will output all input data. You can change the employee class enumeration passed in to emp.PrintUsingViewerToken() on line 178 of main.cs (to Employee.zClass.EMPLOYEE or Employee.zClass.MIDLEVEL) to get different results.
Edit 5/16/07: I’ve made corrections to the C# version. See my post here.