Another Take on Design Patterns

Posted by Rick DeNatale Tue, 19 Jun 2007 20:48:00 GMT

<iframe align = “right”, src=“http://rcm.amazon.com/e/cm?t=denhaven2com-20&o=1&p=8&l=as1&asins=0201184621&fc1=000000&IS2=1&lt1=_blank&lc1==E50707&bc1=000000&bg1=FFFFFF&f=ifr&npa=1” style=“width:120px;height:240px;” scrolling=“no” marginwidth=“0” marginheight=“0” frameborder="0">

Most programmers these days are familiar with, or at least aware of the now classic
“Gang of Four” book Design Patterns: Elements of Reusable Object-Oriented Software.


One of the recurring arguments about design patterns is how they relate to individual programming languages. The “Gang of Four,” Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, were by majority, proponents of strongly typed languages. Ralph was the sole representative of Smalltalk and the rest of the dynamic object oriented languages. As a result, The GOF book had and has more resonance with the C++ community and it’s successors. Although there
are some Smalltalk examples in the book, many of the patterns express things which are easier, and in some cases
unnecessary to express in a dynamically typed language. I find this a bit ironic, since the whole patterns movement
seems to have started when Ward Cunningham and Kent Beck, two of the best known Smalltalkers, discovered the work of architect
Christopher Alexander and thought that his approach to building and municipal design could be translated to the
design of software.


As I was browsing today, I was reminded that there is another “Design Patterns” book,
“The Design Patterns Smalltalk Companion” by Sherman Alpert, Bobby Woolf, and Kyle Brown.
Which might be of interest to not just Smalltalkers
but also Rubyists, since it approaches the subject from they dynamic language point of view. It’s not easy to find, but Amazon has a few copies in stock.


Sherm was one of the researchers in the IBM User Interface Institute
which was housed in the same building where
John Vlissides and Richard Helm of the “GOF” worked,
the IBM Watson Research center in
Yorktown Heights, NY. I spent quite a bit of time with Sherman and the rest of the UI institute team under John T.
Richards back in the late-1980s to early 1990s.
Bobby and Kyle were OO consultants, who I also knew through Knowledge Systems Corp.


You never know what you might learn from the old Smalltalkers.


Die Hard?

Posted by Rick DeNatale Tue, 12 Jun 2007 15:24:00 GMT

At the last meeting of the Agile RTP group, I won Michael T. Nygard’s book Release It! which I’m reading as a background task. This morning I ran across this:

Interpreted languages such as Java and Ruby almost never crash. Sure they get application errors, but it’s relatively rare to see the interpreter or virtual machine crash. I still remember when a rogue pointer in C could reduce the whole machine to a navel-gazing heap.

I remember “back in the day” when there were endless arguments between the C++ and Smalltalk advocates. The C++ folks would often quote Bjarne Strroustrup’s fear of flying in an airplane whose flight control system was written in Smalltalk, and threw a “message not understood” exception.

Those of us in the Smalltalk camp found this amusing, since the alternative was a system crash caused by an invalidpointer.

Now maybe Nygard framing rogue pointers in C as a memory means that the problem has been solved, but I seem to recall having seen it recently.

It’s Not Just The Language Stupid

<iframe align = “right”, src=“http://rcm.amazon.com/e/cm?t=denhaven2com-20&o=1&p=8&l=as1&asins=0978739213&fc1=E50707&IS2=1&lt1=_blank&lc1=E50707&bc1=000000&bg1=FFFFFF&npa=1&f=ifr” style=“width:120px;height:240px;” scrolling=“no” marginright=“0” marginheight=“0” marginleft=“8” frameborder="0">

One point here is that pet-features such as strong vs. dynamic typing or garbage collection vs. allegedly more performant1 manual memory management aren’t panaceas. They can have a major effect on aspects such as easo of development, or tweaking out the last bit of performance, sometimes in non-intuitive ways.


Making robust software requires more than just choosing a language, it requires craftmanship, adherence to best practices for the chosen language(s) and technologies, and a realistic understanding of the challenges at hand.


Release It!


And that’s where we come back Nygard’s book. Although I assume that most of my readers are Rubyists, and Nygard is a Java guru, there is much of value here for anyone concerned with producing robust software that can stand up to the real world.


Based on what I’ve read sofar, and skimming the rest, I can recommend it. If you’re interested you can buy it directly from the Pragmatic Programmers, or via the amazon.com link. The later would help feed the duckdogs who run this site, and lower my distraction from their gowling stomachs.

<a name=“fn1 href=”#fn_ref1">1 The “allegedly” will no doubt be explained in further posts here.


Ruby Extensions vs. Smalltalk Primitives

Posted by Rick DeNatale Mon, 04 Jun 2007 14:16:00 GMT

One of the ways in which Ruby differs from Smalltalk is in how much of the implementation is buried in C, which forms a barrier for deep understanding.

For the purposes of this article, I’m going to use the term extension a little loosely to refer to both core library and extension code written in C.

For example, in Ruby, much of the code which implements core classes like Array, is implemented by C code. This is good for performance, but for those with a need or desire to grok the code, not so much. In contrast, Smalltalk has a large brigade of Collection classes which are written in Smalltalk.

This is not to say that Smalltalk doesn’t use the equivalent of extensions. Smalltalk calls them primitives.

There are some interesting differences which might be interesting for the Ruby Core team to ponder, if they haven’t already.

Smalltalk primitives

In Smalltalk-80 and it’s descendants, primitive methods are implemented in a low-level languages like C or Assembler. They are attached to normal Smalltalk methods by a special syntax. For example, here’s a simppet from the Smalltalk-80 Blue Book, this is a method definition for the + method in SmallInteger (Smalltalks analogue to Fixnum in Ruby:

1: + addend
2:   <primitive: 1>
3:   ^ super + addend

The Smalltalk compiler turns method code into CompiledMethod objects which contain the bytecodes implementing the smalltalk code along with other information such as where to find temporary variables. In the case of a method such as the bytecodes would be something like:

   push self
   push addend
   send_super #+, 1  // invoke the inherited + method with 1 argument 
   return_top_of_stack

These are the bytecodes to implement line 3.

The effect of line 2 is to mark the compiled method as being associated with a numbered primitive. A Ruby implementation of a Smalltalk VM might have code like this.

Module VM

  class CompiledMethod

  def execute
      begin
        return exec_prim if has_prim?
      rescue PrimitiveFailed
      end
      return VM.interpret(byte_codes)
  end    

So the idea is that, if a compiled method has an associated primitive method the VM executes it. If it succeeds then that’s the end of this method invocation. If it fails then execution falls through to interpret the byte codes.

In the case of the method we are considering the primitive suceeds if the argument is also a SmallInteger, and the result doesn’t overflow othewise it fails. This allows primitives to quickly handle the 80% cases, and fall back on high-level smalltalk code for the more complicated cases.

User Primitives

Later Smalltalk implementations such as Smalltalk/V and IBM/Smalltalk allowed user written primitives. These were usually referenced by namerather than a number. The same flow allowed fallback to Smalltalk code on failure of a user primitive, either for error recovery, or for balancing implementation complexity against performance.

Ruby Extensions

In contrast, Ruby methods are either wholly normal Ruby code, or wholly extension methods written in C functions registered using ruby api calls like rb_define_method. These methods are somewhat invisible to the ruby programmer. This can be confusing, particularly when you are trying to read code which is partially implemented in C and partially in Ruby. Just this morning I was trying to debug somebody else’s code which was using the eventmachine gem. Looking at the source for eventmachine showed methods being invoked with no definition visible in the ruby source. These methods actually live in a C extension to the class.

Could Ruby Use Something like Smalltalk’s Primitive Methods?

It might be nice if this could be made visible using a mechanism like Smalltalk’s primitive not only to document such cases, but as a way to do th ekind of complexity/performance balancing I’ve described.

It might be interesting to think about combining this with the ideas behind ruby-inline, and to allow the primitives to be written in-line as well. The difference I would see would be the introduction of the idea of failure/recovery and better support for usage of the ruby.h api inside the inlined primitives.


Just a thought.

Postscript – Related Technology

Although I consider the Smalltalk primitive idea as something which might be added to Ruby, Smalltalk and related languages have added more modern techniques for moving the implementation of the core up into the higher-level language.

Squeak smalltalkUses a language called slang (not tobe confused with s-lang), as the source language for the Squeak VM. Slang has a Smalltalk-like syntax but it is easily translated to C. Squeak user primitives are written in slang as plug-ins.

Evan Phoenix’, Rubinius started out as a Ruby VM being written in Ruby or a slang-like language with a ruby-like syntax, but it seems to have changed tack to use a handcoded port of Evan’s earlier Ruby code to C. This ported VM is called Shotgun. Shotgun seems to be taking an approach quite similar to the original Smalltalk-80 numbered primitives to implement the functions of the ruby standard library. I don’t beleive that they are using the primitive failure with fallback idea though.

Java has the Java Native Interface (or JNI) which is similar to ruby’s extensions in that it provides a c-API to the JVM. It differs from Ruby in that Java classes must have declarations of any native functions they provide and are responsibole for loading the load library containing the binary.

I must confess that it’s been a few years since I stopped keeping up with Java evolution, so there may be new things in Java in this area.

An interesting historical sidenote is that the original VisualAge for Java which was written before the advent of JNI used what was called the “UVM” or Universal Virtual Machine. This was a version of the IBM Smalltalk VM extended to support both Smalltalk and Java bytecodes. The UVM used Smalltalk as the language in which Java native methods were written. When Sun came out with the JNI, with requirements for C language primitives, VA/Java moved from a Smalltalk VM to either the Sun or IBM JVMs.

After Dave Ungar cut his teeth (and earned his PhD) working on the UCB implementation of Smalltalk-80, he took on the challenge of implementing a dynamic language completely in itself in the aptly named self language. The philosophy behind self abhored statically optimized techniques, including prmitives written in a low-level language, in favor of dynamically optimizing code at run-time. This was the genesis of the JIT and HotSpot approaches commonly used in Java. It was also the basis of the Strongtalk project which saw members of Dave’s self team taking some of the ideas from Self back to a Smalltalk implementation.


Power, Responsibility and Tricksy VM Implementers

Posted by Rick DeNatale Thu, 15 Mar 2007 12:05:00 GMT

In a ruby-talk discussion of the pleasures and perils of adding to or changing core ruby classes. A practice denigrated as “monkey patching” by some, but embraced as a powerful technique, when practiced with care, by others. Someone just reported an experiment involving changing a basic core method:

 Fixnum.class_eval do
   def +(number)
     self - number
   end
 end

The result: It blew up his irb.

Ruby certainly gives a lot of power. A little, and in some cases a lot, more than most popular OO languages. Read on..

Dave Ungar, who analysed and ‘optimized’ the Berkley implementation of Smalltalk-80 for his PhD dissertation, and then went on to invent the Self language used to go around and try to torment Smalltalk implementers by asking them to add an instance variable to the Object class, something which either was disallowed or would blow up. Keep in mind that Smalltalk is a dynamic language like Ruby and such changes happen while the code is running.

Ruby survives this test. Actually, it redefines it in a way similar to the way Self did. In Smalltalk, and most OO languages, instance variables are declared in classes and the classes define a template for the memory layout of the classes instances, a given instance variable is kept in a slot at a known distance from the beginning of the object. When a class is redefined all it’s instances, and the instances of all it’s subclasses need to be re-mapped.

In Ruby, classes in general don’t actually know about their instances instance variables. Instance variables are represented as an individual hash which maps the instance variable name to its value. The instance variables only come about when an instance method is executed which defines it by mention. This means that you might well have two instances of a class, one of which has a given instance variable and one which doesn’t.

This highly dynamic nature of ruby gives it a great deal of power which is put to use by advanced Rubyists and leads to nice results like Ruby on Rails.

With great power comes great responsibility!

Tricksy VM Implementers

It might be the case in some future implementations that patching FixNum#+ might be ineffective, or intermittently effective.

For example, some Smalltalk implementations, would handle a + b under the covers as an integer add of the two object pointers and a little adjustment, followed by a quick check to see if the result were a fixnum, and only send the + message if it wasn’t. This check can be done relatively inexpensively due to the way in which references to FixNums (or SmallIntegers as Smalltalk called them) are encoded.

If a number x is in FixNum range, i.e it’s twos-complement representation will fit into a bitstring of length one less than a pointer, then it’s encoded as a ‘pointer’ with the binary value x*2+1 This means that, if the low-order bit set it’s a Fixnum otherwise it isn’t. So if we have two object pointers xp and yp, referring to the objects x and y respectively we can implement x + y as something like this pseudo-C code:

   result = xp + yp - 1;  
   if (arithmetic overflow || !(result && 1) ) {
        result = send(xp,:+,yp)
   }

Note that, if xp and yp refer to Fixnums:

   xp + yp - 1 
   = (x*2+1)+(y*2+1) - 1 
   = x*2 + y*2 + 1
   = (x+y)*2 + 1

which is the correct representation for the FixNum x+y

If we don’t get an overflow, and the low-order bit is set when we compute result, we’ve got our FixNum result and we can move on. Otherwise we need to do it the old-fashoned way.

I don’t know whether YARV already does this or might in the future. This is one of the things which VM implementers tend to look for, they ‘cheat’ and try not to get caught in the interest of performance.

Now Matz and his team might reject some of these tricks since the dynamic nature of ruby might make it harder not to be caught, but in some of these edge cases, I think that case can be made that it’s probably OK since it’s unlikely that anyone will actually redefine basic arithmetic operations on core classes such as FixNum and live to tell about it without blowing up irb or worse.


Boolean Implementations, Ruby, Smalltalk and self

Posted by Rick DeNatale Tue, 10 Oct 2006 16:43:00 GMT

The topic of defining a new ruby class which could have instances that, like false and nil were seen as a boolean which was not true, just came up on ruby-talk.

This has come up before, and it turns out that in Ruby being untrue is reserved to these two specific instances.

The boolean test is pretty deeply engrained into the implementation of ruby. The actual test seems to be defined in the RTEST macro in ruby.h

#define Qnil   ((VALUE)4)
#define RTEST(v) (((VALUE)(v) & ~Qnil) != 0)

Which means that any object whose reference VALUE has any bit set other than the 3rd LSB is true.

In ruby, the control flow statements like ‘if’ aren’t messages, but are ‘compiled’ into a direct test and conditional branch.

Even Smalltalk, which defined even if/then/else as a message, e.g.

    booleanValue ifTrue:[Transcript show:'true'] ifFalse: [Transcript show:'false']

Tended to cheat in the implementation…

In most Smalltalk implementations #ifTrue;ifFalse: and its ilk are never sent, but are, like in ruby, compiled into test and branch code. Some implementations might have had a fallback if booleanValue wasn’t actually a boolean, but IIRC most would trigger a MustBeBoolean exception.

By the way, those […] are the Smalltalk analog to ruby’s blocks. In Smalltalk, blocks can be used as the value of any argument to a method, and a method could take more than one block argument.

But blocks are also another area where Smalltalk implementations tend to cheat a bit.

Smalltalk maintains the fiction that ifTrue:ifFalse: is really a message, and the methods in True and False are there to see:

in the True class

   ifTrue: trueBlock ifFalse; falseBlock
       ^trueBlock value

and in the False class
   ifTrue: trueBlock ifFalse: falseBlock
        ^falseBlock value

The sending the message value to a Smalltalk block is analogous to sending call to a Proc in ruby, although the actuall message varies with the arity of the block. In the case of ifTrue:ifFalse, the block arguments don’t really bedome block objects, they get compiled as in-line code.

A lot of Smalltalkers ran across a head-scratcher when they got to the point of looking at the implementation of the value method in block which looks something like thi
   value
      "return the result of evaluating the receiver"
      ^self value

This certainly looks like it should be an infinite loop, but it isn’t. The trick is that in almost all circumstances, the Smalltalk compiler compiles sending value to a block into either special bytecodes. The only reason that the value method in block needs to be there is to handle cases like:

aBlock perform:#value

where perform is the analog to ruby’s send.

Smalltalk VM implementors like to say that it’s okay to cheat as long as they don’t get caught. MustBeBoolean is one area where they do get caught.

Pushing the Envelope

It’s quite a daunting task to fully implement a computation model where everything is a message and get reasonable performance. Smalltalk pushed this model quite far, but bowed to practicality in a few cases.

Ruby, although it’s more dynamic than Smalltalk in a lot of ways, makes more concessions in it’s current implementation.

Dave Ungar’s self language, in the spirit of Nigel Tufnel, turned theknob up to eleven, and eschewed the pre-optimization of even if tests. Instead, the self implementation developed and used sophistacated run-time type inferencing and analysis to generate optimized code at runtime by detecting the common cases of a boolean receiver and converting the message send to tests and branches, while avoiding supporting the less common case.

In common with Ruby, self had a more dynamic object model than Smalltalk, based on delegation rather than inheritance. Something which engendered roaring debates in the early OOPSLA community over how delegation and inheritance are related. The status of that discussion ca. 1989 is captured in “The Treaty of Orlando.” which documented the observation that the differences were really a matter of perception and viewpoint.

The real contribution of self was setting the bar high in terms of the difficulty of implementing a simple and dynamic specification, and then jumping over it. The self team later applied the lessons they had learned to the implementation of Strongtalk, a Smalltalk VM which applied the techniques of the self implementation to both make Smalltalk more dynamic, and better performing.

Many of those sessons should be applicable to implementations of Ruby. I hope to see that unfold over time.


Simulee, Simula, Simulee, Simu-la-ah-ah-ah

Posted by Rick DeNatale Thu, 05 Oct 2006 15:48:00 GMT

Recently, a certain “gentle-reader” questioned my statement in my “mini-memoir” that Simula lacked classes and inheritance.

I stand by my guns. Simula (now known as Simula I) had neither. These were introduced by Simula-67 about five years later. It was Simula rather than Simula-67 which was one of the influences on Alan Kay’s early conception of Smalltalk.

For more details, see my reply to “gentle reader” in the comments to my mini-bio article.


Performance Anxiety

Posted by Rick DeNatale Tue, 26 Sep 2006 19:17:00 GMT

I've been meaning to write about Ruby performance for a while, and a recent blog post by an old friend and colleague, got me off my proverbial.

The old friend is John Duimovich, who wrote about the relative performance of C++ and Smalltalk and what that could mean for ruby.

John's message is important for those who bemoan the performance of Ruby, and I plan to expand on that message in this and later posts to this blog, but first a few words about Mr. Duimovich.

Consider the source

In his day job, paraphrasing his self description John "works for IBM on Java virtual machines and is the lead on the Eclipse tools project management commitee."

But some of my readers might be interested in John's background. John was for a very long time, the lead of the Smalltalk and Java virtual machine team at Object Technology International (OTI) dating from before the time it was acquired by IBM. Among other things John was responsible for the development of embedded Smalltalk virtual machines from OTI, which spawned the VM used in Smalltalk/V Mac, IBM Smalltalk (used in IBM/VisualAge), the 'Universal' Virtual machine which implemented Java on an extended Smalltalk VM, and which was used for the early releases of IBM/VisualAge for Java, and the J9 Java VM. A good deal of what I know about implementing VMs comes from working, lunching, and bar-hopping with John.

John had become OTI's Chief Technology Officer before OTI got assimilated into the IBMborg.

John is a brilliant guy, with a great sense of humor. Two characteristics which seem to have been requirements for a job at OTI. I'm still not sure how I ended up spending several years there.

Dynamically Typed Doesn't Need to Mean Slow

I encourage you to read John's blog post yourself, but to summarize; John ran across another blog item which gave a benchmark written in C++, Ruby and Python. The C++ version runs in under 1/10 of the time needed for either the Ruby or Python versions.

John duplicated the results on his machine, then decided to port the Ruby version of the benchmark to Smalltalk. He then ran it using VisualAge Smalltalk.

And the Smalltalk version runs in the same time as the optimized C++ version!

How can this be?

The Value of Pole Vaulting

Languages like Smalltalk and Self started from the position that a clean object-oriented language was more important than one which makes compromises to make efficient implementation obvious.

Early implementations of Smalltalk used obvious implementations of some features, which were 'fast enough' in many cases, but by no means fast. Two areas which cried for improvement were method dispatch and garbage colection. The obvious techniques were walking up the class hierarchy each time a method was needed, and relatively easy to implement GC techniques like reference counting, and mark-and-sweep. Reference counting has a fairly high cost for each change of an object reference, and also has the drawback of leaking memory because cyclical references lead to garbage which is uncollectable. Mark and sweep delays the overhead until storage is exhausted, but leads to more perceptible pauses when the application gets paused so that the housemaid cleans the room.

Encountering (or having set) this high bar, various implementors of these languages found very clever techniques for both problems. Dave Ungar made measurements of the lifespans of Smalltalk objects and observed that most objects died very shortly after being instantiated, with few living a long life. This led to the invention of generational GC techniques, which quickly dispatched young dead objects, which are the vast majority.

Method dispatching techniques of efficiently implemented dynamically typed languages tend to use clever caching algorithms which can get to what is probably the right method quickly, with a quick test to make sure that the right method was found.

These dispatching techniques turn out to be faster than the virtual function pointer dispatching made possible by strongly-typed languages like C++. In fact, I've heard that more modern implementations of these languages have actually used a more dynamic method dispatch mechanism internally in order to increase performance.

Anoher implementation choice is how to represent executable code. Most efficient implementations use a combination of byte-code representation, and some form of just-in-time translation of byte-codes to machine code. Just how to divide execution between byte-code and machine code is a complicated decision. Back when DIgitalk first produced a version of Smalltalk/V for OS/2, they decided to eschew byte-codes entirely and generate 80286 machine code. The reason was that they were tired of hearing complaints about Smalltalk being an 'interpreted' language.

The surprising result of this experiment was that the resulting implementation was slower. Machine code was bigger, so it took longer to load, and caused more swapping. These costs were paid whether the code in question was executed once or a million times.

Again caching was the basis for getting the best of both worlds. Peter Deutsch of Xerox, later ParcPlace, had introduced the notion of translating byte-codes to machine code into a cache during execution, David Ungar's implementation of Self introduced the notion of using light-weight profiling techniques to avoid the overhhead of translating byte-coded methods which were infrequently executed.

Another area which posed difficulties in implementation was control flow. Smalltalk-80 defines all control flow as methods. Even primitive control flow constructs such as if (ifTrue: in Smalltalk) were implemented as methods on Boolean classes. This is one area where Smalltalk implementations cheated compiling such methods in to testing and branching byte-codes, and requiring the receivers to be boolean instances.

Self eschewed this early optimization. Ungar's team instead relied on run-time type inference in order to dynamicaly generate code which achieved the same or better performance when such a message was sent to a boolean without restricting other cases.

The Current State of Ruby Implementation

Ruby performance today is surprisingly acceptable for a wide range of uses.

This is despite the fact that the implementation is relatively straightforward, almost to the point of being naive. In the current standard implementation of Ruby:

  • Method dispatch is done by walking up the 'class' hierarchy looking for methods in a hash table in each class/module.
  • Garbage Collection is done by a simple mark and sweep algorithm.
  • Executable code is represented by a parse tree which is executed by traversal.

This is not meant to understate the achievements of Matz and the ruby developers. Ruby as it is definitely usable for many production uses.

The point is how much better Ruby performance can get as the implementation matures. A virtual machine, with byte-codes, and better GC is on the roadmap. Ruby virtual machines such as YARV, and JRuby are showing glimmers of the value of implementing Ruby as a virtual machine. If Ruby continues to grow in acceptance, I've no doubt that other clever implementers with experience in efficently implementing dynamically typed languages will provide more implementations.

My prediction is that the future will be so bright that we're going to have to wear (ruby colored) shades!


On Variables, Values, and Objects

Posted by Rick DeNatale Wed, 13 Sep 2006 19:47:00 GMT

I’ve recently observed some posts to ruby-talk which evidence some confusion on the part of the posters about the relationship between variables and objects in Ruby. One currently active thread concerns several participants who are upset that instances of the Matrix class in the Ruby standard library can’t be changed once created.

In Ruby, like in other uniformly object-oriented languages, the relationship between variables and their values is subtly different than in other languages, and this is a crucial paradigm shift, which must be crossed in order to understand Ruby.

In many languages a variable names an area in memory which holds a “bag-of-bits” representing the value of the variable. The size of that area depends on the type of the variable. A variable holding an integer might be 4-bytes long, while one holding a particular structure might be 325 (or whatever) bytes.

In a uniformly object-oriented language, all variables reference objects, and any variable can reference any object, or different objects over time. My good friend at IBM, the late David N. Smith, used to say that in such a language, “all variables are the same size,” when he wrote about or taught Smalltalk.

This distinction can trip up the unwary. Let’s try to clear some of the stumbling blocks out of the way.

Ruby Variables Don’t Have (Permanent) Classes

In one recent thread, someone suggested adding a method to the “class of a variable.”

The problem with this idea, is that a variable doesn’t really have a class. For example, consider thiscode:

require 'matrix'
   a = 5
   a = a * 1.0
   a = a * Matrix.identity(3)

Here the variable a refers to a sequence of objects, each with a different class. First a Fixnum, then a Float, then a Matrix. While Fixnum, and Float inherit from Numeric, Matrix doesn’t but it can form a duck-type with Numeric in many uses.

This also illustrates that “all variables are the same size.” In a language like C, a variable holding an integer, will probably have a diffferent size as one holding a double (which is what Ruby defines as the representation of a float), and one which holds a 3×3 matrix of doubles certainly will be bigger than one holding a scalar double.

Ruby Variables Hold Object References, not Object State


The magic which allows this is the fact that in Ruby, as in Smalltalk, a variable doesn’t hold the “bag-of-bits” which represents a particular data-structure. Instead it contains a reference to an object which holds the “bag-of-bits.” The actual structure of that “bag-of-bits” is of no concern to, and is hidden from the variable and it’s users.

This encapsulation barrier is key to what makes a language truly “object-oriented,” at least the way I use the term.

The “bag-of-bits” which represents a particular object is visible to the methods of that object’s class, at least in an abstract way. Some details are even hidden to those methods at the Ruby source code level, and are tied up in the language implementation, hand written extensions to Ruby usually do need to deal with those details.

In Smalltalk, the pseudo-variable self is actually strongly typed in the C-sense since instances of Smalltalk classes have a fixed structure, and self in a method is guaranteed to refer to an instance of the class owning the method or one of it’s subclasses, and instance variables are found in known slots within the object.

In Ruby it’s a little different because Ruby instance variables are created dynamically and accessed via a hash table within the object, at least in the 1.8.x implementation.

As a first approximation, we can initially think of variables as holding pointers to objects, but I’ll expose this for the pedagogical lie that it is, a little later in this article.

Mutability, and Aliasing

Here’s one of those stumbling blocks for those who expect variables in a uniformly object-oriented language to work like they do in a language like C or Fortran:

 1: a = [1, 2, 3]
 2: b = [1, 2, 3]
 3 1: a = [1, 2, 3]
2: b = [1, 2, 3]
3: c = a

4: a[1] = 0 5: p a #=> [1, 0, 3] 6: p b #=> [1, 2, 3] 7: p c #=> [1, 0, 3]

Everything looks pretty normal up ot line 7. We never did anything with c after we assigned it a value, but it doesn’t seem to have held it’s value.

Or has it?

Well, it actually has, since it’s value is a reference to an object, and that object is the same one referenced by a.

Line 4 might look like an assignment to the variable a, but it’s really a method call to the array which a happens to be referencing at the time. And that method (called []=) changes, or mutates that array. That change will be visible through the variables a, c and any others that reference that particular array. Multiple references to the same object are called aliases to that object. They might be named variables, or referenced which are inside another object:

 8: d = [[1, 2, 3], [4, 5, 6]]
 9: e = d
10: d[1][1] = "Fred"
11: p e #=> [[1, 2, 3], [4, "Fred", 5]]]

While such mutating methods are often very useful, this effect of aliasing is something which the Ruby programmer who uses them needs to keep in mind.

Many built-in Ruby classes have both mutating, and non-mutating versions of methods, for example Array#compact returns a new array which is a copy of the receiver with nil elements removed, leaving the original array intact, while Array#compact! mutates the receiver and removes the nil’s in-place.

As with compact and ocmpact!, it’s standard practice to give such mutating methods a name with a trailing ‘!’ which serves as a warning that they mutate the receiver. It’s a warning to the wise.

That Little White/Pedagogical Lie, or Variables and Object Identity

I said above that thinking that variables hold pointers to objects was a first approximation to reality. The fact is they really don’t

12: a1 = [1, 2, 3]
13: a2 = [1, 2, 3]
14: p a1.object_id #=> -605450882
15: p a2.object_id #=> -605225658

The object_id method returns a number which is unique in the sense that no two active objects will ever have the same object_id, and a given object will always have the same object_id. In the Ruby 1.8.x implementation, object_id actually just gives the bits of the value used to reference the object in the guise of a Fixnum.

So we see here that a1 and a2 are diffferent objects. Let’s try a few more objects:

14: i1 = 1
15: i2 = 1
16: p i1.object_id #=> 3
17: p i2.object_id #=> 3
18: sym1 = :sym
19: sym2 = :sym
20: p sym1.object_id #=> 4090126
21: p sym2.object_id #=> 4090126 

Here’s another surprise. Before when we created two different arrays, we ended up with two different objects. But even though we never assigned i2 to i1, or sym2 to sym1, the ‘two’ 1s have the same object_id, and the ‘two’ symbols named :sym share an object_id, what’s that about?

Certain classes ensure that if ‘two’ of their instances are equal they are the same object. We can see that Fixnum, and Symbol do this, others are NilClass, TrueClass, and FalseClass. For symbols, this conflation of value and identity is part of their definition, for the others, it’s probably not strictly necessary, but it makes some common operations like testing for equality, and in the case of Fixnums arithmetic operations, much faster.

What’s really held in variables is a value which can either be used to recognize that the object is one of these special objects, or that can be mapped efficiently to the real address of the object. The details are implementation-specific, and not really germane to the current topic, so I won’t go into them in this article.

Immutable Objects


It’s often advisable to design classes without mutating methods. For example, Fixnum has a method [] which returns the nth bit of the representation of the number where bit 0 is the least significant bit. Suppose that it also had a method []=, which set the value of the cooresponding bit:
#Hypothetical code - with a tribute to Jimi Hendrix
h1: a = 6
h2: b = 6
h3: a[0] = 1; a[1] = 0; a[2] = 0; a[3] = 1
h3: p a #=> 9
h4: p b #=> 9

Since all 6’s are the same object, then if Fixnum had mutating methods, we could make all 6’s turn out to be 9. While Jimi might not mind, my program might not like it.

And it would cause head-scratching debugging sessions. Thirty-two years ago, I found myself in just such a situation. Fortran II had a bug in the language specification which allowed the value of integer literals to be changed when you passed a literal as an argument to a subroutine which assigned to that argument. I spent over a day trying to figure out why my program didn’t work.

For this reason, to quote Martha Stewart, it’s a good thing that the Ruby numeric classes don’t have mutating methods. Even though Bignums and Floats don’t conflate value with identity, it would probably be even more mystifying to find that some instance of 1.5 changed to 1.45 when other’s didn’t. To me it seems far better to head off that particular ‘feature’ at the pass.

Another reason for this choice of immutability is taken from functional programming. Although Ruby is not really an FP language, it takes many concepts from that paradigm. In FP, functions with side-effects are disallowed, and mutation is certainly a side-effect. Taking FP to the limit makes doing things which require side-effects, like I/O, take special tricks. Ruby allows side-effects, and doesn’t require an FP approach, but like other features like regular expressions, understanding functional approaches is a useful tool in the Ruby programmer’s bag.

Immutability at the Instance Level

Ruby Object’s have a freeze method which makes a particular instance immutable:

F1: a1 = [1, 2, 3]
F2: a2 = a1
F3: a1.freeze
F4: a1[1] = "Fred" #=> TypeError: can't modify frozen array
F5: a2[1] = "Fred" #=> TypeError: can't modify frozen array

Beware, though, that this only freezes the object itself and not it’s sub-objects, or referenced objects:
F6: a3 = [[1, 2, 3], [4, 5, 6]]
F7: a3.freeze
F8: a3[0][1] = "Fred"
F9: p a3 #=> [[1, "Fred", 3], [4, 5, 6]]

Matrix and Mutability


Following the pattern established by Numerics, the designer of the Matrix class, who, according to the comments in the source code, ported it from Smalltalk, made Matrix instances immutable.

This upsets some who prefer to think of a Matrix as a 2-dimensional array rather than a mathematical construct which acts much like a numeric in linear algebra.

If you want to view matrices that way you’ve got a few choices:

  1. Swim-against the current: Monkey-patch Matrix to add mutating methods.
  2. Swim with the current: Use the Matrix#to_a and Matrix[] to get a mutable array and then create a new Matrix from it:
    M1: m1 = Matrix.identity(3)
    M2: p.m1 #=> Matrix[[1, 0, 0], [0, 1, 0], [0, 0, 1]]
    M3: a1 = m1.to_a
    M4  a1[1][1] = 3
    M4  m1 = Matrix[a1]
    M5: p m1 #=> Matrix[[[1, 0, 0], [0, 3, 0], [0, 0, 1]]]
  3. Find a new stream: look at other sources of a mutable 2-dimensional array, for example NArray

The choice, gentle reader, is yours. I hope that my efforts help you make it a more informed choice.


About me

Posted by Rick DeNatale Sat, 29 Jul 2006 13:34:00 GMT

For those who don’t want to read a lot, or dont care too much, here’s the executive summary:

  • I’m a long time object programmer.
  • I worked for IBM for 31 years.
  • I was one of the early adopters/advocates of Smalltalk in IBM.
  • I’ve done a lot of Smalltalk.
  • I’ve done a lot of standards work.
  • I’ve done a lot of Java.
  • I’m now free of IBM and Java, and I’m learning to love Ruby.

As a result of all of the above I’ve developed lots of strong opinions, weakly held, which I’d like to share.

Now for those with the stamina, some more details on my personal journey…

IBM Research – Smalltalk and ClassC

My early IBM career gave me a lot of experience with developing software. One of the things which struck me was how, despite its name, most software was hard. Hard to develop in the first place, and harder to change to adapt to new requirements.

Like many others, I first became aware of Smalltalk when Byte magazine published a special issue on the langage in 1981. I led a small team at IBM Watson Research which developed a language called ClassC which was inspired by that Byte issue, and added Smalltalk message sending to C, it was similar in concept, but not in syntax to Brad Cox’s Objective-C. We found out about Objective-C after we’d already done our worst. ClassC got some use for internal projects in IBM after I moved to a new IBM development lab in Cary, NC in 1984.

While I was working on ClassC, the late David N. Smith was dealing with the lawyers at IBM Research, Xerox, and UC Berkeley to get Smalltalk-80 into research. Dave and I became good friends, along with other folks in the IBM Research User Interface Institute like Dave’s “sidekick,” the late Jerry Archibald, and John T. Richards, and we formed an OO-Smalltalk cadre within IBM. These three were also key participants in the birth of the ACM OOPSLA conference. Although I personally missed the first OOPSLA, I was a steady participant for the first decade or so, moderating several panel discussions, participating in workshops, and serving on the commitee for OOPSLA ’93.

One of the advantages of being part of the OOPSLA community was being able to forge friendships and working relationships with many very bright people such as Ward Cunningham, Kent Beck, and all four of the “Gang of Four”

Research to Internal Consultant

After moving to the new lab in Cary, I primarily worked as an inter-divisional consultant, working to drive the requirements of my division, which was writing what was then a new style of applications with graphical direct manipulation user interfaces, into the plans of the Personal Systems division. This got me into a lot of interesting meetings with not only other IBM folks, but also staff from other companies. For example, I was present at the shotgun marriage between IBM Boca Raton, IBM Hursley, and Microsoft which led to OS/2.

My job had given me the opportunity to visit various companies which IBM was investing in, or considering investing in. I got to meet people like Jean-Marie Hulot of Expertelligence whose interface builder implemented in Lisp got re-written in Objective-C to become NeXTStep’s Interface Builder, after he moved to NeXT. A little later, after IBM had made an investment in NeXT, I got to meet Jean-Marie again along with Steve Jobs. I got to argue with Tony Williams and Bill Gates and his team over the merits of their approach to the early design of what became COM, which made the C++ type system a little more dynamic andwith the IBM designers of SOM which tried to make a statically typed systems more resilient to “schema” evolution. Both of these were also (failed) attempts to forge an entente in the “Language wars”

Smalltalk and IBM

With the availability of Digitalk’s SmalltalkV, our little OO cadre started to push for adoption of Smalltalk inside IBM. One of my biggest contributions was to implement a prototype which extended the Smalltalk/V development environment with a direct-manipulation UI and UI Logic (i.e. controller) tool inspired by the Interface builder, which I dubbed Application Builder. When SmalltalkV/PM came out, I ported the Application Builder to it.

The division’s mission had been shifting towards building application development tools, so this prototype fit in. Most of those tools were focused on old big-iron ideas and languages, such as ISPF, and Cobol adapted to personal computers, although targeted for mainframes. I arranged to demonstrate Application Builder to Earl Wheeler, the group executive who oversaw our division and who was in charge of a grand IBM strategy called Systems Application Architecture. Wheeler seemed quite impressed with the App Builder demo and directed us to turn it into a product, and get Smalltalk to be part of SAA, although he wanted it positioned as a “generator” instead of a language for internal IBM political reasons.

I took the point on getting Smalltalk into IBM product plans, while others took the prototype and turned it into what became VisualAge. In my opinion they took the visual programming idea a bit too far, but it did the job of getting Smalltalk out to the world from IBM. And it resulted in IBM Smalltalk, which was implemented by Object Technology International, a company founded by Dave Thomas, although a different Dave Thomas than PragDave. As an aside, what is it about guys named Dave Thomas? Besides OTI-Dave (who is well-known to the Smalltalk community as Big Dave), and PragDave, we have the Dave Thomas from SCTV and Doug of the McKenzie brothers, and the Dave Thomas who founded Wendy’s. Two Canadians, and two Americans.

I also spent a lot of time talking to IBM customers about how object-oriented approaches, and Smalltalk in particular, could help them solve the problems they were having with software being hard.

Smalltalk Distributed

One of my big-idea products was Smalltalk Distributed, a feature for VisualAge/Smalltalk. I led the development on this one.

Distributed applications were the rage at the time. There was another approach to distributing Smalltalk from HP called Distributed Smalltalk, but this was really a Smalltalk implementation of the Object Management Groups CORBA. Although I had been serving as one of the IBM representatives to OMG (as a Smalltalk expert), I didn’t find this idea particularly interesting or appealing. The goal of Smalltalk Distributed was transparent distribution of Smalltalk. Our approach was to implement a distributed implementation of the Smalltalk object model including object storage and garbage collection, message sending, and distributed threads of execution complete with non-local returns. This was all done completely in Smalltalk, using lots of tricks in using metaprogramming much like what the wizard Ruby metaprogrammers do.

This project was technically interesting, and got some use by customers, but it was most valuable as a learning experience. In retrospect, the transparency was both a neat idea, and a problem. Putting a black box around a distrubuted system is probably not as good an idea of putting a distributed system together out of black boxes.

As a result of the Smalltalk Distributed work, I got to spend a month in Sydney Australia, working with Jeff McAffer of OTI, to re-implement some of the ideas such as the distributed threads in a toolkit for building server applications which he called Surfer (or Server) Smalltalk. Jeff subsequently became one of the technical leads of the Eclipse project.

Smalltalk Standardization

Another piece of work I did at IBM was to write a report characterizing the similarities and differences between the various Smalltalk implementations. At that time these were ParcPlace VisualWorks/Smalltalk-80, Digitalk Smalltalk/V, and IBM/Smalltalk (from OTI). By focusing on the externals of the classes and taking inheritance out of the picture, I wrote a report called “Smalltak: A Common Base” which was in effect a rough draft of a reverse-engineered specification for a common Smalltalk language specification.

When the various Smalltalk vendors expressed interest in forging a Smalltalk language standard, X3J20 was formed to develop an ANSI standard, and the common base document became one of the early inputs. I became the secretary of X3J20. The standard was published in January of 1998.

Language Wars – Dynamic vs. Static OO


Of course back in the days before the turn of the century, there was a great debate raging in the “object-oriented” programming community, centered around the value of dynamic languages like Smalltalk vs. static languages like C++.

One of the things which always attracted me to Smalltalk was that it placed encapsulation above all else. As Alan Kay noted in his memoir about the origins of Smalltalk, his original conception of object-oriented programming was that software should be composed of objects which were, in effect, little computers themselves, which encapsulated both data and behavior, and hid the implementation of both from other objects, with objects interacting via sending messages to each other and replying. This uniform object model separates languages like Smalltalk and Ruby from other “object-oriented” languages. The various versions of Smalltalk all shared this model, although they varied as to some of the semantics of message sending and reception.

The idea of classes and inheritance as a way of factoring implementation was actually a rather late addition to Smalltalk. Although Kay acknowledges the Simula language, which also lacked classes and inheritance, as one of the influences on his thinking leading up to Smalltalk, it’s been a popular misconception that the better known Simula-67 was his real influence, when Smalltalk and Simula actually evolved independently.

Kay’s term “object-oriented” got hijacked when Peter Wegner published paper entitled “Dimensions of Object Based Language Design” at the second OOPSLA conference in which he defined “object-oriented” as “objects + classes + inheritance.”

Simula-67 spawned a family of languages which called themselves object-oriented but really used classes and inheritance to create hierarchies of abstract data types. In thes languages which include C++, Oberon, and to a lesser extent, Java became popular bacause they were seen as an easy entree into “object-orientation” to programmers who were more comfortable with the notion of programs manipulating data from “a distance.” This led Alan Kay to observe that

It is unfortunate that much of what is called “object-oriented programming” today is simply old style programming with fancier constructs. Many programs are loaded with “assignment-style” operations now done by more expensive attached procedures.

Because of this morphing of the meaning of object-oriented programming I started to use the term “object programming” instead. In 1991, I wrote an IBM Research Report called “Types From the Client’s Viewpoint,” which very much relates to duck typing and which got cited in a few places. It’s long out of print. So I’ve scanned a hard copy of a draft, to show my thinking at the time.

This debate lives on. It pops up as some of the uneasiness of new Ruby programmers coming from the strong-typing/abstract data type community over thinks like “duck typing.” I plan to explain my thinking about duck typing and other related topics here.

My point here is, I’ve got strong opinions about this topic. While I do believe that the key to wisdom is strong opinions weakly held, I haven’t seen any reason, over twenty-something years to let go of this set of opinions.

Smalltalk to Java


Smalltalk was quite successful with our customers. In some ways it looked like it might become the Cobol of the 21st Century.

Then Java came along. It gave some of the benefits of Smalltalk like languages in a package which was appealing to the C++ community, a lot of who were starting to become jaded over how C++ (if they actually used the compiler to do more than compile normal C programs), seemed to make development harder. It kind of looks like C++, and has a more “regular” syntax than Smalltalk, which some found wierd, although to the Smalltalkers it was beautiful in it’s sparseness and elegance.

And IBM made the jump to Java. Most of us who had been working on Smalltalk were encouraged to start working on Java and Java tools.

About this time, I took an assignment to OTI, which had been acquired by IBM Canada as a wholly owned subsidiary.

OTI itself was making an investment in Java. The first step was to turn the IBM/Smalltalk virtual machine into what was called the UVM or Universal Virtual Machine. This could run both Java and Smalltalk bytecodes. The Java “natives,” the equivalent of extensions in Ruby were written in Smalltalk instead of C. The first VisualAge for Java was written in Smalltalk on this UVM.

Eventually, as Java evolved this approach became less tenable. So OTI started building a new IDE in Java. Our first use for this was for a system to develop embedded Java applications. IBM was getting very interested in embedded software, which they called “Pervasive Computing” and had formed a division called PvC to pursue it. Embedded applications (e.g. code inside an oscilloscope, or a cell phone) written in Smalltalk was an early focus of OTI predating the relationship with IBM. Java, which was actually first developed within Sun for such embedded applications, was a natural language to employ.

The resulting development was called VisualAge/Micro Environment or VAME. The IDE and UI design was done at the OTI Zurich lab by a team led by Erich Gamma of the “Gang of Four.” This code was almost completely reworked and combined with Jeff McAffer’s component run-time architecture to become the basis for Eclipse.

After working on VAME, I moved over to a group working with customers on embedded Java applications. We majored on automotive applications, since there were a lot of car companies and suppliers who were interested in telematics systems with sophisticated software. As a “standards guy” I represented IBM in standards organizations such as the “Vehicle Expert Group” within OSGi

Back to the Mother Ship for a while

By this time, OTI was being gradually assimilated into the Borg of IBM. My group was first. Although we continued to work out of the OTI lab in Raleigh, NC, we now reported to IBM PvC management in Austin Tx.

Then because I was “the standards guy,” I got re-assigned to the PvC architecture department in Austin which was the home of all the PvC standards guys.

Eventually, OTI got “reorganized” (i.e. broken up) with various pieces going to different IBM divisions.

Free at last

After a year or so of this, and 30+ years of IBM, I realized that I was tired of life in a big corporation. Since I was old enough to still have a traditional pension, it was time to see what life was like on the outside, so I retired in the spring of 2005, and I’ve been happily pursuing my own muse, happily learning and working on new projects that I wanted to work on.

I’ve recently discovered Ruby, and as an old Smalltalker, I’m excited to see what looks like the reincarnation of an old friend. I’m starting this blog to see what I can share with the Ruby community based on my experiences.


On Hunting Ducks

Posted by Rick DeNatale Wed, 26 Jul 2006 19:39:00 GMT

Five doctors go duck hunting, they draw lots to determine the order in which they will shoot from the blind.

The Psychiatrist gets the first chance.

A flock of birds fly over. He looks down at his shotgun and says

They look like ducks! They sound like ducks! I wonder how they feel about being ducks?

Meanwhile the birds fly by.

Next up is the internist:

They look like ducks! They sound like ducks! But we can’t rule out the possibility that they might be geese.

Then the general practitioner:

They look like ducks! They sound like ducks! What do you guys think?.

The surgeon takes his place next. He confidently feels the trigger of his shotgun with his highly skilled right forefinger. The next flock flys over.

Bang! Bang!

And the surgeon turns to the pathologist and says:

Check them out and see if they are ducks.

I’ve known this joke for quite a few years, but I’ve never thought about it in relationship to software, until I started playing around with Ruby, and discovered an old friend under a new name, “Duck Typing.”

Last week, I ran across a thread on the ruby forum called “I’ll have the Duck!” which quickly got lots of responses, and seems to have ended up with jokes.

Most of this thread seems to miss the point of duck typing.

Once you’ve really grokked duck-typing you become like that surgeon. Your perception of the properties of objects that really matter changes. And you learn to use the pathologist (testing) as a powerful ally.

Many programers coming to ruby from languages like C++ and Java are like the psychiatrist, internist, and general praticioner in the duck hunting story.

They want certainty in their typing. They’ve developed the expectation that early type-checking by a compiler will keep them from making mistakes.

The problem with this expectation of the power of early type checking is two-fold.


  • It doesn’t really work

  • It is overly constraining

It doesn’t work because the bugs caused by type-checking errors is a small subset of buges in general. Besides, in a fully object—oriented language like Ruby or Smalltalk, they are rare (because the methods which actually operates on the data is actually automatically strongly type-bound to the data by virtue of it being a method. It’s overly constraining because it unnecessarily couples the implementations of the provider and users of the services provided by an object.

Rather than droning on about the failures and contraints of early-type checking, which I suspect I’ll address more fully here as time goes on. Allow me to introduce the notion of types in an object-oriented languagethat I’ve come to accept over many years.

Let me suggest that in a fully object-oriented language types are not properties of objects or classes, but properties of variables which code using an object uses to refer to those objects. In saying this I’m recapping the key idea behind an IBM Technical Report I wrote back in 1991 entitled “Types fromthe Client’s Viewpoint” Which is available here as a pdf file.

“But wait a minute!”, you say. “Aren’t types for matching objects with variables, so that programmers won’t make mistakes when they manipulate the object?” To which I reply, “That’s not object-oriented.”

Now of course many will argue with this, but I’d like to revisit the original conception of object-orientation, a term which was coined by Alan Kay, the inventor of Smalltalk, a language from which Ruby has borrowed a lot.

The key idea behind “object-orientation” a la Smalltalk and Ruby is the encapsulation of implementation behind an interface defined by a set of messages. Kay felt that the traditional way of structuring software as programs which processed data, and the attendant separation of program and data was somthing to be avoided. His view is that it isbetter to compose software out of components which all look like little computers, which contain and bind the programs and state together. This was a synthesis of ideas which he had seen over many years, although they had never been codified before he did it.

For an insight into Kay’s thinking, have a look at the article he wrote some years ago about “The Early History of Smalltalk”

Another way of looking at this idea, is that objects should be like little server machines, the exact set of services available and their implementation can vary from server to server, but clients can still use those services in isolation from those details.

In both Ruby and Smalltalk, classes and inheritance are used for implementation sharing, in order to achieve economies in implementing those little computers (objects). This is not an essential feature in Kay’s conception of OO. The original versions of Smalltalk had neither classes nor inheritance which were introduced in later versions.

In parallel with the evolution of Smalltalk, a family of languages based around the concept of Abstract Data Types became an important Computer Science research topic. Abstract Data Types arranged data types into a hierarchy so as to categorize their use as a way to structure more traditional procedural programs, and they called these abstract data types, classes, and the relationship between classes inheritance, so subclassing was simply a synonym for subtyping.

Since, by the time Smalltalk had been made widely known by the publication of a special issue of Byte magazine devoted to Smalltalk-80 in 1981, it had added classes and inheritance, most observers mistakenly thought of classes and inheritance as essential features of the language. One of these was Peter Wegner who wrote an influential paper Dimensions of Object based Language Design which was published in the proceedings of the 1987 OOPSLA conference. In this paper, Wegner defined “object-oriented” languages as those cobining “objects+classes+inheritance.” What he missed was that in Kay’s conception of object-orientation classes and inheritance were merely implementation artifacts, and that the encapsulation of implementation within an object was the big idea which separates object-oriented languages from procedural languages, and despite the similarity in terminology, abstract-data-type languages, which presented instances of those data types as things to be manipulated from the outside, were far from object-oriented, at least as Kay conceived it.

So to wrap this up for now, duck-typing is a natural consequence of the nature of how objects with strongly encapsulated implementations should interact. The notion of objects containing the code which manipulates them, and hiding that implementation behind a wall, through which messages are sent, is a paradigm shift with powerful consequences. Because many so-called “object oriented” languages missed this paradigm shift, many of their users are uaware the power of thinking about software design from this new perspective.

I hope, that in some small way, this blog will help expose the beauty of this paradigm shift.