On 9/27/06, Andreas Jung lists@zopyx.com wrote:
It's definitely time to work on a replacement.
Yes. And here is my short vision of that. Comments are appreciated.
1. We have a base content class used to create content objects. This has the concept of type, pretty much like CMFs portal_type. The type is defined in the ZODB.
2. On the type you can set marker interfaces, that enables adapters with different functionality, such as indexing awareness, and whatnot. These adapters are written in diskbased pythons. Hence any type of basic functionality like this still needs to be disk-based.
3. Each type also has schemas and forms, templates and python scripts in the ZODB. The schemas and forms are to generate edit and create forms, the python scripts act like methods on a view, and the templates as, well, templates.
4. When you then run into a thing you can't do through the web you are not stuck. If you want to add new event handler for your type, you can write a new functionality adapter on disk, and then enable it via marker interfces for your type. If you python scripts security becomes a hindrance, you can easily move that to disk by making another marker interface and building views for that. We could even have a button "Export to disk module" which exports the current templates + scripts to a view + methods + templates all on disk.
This combines and easy plug-and-play attitude with TTW programming without providing a dead end.
Lennart Regebro wrote:
On 9/27/06, Andreas Jung lists@zopyx.com wrote:
It's definitely time to work on a replacement.
Yes. And here is my short vision of that. Comments are appreciated.
Have you looked at zope.app.schemacontent, Sidnei's prototype for TTW-schemas and content based on that?
- We have a base content class used to create content objects. This
has the concept of type, pretty much like CMFs portal_type. The type is defined in the ZODB.
Possibly. It's important to keep this content class really really dull ("one size fits all") so that we don't need to magically create persistent classes or something.
- On the type you can set marker interfaces,
Why not set marker interfaces directly on the objects? That whole "type" thing is unnecessary. Just use interfaces.
that enables adapters with different functionality, such as indexing awareness, and whatnot.
Yes and no. "catlaog awareness" is a Zope 2 thing, with the CA you'd use events.
These adapters are written in diskbased pythons. Hence any type of basic functionality like this still needs to be disk-based.
Except for views, perhaps. Simple template-based views could still be done through-the-web, perhaps even views that are implemented as Python Scripts.
- Each type also has schemas
Type, schema, and interfaces should be synonymous: interfaces. Don't invent more concepts than we already have.
and forms,
those can be automated from the schema
- When you then run into a thing you can't do through the web you are
not stuck.
Wrong. You write it in Python and register it locally for your "type" (read: interface).
If you want to add new event handler for your type, you can write a new functionality adapter on disk, and then enable it via marker interfces for your type.
No need for the marker interface. You already have your "type" interface. Just use that.
If you python scripts security becomes a hindrance, you can easily move that to disk by making another marker interface and building views for that. We could even have a button "Export to disk module" which exports the current templates + scripts to a view + methods + templates all on disk.
This combines and easy plug-and-play attitude with TTW programming without providing a dead end.
Hopefully.
So, when are you going to write it? :)
Thanks for the comments. For all the things you wrote that I deleted, I would just say "Exactly!" :-) Here are the things that are not "exactly!":
On 9/28/06, Philipp von Weitershausen philipp@weitershausen.de wrote:
Have you looked at zope.app.schemacontent, Sidnei's prototype for TTW-schemas and content based on that?
Nope. But thanks for the hint.
- On the type you can set marker interfaces,
Why not set marker interfaces directly on the objects? That whole "type" thing is unnecessary. Just use interfaces.
Because you want to be able to add a new functionality (by setting a new marker interface on the type), and get it added to all the objects that have that type. Of course, the type assignment would, I expect, in itself be done by a marker interface, but that's implementation details I don't want to think about yet. :-)
I was unfortunately talking too much implementation details. I should have tried to be more conceptual. From now on, I will call the functionality adapters for "aspects". :)
that enables adapters with different functionality, such as indexing awareness, and whatnot.
Yes and no. "catlaog awareness" is a Zope 2 thing, with the CA you'd use events.
Well, that was the one example I could think of just then, although I knew it was a crap one. I could think of specialized aspects, such as an aspect to automatically ping a site like del.icio.us when you post your bloggentry, but I couldn't think of anything truly generic. However, during this answer, I did think of something better: Workflows:
You could for example have an aspect for a simple publishing workflow. So if you enable this, the objects of the type gets a publishing workflow. And another aspect could enable the wmfc workflow module for the object, for example. (Which makes me realize that some aspects could need settings on the type... Hmmm...)
- Each type also has schemas
Type, schema, and interfaces should be synonymous: interfaces. Don't invent more concepts than we already have.
Nah, they should not be synonyms. But I was as mentioned mixing implementation and concepts before. I'll explain:
The people who use these new ZClasses want to be able to create content types that has forms with a set of fields and informations like if a field should be required or max length and stuff. They also want to be able to create specialized views, and enable "aspects" for the type, like saying that objects of this type should have this workflow.
They will never understand you if you call both the forms, and the views and the aspects for "interfaces", because although technically there are interfaces below all of this, the functionality in the end is wildly different, and the way you use it is also wildly different. How all this is implemented and attached to the object is nothing the user want to be aware of.
However, you may be right in that maybe one schema, and a set of views, in themselves should be an aspect, so that you do not assign these to types, but you create a form-aspect and a view-aspect, and assign these to the type.
- When you then run into a thing you can't do through the web you are
not stuck.
Wrong. You write it in Python and register it locally for your "type" (read: interface).
I think you missed a "not" there. :)
If you want to add new event handler for your type, you can write a new functionality adapter on disk, and then enable it via marker interfces for your type.
No need for the marker interface. You already have your "type" interface. Just use that.
Yes, and no. If I do that, I can't use the aspect for other types. Then I'm stuck with using it ONLY for that type. This may be what I want, or it may not be.
So, when are you going to write it? :)
My crystal ball blue-screened. :-)
Philipp von Weitershausen wrote at 2006-9-28 14:23 +0200:
... Why not set marker interfaces directly on the objects? That whole "type" thing is unnecessary. Just use interfaces.
Usually, a type is seen as a set of objects, its type instances.
It is quite nice to be able to work on a object set meta level rather than on individual objects....
Dieter Maurer wrote:
Philipp von Weitershausen wrote at 2006-9-28 14:23 +0200:
... Why not set marker interfaces directly on the objects? That whole "type" thing is unnecessary. Just use interfaces.
Usually, a type is seen as a set of objects, its type instances.
It is quite nice to be able to work on a object set meta level rather than on individual objects....
Sure, though I don't see how an interface can't represent this meta level. Perhaps I'm missing an important point here...
Philipp von Weitershausen wrote at 2006-9-29 01:35 +0200:
Dieter Maurer wrote:
Philipp von Weitershausen wrote at 2006-9-28 14:23 +0200:
... Why not set marker interfaces directly on the objects? That whole "type" thing is unnecessary. Just use interfaces.
Usually, a type is seen as a set of objects, its type instances.
It is quite nice to be able to work on a object set meta level rather than on individual objects....
Sure, though I don't see how an interface can't represent this meta level. Perhaps I'm missing an important point here...
You want to stick this interface to individual objects, while Lennart proposed to stick it to a type and use some kind of inheritance to make it effective on all objects instantiated from this type.
For me, Lennart's approach seems to be far more economic, as he does things on an abstract (the type) level rather than always work on the concrete (the individual object) level.
On 9/29/06, Dieter Maurer dieter@handshake.de wrote:
You want to stick this interface to individual objects, while Lennart proposed to stick it to a type and use some kind of inheritance to make it effective on all objects instantiated from this type.
For me, Lennart's approach seems to be far more economic, as he does things on an abstract (the type) level rather than always work on the concrete (the individual object) level.
In fact it is absolutely necessary, as you want to be able to change the behaviour of a whole type of content classes. If you create the content class "Events" and then suddenly want all events to have a iCal export support, you do not want to enable this per event, but for the type "event".
The type is thusly equivalent to portal types of CMF.
Lennart Regebro wrote:
On 9/29/06, Dieter Maurer dieter@handshake.de wrote:
You want to stick this interface to individual objects, while Lennart proposed to stick it to a type and use some kind of inheritance to make it effective on all objects instantiated from this type.
For me, Lennart's approach seems to be far more economic, as he does things on an abstract (the type) level rather than always work on the concrete (the individual object) level.
In fact it is absolutely necessary, as you want to be able to change the behaviour of a whole type of content classes. If you create the content class "Events" and then suddenly want all events to have a iCal export support, you do not want to enable this per event, but for the type "event".
That doesn't make it necessary. Let's say all event objects are marked with IEvent. Now you want to add behaviour to events. You can do that by registering stuff for IEvent. All objects marked with IEvent will get the new behaviour.
Why would a type be needed?
The type is thusly equivalent to portal types of CMF.
Types in Zope 3 are typically expressed by interfaces. I think all of your use cases can be covered with just interfaces. No need to invent yet another thing that you'll have to persist and create machinery for.
Dieter Maurer wrote:
Philipp von Weitershausen wrote at 2006-9-29 01:35 +0200:
Dieter Maurer wrote:
Philipp von Weitershausen wrote at 2006-9-28 14:23 +0200:
... Why not set marker interfaces directly on the objects? That whole "type" thing is unnecessary. Just use interfaces.
Usually, a type is seen as a set of objects, its type instances.
It is quite nice to be able to work on a object set meta level rather than on individual objects....
Sure, though I don't see how an interface can't represent this meta level. Perhaps I'm missing an important point here...
You want to stick this interface to individual objects, while Lennart proposed to stick it to a type and use some kind of inheritance to make it effective on all objects instantiated from this type.
But where does this type come from? Persistent classes are hard (hence ZClasses cannot be maintained by anyone except a few people).
For me, Lennart's approach seems to be far more economic, as he does things on an abstract (the type) level rather than always work on the concrete (the individual object) level.
I don't see how introducing another concept (a type) would be more economic. It'd be one more thing to worry about wrt persistency etc.
Philipp von Weitershausen wrote at 2006-9-30 02:30 +0200:
...
You want to stick this interface to individual objects, while Lennart proposed to stick it to a type and use some kind of inheritance to make it effective on all objects instantiated from this type.
But where does this type come from? Persistent classes are hard (hence ZClasses cannot be maintained by anyone except a few people).
I remember that Jim proposed "PersistentModule"s, currently a ZODB proposal, to implement functionality similar to ZClasses in an easier way.
But, I cannot yet answer your question sincerely.
For me, Lennart's approach seems to be far more economic, as he does things on an abstract (the type) level rather than always work on the concrete (the individual object) level.
I don't see how introducing another concept (a type) would be more economic.
I find that the introduction of classes with (multiple) inheritance has been very economic. It was another concept but a highly fruitful one, despite the fact that they are not so liked in Zope3 land.
As a former mathematician, I also like the introduction of abstraction layers (object -> type/class -> metatype/metaclass -> ...) as abstraction often drastically increases economicity.
It'd be one more thing to worry about wrt persistency etc.
Your answer to Lennart made me a bit unsure.
It appears as if an interface could live on different abstraction levels -- at least together with ZCML and adapter magic.
I am not yet really familiar with this. Let's see what Lennart answers.
Dieter Maurer wrote:
Philipp von Weitershausen wrote at 2006-9-30 02:30 +0200:
...
You want to stick this interface to individual objects, while Lennart proposed to stick it to a type and use some kind of inheritance to make it effective on all objects instantiated from this type.
But where does this type come from? Persistent classes are hard (hence ZClasses cannot be maintained by anyone except a few people).
I remember that Jim proposed "PersistentModule"s, currently a ZODB proposal, to implement functionality similar to ZClasses in an easier way.
But, I cannot yet answer your question sincerely.
I can't either. If we ever get persistent code, that's nice, but I'd still be skeptical. Frankly, I think it's yagni ("you ain't gonna need it"). And if I understood Jim correctly, he nowadays prefers the "code is on the filesystem and we evolve datastructures using generations" story over "code and datastructures are persistent so that both can be evolved at the same time".
For me, Lennart's approach seems to be far more economic, as he does things on an abstract (the type) level rather than always work on the concrete (the individual object) level.
I don't see how introducing another concept (a type) would be more economic.
I find that the introduction of classes with (multiple) inheritance has been very economic. It was another concept but a highly fruitful one, despite the fact that they are not so liked in Zope3 land.
I think "fat" objects from mixing many different concerns into a single implementation are a failed approach. Seeing how flexible you can be wit
a) separating concerns (functionality, responsibilities) into separate objects called components and
b) making the lookup of these components pluggable (using registries a.k.a. the Component Architecture),
I would not recommend anyone to over-use multiple inheritance as it's been done in Zope 2. That is not to say that inheritance and even multiple inheritance is evil. I think the right balance is necessary :)
Philipp von Weitershausen wrote at 2006-10-7 23:51 +0200:
...
I find that the introduction of classes with (multiple) inheritance has been very economic. It was another concept but a highly fruitful one, despite the fact that they are not so liked in Zope3 land.
I think "fat" objects from mixing many different concerns into a single implementation are a failed approach.
Seeing how flexible you can be wit
a) separating concerns (functionality, responsibilities) into separate objects called components and
b) making the lookup of these components pluggable (using registries a.k.a. the Component Architecture),
I am almost convinced that in some years these registries will share the fate of acquisition: they will be seens as too much magic.
I expect this to happen as soon as Zope3 is becoming main stream and not only used by the fittest people.
I would not recommend anyone to over-use multiple inheritance as it's been done in Zope 2.
I am a strong favorite of (multiple) inheritance and use it excessively. I have the feeling that it makes me very productive.
--On 9. Oktober 2006 19:11:55 +0200 Dieter Maurer dieter@handshake.de wrote:
I would not recommend anyone to over-use multiple inheritance as it's been done in Zope 2.
I am a strong favorite of (multiple) inheritance and use it excessively. I have the feeling that it makes me very productive.
We have some code where some classes have up to 15(!) base classes (usually mixin classes), not counting classes inherited from the mix-in classes. I would call that unmanageable. Personal productivity is one side of the medal, readability and understandability of code for other team member is the other side of the medal. Although I am not the biggest fan of the component architecture I have to admit that it makes a lot of things clearer and cleaner.
-aj
Andreas Jung wrote at 2006-10-9 19:24 +0200:
... We have some code where some classes have up to 15(!) base classes (usually mixin classes), not counting classes inherited from the mix-in classes. I would call that unmanageable.
Each of these classes represent a mixed in feature. You get 15 classes because the end result needs a lot of features.
Manageability does not increase when you implement the features differently than listing them in the inheritance clause.
Dieter Maurer wrote:
Philipp von Weitershausen wrote at 2006-10-7 23:51 +0200:
...
I find that the introduction of classes with (multiple) inheritance has been very economic. It was another concept but a highly fruitful one, despite the fact that they are not so liked in Zope3 land.
I think "fat" objects from mixing many different concerns into a single implementation are a failed approach.
Seeing how flexible you can be wit
a) separating concerns (functionality, responsibilities) into separate objects called components and
b) making the lookup of these components pluggable (using registries a.k.a. the Component Architecture),
I am almost convinced that in some years these registries will share the fate of acquisition: they will be seens as too much magic.
Perhaps. That's to be seen.
For one, the CA's registries are much less magic because look-up is always explicit (as opposed to the implicit acquisition as its widely used in Zope 2).
I expect this to happen as soon as Zope3 is becoming main stream and not only used by the fittest people.
This is indeed a good point. There are currently efforts to make Zope 3 easier for simpler use cases that wouldn't involve dealing with those registries, at least not directly. In fact, we're having a sprint on this topic this month.
I would not recommend anyone to over-use multiple inheritance as it's been done in Zope 2.
I am a strong favorite of (multiple) inheritance and use it excessively. I have the feeling that it makes me very productive.
That's good. Again, I think multiple inheritance is a valid tool. One reason why I would advise against using is excessively, though, is the lack of pluggability. The way Zope 2 deals with APIs, for example, makes hard to reuse and customize existing components. Sure, you CAN try to reuse stuff (and I know some of your tools, e.g. rebindFunction et.al. from ReuseUtils), but most of these revolve more around implementation details than around well-defined APIs and responsibilities.
Philipp von Weitershausen wrote at 2006-10-9 19:59 +0200:
... Sure, you CAN try to reuse stuff (and I know some of your tools, e.g. rebindFunction et.al. from ReuseUtils), but most of these revolve more around implementation details than around well-defined APIs and responsibilities.
This must mean "most of those you know of" and not "most of my tools" :-)
On 9/30/06, Philipp von Weitershausen philipp@weitershausen.de wrote:
But where does this type come from? Persistent classes are hard (hence ZClasses cannot be maintained by anyone except a few people).
I'm hopeful that this can be solved without actually reverting to that kind of magic.
I don't see how introducing another concept (a type) would be more economic. It'd be one more thing to worry about wrt persistency etc.
Well, then we won't come further in that discussion. The type is absolutely necessary for functionality, and as concept to make it understandable.
That doesn't make it necessary. Let's say all event objects are marked with IEvent. Now you want to add behaviour to events. You can do that by registering stuff for IEvent. All objects marked with IEvent will get the new behaviour.
Why would a type be needed?
You are again mixing implementation details and principles. In your example here IEvent is the type. In my first mail I was also mixing implementation details and principles, I hope to have since rectified that.
Types in Zope 3 are typically expressed by interfaces.
Yes, and that would most likely be the case here too. Most likely which "type" and object is would be expressed by letting that object have a specific interface. This does not make "interface" and "type" conceptually equal.
As I mentioned before, if you tell a site administrator that he can create interfaces which enables adapters, factories and more interfaces, he will not understand what that means, or why he would want it or how to do it.
If you tell him that he can create types, on which he can enable functionality and create views and pages, than he will understand.
We can't call everything "interfaces", no matter how we use them and expect people to understand us.
Lennart Regebro wrote:
Types in Zope 3 are typically expressed by interfaces.
Yes, and that would most likely be the case here too. Most likely which "type" and object is would be expressed by letting that object have a specific interface. This does not make "interface" and "type" conceptually equal.
As I mentioned before, if you tell a site administrator that he can create interfaces which enables adapters, factories and more interfaces, he will not understand what that means, or why he would want it or how to do it.
If you tell him that he can create types, on which he can enable functionality and create views and pages, than he will understand.
We can't call everything "interfaces", no matter how we use them and expect people to understand us.
Ok, sure. Then we agree. The 'type' would be a special kind of interface. It's a concept, rather than an implementation detail (e.g. like 'view' is an adapter).