components via meta-data?

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

components via meta-data?

Sophie424
Apologies for this long post from a newbie. I was trying out Adrian
Lienhard's Mewa with Seaside and it seems Mewa has languished. I was curious
what knowledgable Seasiders thought of the following.

QUESTION: Can we build very smart Seaside components automatically from
meta-data of the domain objects, and still require a very small amount of
meta-data for customized components?

What's different about these "Components"?
=========================================

Nothing changes on the interface between the Component and sessions,
browsers, etc. However, each component in that tree is connected to domain
objects via a meta-layer. This meta-layer provides a uniform (structural)
reflective interface to all domain objects, their attribute values, and
their operations including parameters and calling constraints, so that
generic view and editor components can operate through this interface.

What is this meta-layer?
========================

Components in successive levels of the component tree are (STRICTLY)
attached to either
  - (meta)objects or
  - (meta)attributes of those object, or
  - (meta)operations on those objects

A meta-object (in this discussion) is NOT a class; rather, it is a
proxy-like object carrying meta-information for a specific domain object
(instance). (The "meta" terminology comes from Mewa).

A meta-attribute is an object carrying meta-information for the value of a
specific attribute of a specific object.

A meta-operation is an object carrying meta-information for a specific
operation that might be invoked on a specific object.

In combination these three carry all the information needed to construct
components.

The attached pictures from the Mewa paper show the essential idea (but don't
include the meta-attributes and meta-operations).

None of these meta-things need db-level persistance, they might use
session-level persistence. Below is pseudo-Ruby code (sorry, I am not yet
fluent in Smalltalk):

class MetaObject
  # mostly acts as a proxy to obj, adding meta-information
  has_one :obj, Object
  has_many :attributes, MetaAttribute
  has_many :operations, MetaOperation
  def renderHtmlOn: html
    # walk attributes to structure views
    # walk operations to structure buttons/anchors/editors/...even wizards
  end
end

class MetaAttribute
  # a slot value of a domain object i.e. obj + attr + value
  # or, a slot + value of an operation on an object (op + param + value)
  has_one :attribute, Symbol
  has_one :type, Class # or duck-type
  has_one :multiplicity, Symbol
    # :attribute, :type, :mult should be shared via class level Attribute
    # I've just stuffed them here, just easier to understand this way

  has_one :owner, Object # domain obj or a MetaOperation (below)

  def value
    owner.instance_variable_get attribute # or #send...
  end
  def replace (replacement_obj)
    # illustrative only
    owner.send "#{attribute.to_s}=", replacement_obj
  end
  def add (added_obj)
    # illustrative; only defined if attr is a collection
    owner.send "add_to_#{attribute.to_s}", added_obj
  end
end

class MetaOperation
  # an operation-to-be-called on an object
  #
  has_one :operation, Symbol
  has_many :params, MetaAttribute
    # tracks param name, type, multiplicity, etc.
    # Used to populate (d)html accordingly
    # including using the smarts below
    # :operation and :params could be shared via class level Operation

  has_one :owner, Object

  has_many :current_values, Hash
    # current user-selected param values, hashed by param_symbol

  # for populating of parameter candidates e.g. a drop-down list
  #   may be used via Ajax, including current parameter selection
  def candidates_for (param)
    owner.candidates_for operation, param, curr_values
  end

  # for enabling of operations e.g. menu or button enabling
  #   may be used via Ajax, including current parameter selection
  def invocable?
    owner.invocable? (operation, current_values)
  end

  def invoke
    owner.send operations, current_values
  end

end

Example meta-layer instance
===========================

Assume there is a component tree consisting of nested viewers and editors.

On demand, build metadata about domain objects that these viewers and
editors connect to, including the attributes and relations of these domain
objects. Make that metadata structure uniformly as follows:
  m_obj
    m_attr
      m_obj
      m_obj
    m_attr...
    m_op1
      m_attr...
      m_attr...
    m_op2

So if I have objects
  joe=Person.new
  joe.name = "Joe"
  home=House.new(:address=>"123 hometown")
  joe.add_house home
  vacation_home = House.new
  joe.add_house vacation_home
  room1 = Room.new
  room2 = Room.new
  home.add_room room1
  home.add_room room2

  bob=Person.new
  joe.add_friend bob

Then a view or editor *on joe* will create and use this metadata structure:

  joe -- meta-object
    joe#name -- meta-attribute
    joe#name= -- meta-operation
    joe#houses -- meta-attribute
      home -- meta-object
        home#address -- meta-attribute
          "123 hometown" -- metaobject, optimized away
        home#rooms -- meta-attribute
          room1 -- meta-object
          room2
      vacation_home
    joe#friends
      bob


Example Component Tree
======================

CLAIM: The component tree should exactly parallel this metaobject and
metaattribute structure (by default). So here are the components in that
tree, and the (meta)-things they connect to:

person_viewer --> joe
  #houses_viewer --> joe#houses
    house_viewer --> home
      #address_viewer --> home#address
        address_viewer --> "123 hometown"
      #rooms_viewer --> home#rooms

        room_viewer --> room1

        room_editor --> room2#modify
           new_size --> room2#modify.new_size

    house_viewer --> vacation_home
  #friends_viewer --> joe#friends
    person_viewer --> bob

As always, some of the elements in the above tree might change dynamically
with Ajax e.g. a viewer might be replaced by an editor when the little
"edit" link is clicked; but the editor would still be attached to the same
meta-instance.

I believe all the components in this tree could be generic by default, all
the meta-objects constructed automatically given a few meta-data hints.

Not sure how Seaside deals with Ajax right now, but we might need some event
machinery between the tree and domain objects so an (Ajax) operation that
replaced one component might also update other parts of related components
in the tree. Ajax-induced updates would propagate up to the tree root
collecting component updates, before going back to the client.

CSS
===

Seaside components can be reused wonderfully, including embedding them in
others. But if CSS is only provided at the page level, would it make sense
for a component to (somehow) compose the CSS of its parts? We could
eliminate some CSS warts while at it
http://lunchroom.lunchboxsoftware.com/articles/2005/08/19/rcss-anyone, and
with a few restrictions still retain client caching etc. Far less important
than the component ideas above, though.


Thoughts? Am I talking nonsense?

Thanks.

_______________________________________________
Seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside

mewa.png (9K) Download Attachment
mewa2.png (15K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: components via meta-data?

Lukas Renggli
Hi ItsYou,

> QUESTION: Can we build very smart Seaside components automatically from
> meta-data of the domain objects, and still require a very small amount of
> meta-data for customized components?

Yes. Several people have done this for public and commercial projects.
Another such project available in public is Magritte, see:

http://www.lukas-renggli.ch/smalltalk/magritte
http://www.iam.unibe.ch/~scg/Archive/Diploma/Reng06a.pdf

>   - (meta)operations on those objects

Mewa doesn't support that. For Magritte this is only supported on a
very basic level, such as for comparison operators, though it is
definitely feasible on a more generic level.

> A meta-object (in this discussion) is NOT a class; rather, it is a
> proxy-like object carrying meta-information for a specific domain object
> (instance). (The "meta" terminology comes from Mewa).

I would not call that proxy, a proxy is something that is on the same
meta level than the proxied object. A proxy represents the proxied
object. It is rather a type object.

> A meta-attribute is an object carrying meta-information for the value of a
> specific attribute of a specific object.

In Magritte attributes and objects are unified, since an attribute is
an object again. I don't see why the separation of those would be a
benefit, maybe there is a good reason?

> A meta-operation is an object carrying meta-information for a specific
> operation that might be invoked on a specific object.

OMG provides such a model called EMOF. Especially your code looks a
lot like EMOF. When I started with Magritte I didn't know about this
model, however I will try adapt Magritte to bring it closer to EMOF
with the next major version. So far the evolution of Magritte was
solely driven by requirements we had when developing new Web
applications.

> In combination these three carry all the information needed to construct
> components.

I don't think so. My experience shows that this only works for very
simple user interfaces and very simple domain models without much
semantics and behvior, such as for an editor/viewer of a relational
database.

> Assume there is a component tree consisting of nested viewers and editors.

Magritte builds such trees, but allows you to customize any aspect of
the generation, this is to manually display or change the default
behavior using Smalltalk code. I think the possibility to do this is
key to a meta-level framework that should be usable in different
contexts.

>   joe -- meta-object
>     joe#name -- meta-attribute
>     joe#name= -- meta-operation
>     joe#houses -- meta-attribute
>       home -- meta-object
>         home#address -- meta-attribute
>           "123 hometown" -- metaobject, optimized away
>         home#rooms -- meta-attribute
>           room1 -- meta-object
>           room2
>       vacation_home
>     joe#friends
>       bob

Both, Mewa and Magritte can do that. I am missing how the behavior
fits in there you described at the beginning of your mail.

> CLAIM: The component tree should exactly parallel this metaobject and
> metaattribute structure (by default). So here are the components in that
> tree, and the (meta)-things they connect to:

The parallelity does not work in general as I explained above.

> As always, some of the elements in the above tree might change dynamically
> with Ajax e.g. a viewer might be replaced by an editor when the little
> "edit" link is clicked; but the editor would still be attached to the same
> meta-instance.

I have such an extension for Magritte, though it is (currently) only
used in a commercial project.

> I believe all the components in this tree could be generic by default, all
> the meta-objects constructed automatically given a few meta-data hints.

This doesn't work either. People need custom components for custom projects.

> Not sure how Seaside deals with Ajax right now, but we might need some event
> machinery between the tree and domain objects so an (Ajax) operation that
> replaced one component might also update other parts of related components
> in the tree. Ajax-induced updates would propagate up to the tree root
> collecting component updates, before going back to the client.

http://scriptaculous.seasidehosting.st

Cheers,
Lukas

--
Lukas Renggli
http://www.lukas-renggli.ch
_______________________________________________
Seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: components via meta-data?

Sophie424
Hi Lukas,

> Hi ItsYou,

er, that would be "itsme" :-)

> Another such project available in public is Magritte,

That looks great!

>>   - (meta)operations on those objects
>
> Mewa doesn't support that. For Magritte this is only supported on a
> very basic level, such as for comparison operators, though it is
> definitely feasible on a more generic level.

OK.

>> A meta-object (in this discussion) is NOT a class; rather, it is a
>> proxy-like object carrying meta-information for a specific domain object
>> (instance). (The "meta" terminology comes from Mewa).
>
> I would not call that proxy, a proxy is something that is on the same
> meta level than the proxied object. A proxy represents the proxied
> object. It is rather a type object.

The usual multipicity of typeObject:object is 1:N. Not so for these
meta-objects. I prefer to call them "objectReflections", see below.

>> A meta-attribute is an object carrying meta-information for the value of
>> a
>> specific attribute of a specific object.
>
> In Magritte attributes and objects are unified, since an attribute is
> an object again. I don't see why the separation of those would be a
> benefit, maybe there is a good reason?

But an attribute is NOT an object. The #value of an attribute, for a
specific owner object, IS an object. This is a big difference.

Suppose
  joe home = 111USA
then
joe metaAttributeFor: #home  , or
joe attributeReflectionFor: #home
  is an object that encapsulates
    owner = joe
    attr = #home
    value = 111USA

e.g. the object 111USA would know nothing about the label "home", but the
metaAttribute would.

This can also provide a single context for creating objects. The
Meta-properties of an attribute include "own / create: Boolean". This
attribute should be orthogonal to the multiplicity property (a mistake in
Mewa, imo). Every domain object is created in the context of such a
meta-attribute, and is automatically owned by the owner of that attribute.
There is no need for special treatment of the object collections of the
top-level domain object, just give it some "own/create" attributes. This
works cleaner and more uniformly than the current Mewa example.

One can sometimes force this onto the object, but this is often a mistake.
e.g. if I have a class Person, each person can play many different roles
(e.g. referred via attributes of other objects): author, father, project
manager, ...

>> A meta-operation is an object carrying meta-information for a specific
>> operation that might be invoked on a specific object.
>
> OMG provides such a model called EMOF. Especially your code looks a
> lot like EMOF.

If I have joe with operation >>walk, then I have as many instances of the
meta-operation >>walk on joe, as I have components that might invoke >>walk
on joe.

EMOF does not have such a concept, afaik. Perhaps it is not sufficiently
informed by Smalltalk-ish concepts like closures :-)

I don't really like the use of the word 'meta' here either, just borrowed
what Mewa used. I prefer something like:
- objectReflection
- attributeReflection
- operationReflection

> When I started with Magritte I didn't know about this
> model, however I will try adapt Magritte to bring it closer to EMOF

Good to know, there may be tools you can then leverage.

>> In combination these three carry all the information needed to construct
>> components.
>
> I don't think so. My experience shows that this only works for very
> simple user interfaces and very simple domain models without much
> semantics and behvior, such as for an editor/viewer of a relational
> database.

Don't you think using operationReflection (expanded, of course) more fully
could improve this? The kinds of patterns that show up in these semantics
and behaviors are amenable to this, imho.

>>   joe -- meta-object
>>     joe#name -- meta-attribute
>>     joe#name= -- meta-operation
>>     joe#houses -- meta-attribute
>>       home -- meta-object
>>         home#address -- meta-attribute
>>           "123 hometown" -- metaobject, optimized away
>>         home#rooms -- meta-attribute
>>           room1 -- meta-object
>>           room2
>>       vacation_home
>>     joe#friends
>>       bob
>
> Both, Mewa and Magritte can do that. I am missing how the behavior
> fits in there you described at the beginning of your mail.

See joe#name=. I should have shown more operationReflection in the example.
e.g.

(joe houses at: 1) metaOperationFor: #sell
could be another operationReflection.

These operationReflections correctly encapsulate parameters required,
currently chosen of parameter values, available selections of parameter
values, enabling/disabling of the operation, etc.

>> CLAIM: The component tree should exactly parallel this metaobject and
>> metaattribute structure (by default). So here are the components in that
>> tree, and the (meta)-things they connect to:
>
> The parallelity does not work in general as I explained above.

Hmm. Why not? There is a DOM-tree in the browser, and a parallel component
tree in the server. All I am suggesting is that every node of the component
tree be one of:
- objectNode -- attached to an objectReflection
- attributeNode -- attached to an attributeReflection
- operationNode -- attached to an operationReflection

>> As always, some of the elements in the above tree might change
>> dynamically
>> with Ajax e.g. a viewer might be replaced by an editor when the little
>> "edit" link is clicked; but the editor would still be attached to the
>> same
>> meta-instance.
>
> I have such an extension for Magritte, though it is (currently) only
> used in a commercial project.

Any plans to release it?

Is Magritte very experimental, or tested and robust?

>> I believe all the components in this tree could be generic by default,
>> all
>> the meta-objects constructed automatically given a few meta-data hints.
>
> This doesn't work either. People need custom components for custom
> projects.

True. Hopefully small, encapsulated deltas that can be composed. Once we
work at the meta-level we need a set of operations to compose these
meta-objects as objects and derive their resulting composite properties,
including propagating defaults, overriding, adding/appending, etc. just like
class inheritance is largely hard-coded today into class structure.

>> Not sure how Seaside deals with Ajax right now, but we might need some
>> event
>> machinery between the tree and domain objects so an (Ajax) operation that
>> replaced one component might also update other parts of related
>> components
>> in the tree. Ajax-induced updates would propagate up to the tree root
>> collecting component updates, before going back to the client.
>
> http://scriptaculous.seasidehosting.st

Looks nice!

Cheers,

Itsme :_)

_______________________________________________
Seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside