On class/metaclass coupling

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

On class/metaclass coupling

Igor Stasenko
For people who think that we should not revise the class/metaclass
coupling in Squeak,
just ignore this topic and consider it as a rant :)

For those, who interested why i think its not a perfect from
object-oriented point of view, continue reading.

Ok. Lets start from basics.

A classes, in smalltalk is a first class objects, which one of its
strong sides, comparing to other languages.
Since each object has a class, we also need an object which reflecting
the class itself, and hence the metaclass.

But then, each class could have as many instances as it likes to, isnt?
But here the contradiction, which drives me nuts, when i looking at
Metaclass definition - 'thisClass' ivar.

This implies that any metaclass could have only a single instance - class.

Metaclass>>new
        "The receiver can only have one instance. Create it or complain that
        one already exists."

        thisClass class ~~ self
                ifTrue: [^thisClass := self basicNew]
                ifFalse: [self error: 'A Metaclass should only have one instance!']

but hey..
what you suppose to do with things like:

SomeClass clone

?
I am trying to understand, why do we need this inconsistency by
enforcing such a rigid rule.

Like, how often you may need to determine a 'sole' instance of the
class, or all instances?
And why it needs to be so fast by keeping a direct reference to it?

System browser could live well without it.
Altering the metaclass definition? Well, iterate over all instances
indiscriminately - using same mechanism as usual class doing for own
instances.
So, it is strange to me, why do we need such tight coupling..

Is anyone having insights about it?

--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: On class/metaclass coupling

Ralph Johnson
If you haven't done this already, you should look up Actalk, which was
a version of Smalltalk that let you have many classes with the same
metaclass.

http://map.squeak.org/package/19ae332d-1111-4131-8b56-1fd7e9d2b35f

I never used Actalk, I just read the papers.  It was an interesting
and worthwhile experiment, but I wasn't convinced that the change was
worthwhile.  But perhaps we just need to figure out more to do with
it.

What you are saying is a little different.  You are just complaining
about hardcoding the assumption that each clas has a unique metaclass.
 All you are really asking is to get rid of the "thisClass" variable.
I don't see any harm in that.  I bet that "new" is rarely called more
than once on any metaclass, and that one time is during the creation
of the class/metaclass pair.  The bigger issue is that when you
evaluate and print the expression "Object class", what happens is that
it computes the metaclass and then asks the metaclass to print itself,
which it does by fetching the name of its sole instance and appending
" class" to it.  In other words, a metaclass does not have a name, but
derives its name from the name of its sole instance.  But this doesn't
have to be fast, either.  You could call allInstances to find out the
instance and get its name.  My guess is that it would hardly be
noticeable.

Making this change would not cause metaclasses to have more than one
instance, but would make it easier for people to change things so it
would.

-Ralph

Reply | Threaded
Open this post in threaded view
|

Re: On class/metaclass coupling

Nicolas Cellier
2009/12/8 Ralph Johnson <[hidden email]>:

> If you haven't done this already, you should look up Actalk, which was
> a version of Smalltalk that let you have many classes with the same
> metaclass.
>
> http://map.squeak.org/package/19ae332d-1111-4131-8b56-1fd7e9d2b35f
>
> I never used Actalk, I just read the papers.  It was an interesting
> and worthwhile experiment, but I wasn't convinced that the change was
> worthwhile.  But perhaps we just need to figure out more to do with
> it.
>
> What you are saying is a little different.  You are just complaining
> about hardcoding the assumption that each clas has a unique metaclass.
>  All you are really asking is to get rid of the "thisClass" variable.
> I don't see any harm in that.  I bet that "new" is rarely called more
> than once on any metaclass, and that one time is during the creation
> of the class/metaclass pair.  The bigger issue is that when you
> evaluate and print the expression "Object class", what happens is that
> it computes the metaclass and then asks the metaclass to print itself,
> which it does by fetching the name of its sole instance and appending
> " class" to it.  In other words, a metaclass does not have a name, but
> derives its name from the name of its sole instance.  But this doesn't
> have to be fast, either.  You could call allInstances to find out the
> instance and get its name.  My guess is that it would hardly be
> noticeable.
>

My own guess is that there would be a noticeable down speed in code
management tools (Monticello & al).

Nicolas

> Making this change would not cause metaclasses to have more than one
> instance, but would make it easier for people to change things so it
> would.
>
> -Ralph
>
>

Reply | Threaded
Open this post in threaded view
|

Re: On class/metaclass coupling

Nicolas Cellier
2009/12/8 Nicolas Cellier <[hidden email]>:

> 2009/12/8 Ralph Johnson <[hidden email]>:
>> If you haven't done this already, you should look up Actalk, which was
>> a version of Smalltalk that let you have many classes with the same
>> metaclass.
>>
>> http://map.squeak.org/package/19ae332d-1111-4131-8b56-1fd7e9d2b35f
>>
>> I never used Actalk, I just read the papers.  It was an interesting
>> and worthwhile experiment, but I wasn't convinced that the change was
>> worthwhile.  But perhaps we just need to figure out more to do with
>> it.
>>
>> What you are saying is a little different.  You are just complaining
>> about hardcoding the assumption that each clas has a unique metaclass.
>>  All you are really asking is to get rid of the "thisClass" variable.
>> I don't see any harm in that.  I bet that "new" is rarely called more
>> than once on any metaclass, and that one time is during the creation
>> of the class/metaclass pair.  The bigger issue is that when you
>> evaluate and print the expression "Object class", what happens is that
>> it computes the metaclass and then asks the metaclass to print itself,
>> which it does by fetching the name of its sole instance and appending
>> " class" to it.  In other words, a metaclass does not have a name, but
>> derives its name from the name of its sole instance.  But this doesn't
>> have to be fast, either.  You could call allInstances to find out the
>> instance and get its name.  My guess is that it would hardly be
>> noticeable.
>>
>
> My own guess is that there would be a noticeable down speed in code
> management tools (Monticello & al).
>
> Nicolas
>

Posted too fast...
Beside, if it has several instances, then why insisting on giving a
name related to a specific instance ?

Nicolas

>> Making this change would not cause metaclasses to have more than one
>> instance, but would make it easier for people to change things so it
>> would.
>>
>> -Ralph
>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: On class/metaclass coupling

Igor Stasenko
2009/12/8 Nicolas Cellier <[hidden email]>:

> 2009/12/8 Nicolas Cellier <[hidden email]>:
>> 2009/12/8 Ralph Johnson <[hidden email]>:
>>> If you haven't done this already, you should look up Actalk, which was
>>> a version of Smalltalk that let you have many classes with the same
>>> metaclass.
>>>
>>> http://map.squeak.org/package/19ae332d-1111-4131-8b56-1fd7e9d2b35f
>>>
>>> I never used Actalk, I just read the papers.  It was an interesting
>>> and worthwhile experiment, but I wasn't convinced that the change was
>>> worthwhile.  But perhaps we just need to figure out more to do with
>>> it.
>>>
>>> What you are saying is a little different.  You are just complaining
>>> about hardcoding the assumption that each clas has a unique metaclass.
>>>  All you are really asking is to get rid of the "thisClass" variable.
>>> I don't see any harm in that.  I bet that "new" is rarely called more
>>> than once on any metaclass, and that one time is during the creation
>>> of the class/metaclass pair.  The bigger issue is that when you
>>> evaluate and print the expression "Object class", what happens is that
>>> it computes the metaclass and then asks the metaclass to print itself,
>>> which it does by fetching the name of its sole instance and appending
>>> " class" to it.  In other words, a metaclass does not have a name, but
>>> derives its name from the name of its sole instance.  But this doesn't
>>> have to be fast, either.  You could call allInstances to find out the
>>> instance and get its name.  My guess is that it would hardly be
>>> noticeable.
>>>
>>
>> My own guess is that there would be a noticeable down speed in code
>> management tools (Monticello & al).
>>
>> Nicolas
>>
>
> Posted too fast...
> Beside, if it has several instances, then why insisting on giving a
> name related to a specific instance ?
>

i second that.

If problem is only about identifying metaclass by name, then
why not just add a 'name' ivar to metaclass, and let metaclass to
print itself with whatever name it desire?


> Nicolas
>


--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: On class/metaclass coupling

Ralph Johnson
In reply to this post by Nicolas Cellier
On Tue, Dec 8, 2009 at 8:02 AM, Nicolas Cellier
<[hidden email]> wrote:

> Beside, if it has several instances, then why insisting on giving a
> name related to a specific instance ?

That is the way it works now.  If you want to give several instances
to a metaclass, you will need to come up with some other way of naming
metaclasses.  But just getting rid of "thisClass" would not require
adding a "name" variable to MetaClass.

-Ralph

Reply | Threaded
Open this post in threaded view
|

Re: On class/metaclass coupling

Andreas.Raab
In reply to this post by Igor Stasenko
Igor Stasenko wrote:
> For people who think that we should not revise the class/metaclass
> coupling in Squeak,
> just ignore this topic and consider it as a rant :)
>
> For those, who interested why i think its not a perfect from
> object-oriented point of view, continue reading.

It may help your thinking about the problem when you realize that the
core coupling between object and class, is as simple as:

        Class new class == Class.

I.e., if you can implement the #class method you could do something like:

        FooClass>>class
                ^FooFactory

        FooFactory>>new
                ^FooClass new

This will work perfectly fine in terms of the "everyday use" of classes.
I had thought about utilizing this to create "safe classes" that is
classes that separate the factory / utility aspect from the vtable
aspect (FooFactory can expose instance creation and utility methods
without exposing the implemntation / compilation aspect provided by
FooClass class').

Cheers,
   - Andreas


Reply | Threaded
Open this post in threaded view
|

Re: Re: On class/metaclass coupling

Igor Stasenko
2009/12/8 Andreas Raab <[hidden email]>:

> Igor Stasenko wrote:
>>
>> For people who think that we should not revise the class/metaclass
>> coupling in Squeak,
>> just ignore this topic and consider it as a rant :)
>>
>> For those, who interested why i think its not a perfect from
>> object-oriented point of view, continue reading.
>
> It may help your thinking about the problem when you realize that the core
> coupling between object and class, is as simple as:
>
>        Class new class == Class.
>

erm.. at least 2 messages between 'Class' to the left and 'Class' to
the right could do something completely different,
so as result you will get false (or something else, if #== overridden
itself). Of course i leaving an aggressive optimization of #class and
#== aside.

As any expression you writing in smalltalk, you can't tell what will
be result before evaluating it.


> I.e., if you can implement the #class method you could do something like:
>
>        FooClass>>class
>                ^FooFactory
>
>        FooFactory>>new
>                ^FooClass new
>
> This will work perfectly fine in terms of the "everyday use" of classes. I
> had thought about utilizing this to create "safe classes" that is classes
> that separate the factory / utility aspect from the vtable aspect
> (FooFactory can expose instance creation and utility methods without
> exposing the implemntation / compilation aspect provided by FooClass
> class').
>

There are few aspects, which is hardcoded in VM in respect, what
objects could serve as an object factory
(by using #basicNew, or #basicNew: primitives).

One could easily create own factory objects, as soon as VM
requirements met ('superclass methodDict format' slots).

"If it walks like a duck and quacks like a duck, it must be a duck"

Btw, by reading an essay (a link provided by Eliot few days ago) where
discussed a difference between ADT (abstract data types) and objects,
there were very good observation about objects, which is a good
complement to duck typing:
Two objects considered equal, if they simulating each one's behavior.

> Cheers,
>  - Andreas


--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: Re: On class/metaclass coupling

Igor Stasenko
Here are simple example, of what powers lies beneath, yet untamed.

now, try this:

| factory instance |
factory := CustomObjectFactory new superclass: Color.
instance := factory createInstance.
{ instance class. instance class class }

prints -> an Array(CustomObjectFactory(Color) CustomObjectFactory)

btw, there are something baad with Point class. Seems like there are
interference with compact classes in VM.

| factory instance |
factory := CustomObjectFactory new superclass: Point.
instance := factory createInstance.
instance class == factory

prints ->> false


Now lets go back to original question.

The metaclass of instance of CustomObjectFactory(Color) appears to be
a CustomObjectFactory..
but i can create as many instances of CustomObjectFactory class as i want..
Or should i add 'thisClass' ivar to CustomObjectFactory? ;)


--
Best regards,
Igor Stasenko AKA sig.



CustomObjectFactory.st (2K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: On class/metaclass coupling

Michael van der Gulik-2
In reply to this post by Igor Stasenko
On Wed, Dec 9, 2009 at 12:49 AM, Igor Stasenko <[hidden email]> wrote:

> For people who think that we should not revise the class/metaclass
> coupling in Squeak,
> just ignore this topic and consider it as a rant :)
>
> For those, who interested why i think its not a perfect from
> object-oriented point of view, continue reading.
>
> Ok. Lets start from basics.
>
> A classes, in smalltalk is a first class objects, which one of its
> strong sides, comparing to other languages.
> Since each object has a class, we also need an object which reflecting
> the class itself, and hence the metaclass.
>
> But then, each class could have as many instances as it likes to, isnt?
> But here the contradiction, which drives me nuts, when i looking at
> Metaclass definition - 'thisClass' ivar.
>
> This implies that any metaclass could have only a single instance - class.
>
> Metaclass>>new
>        "The receiver can only have one instance. Create it or complain that
>        one already exists."
>
>        thisClass class ~~ self
>                ifTrue: [^thisClass := self basicNew]
>                ifFalse: [self error: 'A Metaclass should only have one instance!']
>
> but hey..
> what you suppose to do with things like:
>
> SomeClass clone
>
> ?

That should probably fail. Instead, use >>copy, which (I suspect)
makes a new instance of Metaclass as well.

> I am trying to understand, why do we need this inconsistency by
> enforcing such a rigid rule.
>
> Like, how often you may need to determine a 'sole' instance of the
> class, or all instances?
> And why it needs to be so fast by keeping a direct reference to it?
>
> System browser could live well without it.
> Altering the metaclass definition? Well, iterate over all instances
> indiscriminately - using same mechanism as usual class doing for own
> instances.
> So, it is strange to me, why do we need such tight coupling..
>
> Is anyone having insights about it?

I'm interested in this because I'll be refactoring Class and Metaclass
soon (next year) for SecureSqueak. I've already got my own
Class/Metaclass hierarchies with no connections to the
SystemDictionary, which allows me to experiment without breaking
things.

The only requirement for a class by the VM is that instance variable 1
is another valid class (the superclass), instance variable 2 is a
valid method dictionary and instance variable 3 is a special "format"
integer. Otherwise you can add whatever you want; every other variable
is optional. You can make your own classes which have no name,
environment, pools and so forth - you'd just break the tools that
inspect them.

As for the tight coupling between class and metaclass, I guess it is
pragmatic. There's no real reason to separate them. If you want a
class with different instance-side methods but exactly the same
class-side methods as another class, then you'd use inheritance.
Because of the tight coupling, the instance variables in a Class or
Metaclass instance could be in either; it makes no difference.

Gulik.

--
http://gulik.pbwiki.com/

Reply | Threaded
Open this post in threaded view
|

Re: On class/metaclass coupling

Igor Stasenko
2009/12/9 Michael van der Gulik <[hidden email]>:

> On Wed, Dec 9, 2009 at 12:49 AM, Igor Stasenko <[hidden email]> wrote:
>> For people who think that we should not revise the class/metaclass
>> coupling in Squeak,
>> just ignore this topic and consider it as a rant :)
>>
>> For those, who interested why i think its not a perfect from
>> object-oriented point of view, continue reading.
>>
>> Ok. Lets start from basics.
>>
>> A classes, in smalltalk is a first class objects, which one of its
>> strong sides, comparing to other languages.
>> Since each object has a class, we also need an object which reflecting
>> the class itself, and hence the metaclass.
>>
>> But then, each class could have as many instances as it likes to, isnt?
>> But here the contradiction, which drives me nuts, when i looking at
>> Metaclass definition - 'thisClass' ivar.
>>
>> This implies that any metaclass could have only a single instance - class.
>>
>> Metaclass>>new
>>        "The receiver can only have one instance. Create it or complain that
>>        one already exists."
>>
>>        thisClass class ~~ self
>>                ifTrue: [^thisClass := self basicNew]
>>                ifFalse: [self error: 'A Metaclass should only have one instance!']
>>
>> but hey..
>> what you suppose to do with things like:
>>
>> SomeClass clone
>>
>> ?
>
> That should probably fail. Instead, use >>copy, which (I suspect)
> makes a new instance of Metaclass as well.
>
>> I am trying to understand, why do we need this inconsistency by
>> enforcing such a rigid rule.
>>
>> Like, how often you may need to determine a 'sole' instance of the
>> class, or all instances?
>> And why it needs to be so fast by keeping a direct reference to it?
>>
>> System browser could live well without it.
>> Altering the metaclass definition? Well, iterate over all instances
>> indiscriminately - using same mechanism as usual class doing for own
>> instances.
>> So, it is strange to me, why do we need such tight coupling..
>>
>> Is anyone having insights about it?
>
> I'm interested in this because I'll be refactoring Class and Metaclass
> soon (next year) for SecureSqueak. I've already got my own
> Class/Metaclass hierarchies with no connections to the
> SystemDictionary, which allows me to experiment without breaking
> things.
>
Good to know. SystemDictionary should die. Theory of Relativity is
something we should learn from :)
Universe has no central point. Every point in Universe is its center.

> The only requirement for a class by the VM is that instance variable 1
> is another valid class (the superclass), instance variable 2 is a
> valid method dictionary and instance variable 3 is a special "format"
> integer. Otherwise you can add whatever you want; every other variable
> is optional. You can make your own classes which have no name,
> environment, pools and so forth - you'd just break the tools that
> inspect them.
>

Yes. And i'm always thinking towards making things less heavyweight,
and keep only required minimal in class/behavior protocols that tools
should know about, instead of thousands and thousands of methods
implying tight coupling.

> As for the tight coupling between class and metaclass, I guess it is
> pragmatic. There's no real reason to separate them. If you want a
> class with different instance-side methods but exactly the same
> class-side methods as another class, then you'd use inheritance.

A single class denotes a family of objects, which can be instantiated
and have same behavior.
Inheritance creates a different family of objects by specialization.

The main problem with inheritance is that it doesn't solves any
problems, it only inheriting them.

Imagine a locomotive with bunch of wagons tied to id. The more wagons
you adding, the slower it become, no matter how powerful it was
initially.
What you proposing is adding another wagon to the train and expect
that it will run faster.


> Because of the tight coupling, the instance variables in a Class or
> Metaclass instance could be in either; it makes no difference.
>

Not sure i understood, what instance variables you talking about.
Any instance of class keeps reference back to a class through implicit
class slot in object header.
But class doesn't sees all of its instances directly, because its impractical.

Still, there is a protocol that supports an idea of having a way to
'see' all its instances (allInstancesDo:).
But to my thinking, this is an over-engineered stuff. Such kind of
reflection useful purely for mutating instances (after modifying the
class definition),
but its too slow and fragile to be used for any real-time tasks, since
it implies a linear scan of all objects in object memory. But new
objects could be created at any moment, a process which scans the heap
can be interrupted.. there are too much issues preventing this feature
to work fine. Unless you register every created instance in some sort
of collection and keep it in class's own ivar :)

Conserning instances mutation:
You, as a designer of secure-squeak, should know well about
problematics of class modification (especially mutation of its
instances). It should be prohibited. Instead, one should create a
modified copy, but never replace the old class by modified one and
never attempt to mutate exising instances.. otherwise you will be
unable to contaminate the numerous security problems.

> Gulik.
>
> --
> http://gulik.pbwiki.com/
>


--
Best regards,
Igor Stasenko AKA sig.