You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@avalon.apache.org by Anton Tagunov <at...@mail.cnt.ru> on 2003/06/10 10:15:10 UTC

[Proposal] WriteProtectable/ReadOnly interfaces

Hi, All!

I think that we have got one more interface
crystalized in our works:

    public interface WriteProtectable
    {
        void makeReadOnly();
    }

As I will show later it also needs a twin
marker interface ReadOnly:

    public interface ReadOnly
    {
    }

For instance DefaultServiceManager is WriteProtectable
while FortressServiceManager is ReadOnly.

-------------

This interfaces are proposed to have a XXXUtil.makeReadOnly()
method to operate them: (a sketch)

    public void makeReadOnly( Object obj )
    {
        if ( obj instanceof WriteProtectable )
        {
            ((WriteProtectable)obj).makeReadOnly();
        }
        else if ( obj instanceof ReadOnly )
        {
            //do nothing
        }
        else
        {
            throw new IllegalArgumentException( "..." );
        }
    }

--------------

This methods may be usefull when we extend any kind of
class via subcalssing, f.e. a container or a component.

Here's a usage example:

    class Abstract
    {
        protected void initializeGreat()
        {
            m_great = createGreat();
            XXXUtil.makeReadOnly( m_great );
        }
    
        protected Great createGreat()
        {
            DefaultGreat great = new DefaultGreat();
            great.put( foo );
            great.put( bar );
            return great;
        }
    }

    class Derived extends Abstract
    {
        protected Great createGreat()
        {
            Great parent = super.createGreat();
            final DefaultGreat great;
            if ( parent instanceof DefaultGreat )
            {
                great = (DefaultGreat) parent;
            }
            else
            {
                great = new DefaultGreat( parent );
            }
            great.put( blah );
            return great;
        }
    }


--------

Great could be Context, ServiceManager, etc.

--------

This mail is on introduction of WriteProtectable/ReadOnly.
Do you think it's a good idea to put them somewhere to the
framework, say o.a.a.f.writeprotection (bad name :-((  )
and make all the classes that have a makeReadOnly() method
implement WriteProtectable?

--------

Where can XXXUtil.makeReadOnly() go?
(My other mail is on a similar subject,
XXXUtil.get( context,key,defaultValue ), where can that go?
Should they both go to one class? Where can it live?)

WBR, Anton


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Proposal] WriteProtectable/ReadOnly interfaces

Posted by Berin Loritsch <bl...@apache.org>.
Niclas Hedhman wrote:
> On Tuesday 10 June 2003 04:47 am, Anton Tagunov wrote:
> 
>>Hello Niclas!
>>
>>NH> Could you provide some reasoning around what you are trying to achieve?
>>Sure :-)
> 
> 
> I think the others have said enough (paradoxically),
> 
> a) It is too generic to be part of Framework, put in java.lang
> b) It is too specific to be part of Framework, be part of the container impl.
> 
> At least, you got to exercise your argumental skills. This is a very 
> argumentative forum...

We are trying to get better about that...

I think Monty Python had a schtick about it.

Seriously, there is a difference between arguing and collaborating
to achieve a goal.  That is why I let Anton know the reasons why
we are protective of certain code bases.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Proposal] WriteProtectable/ReadOnly interfaces

Posted by Niclas Hedhman <ni...@hedhman.org>.
On Tuesday 10 June 2003 04:47 am, Anton Tagunov wrote:
> Hello Niclas!
>
> NH> Could you provide some reasoning around what you are trying to achieve?
> Sure :-)

I think the others have said enough (paradoxically),

a) It is too generic to be part of Framework, put in java.lang
b) It is too specific to be part of Framework, be part of the container impl.

At least, you got to exercise your argumental skills. This is a very 
argumentative forum...


Niclas


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re[2]: [Proposal] WriteProtectable/ReadOnly interfaces

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello Niclas!

NH> Could you provide some reasoning around what you are trying to achieve?
Sure :-)

NH> You want to have a way to force that an object can no longer be modified, 
NH> after some point in time. The ReadOnly interface is intended as a marker that 
NH> an object can not be modified, and the WriteProtectable is an interface to 
NH> "turn on" the ReadOnly functionality.
yep!

NH> Provided this is the case, why do you need to "pollute" the Avalon Framework
NH> interfaces with such a construct?
only because I want to make all the classes that belong
to the framework that have .makeReadOnly() method to
implement this interface

NH> How do you see that the containers need to be involved in this scheme at all?
<disclaimer>I must confess I have been working only with Fortress,
so my experience is limited, and I will talk only about
Fortress</disclaimer>

I think that this will have its use in Fortress for instance.
The thing is that for for instance currently the AbstractContianer has
the following methods (submitted by me, that's why I concentrate
on them :-)

    protected ServiceManager provideServiceManager( final ServiceManager parent )
            throws ServiceException
    {
        return new FortressServiceManager( this, parent );
    }

    protected Context provideComponentContext( final Context parent )
            throws Exception
    {
        /* the default implementation: just use the same as for container itself */
        return parent;
    }

these are the extension points. Derived containers may override these
methods to deliver a different ServiceManager and/or Context to child
components.

Currently it is all okay, it is easy to subclass and override these
methods. But imagine that our subclassing hierarchy is going to
be one level deeper:

AbstractContainer - > DefaultContainer - > Custom0 - > Custom1

Imagine Custom0 overrides provideComponentContext:
    // in Custom0
    protected Context provideComponentContext( final Context parent )
            throws Exception
    {
        DefaultContext context = new DefaultContext( parent );
        context.put( "foo", "bar" );
        context.makeReadOnly();
        return context;
    }

then in Custom1 we want to override this:
    // in Custom1
    protected Context provideComponentContext( final Context parent )
            throws Exception
    {
        DefaultContext context = DefaultContext( parent );
        context.put( "blah", "blah" );
        context.makeReadOnly();
        return context;
    }

The thing I do not like about this is that the
hierarchies may get quite deep. I would personally
prefer
    // in Custom1
    protected Context provideComponentContext( final Context parent )
            throws Exception
    {
        DefaultContext context;
        if ( parent instanceof DefaultContext )
        {
            context = (DefaultContext) parent ;
        }
        else
        {
            context = new DefaultContext( parent );
        }
        context.put( "blah", "blah" );
        return context;
    }

and there is only one reason why this can not be done now:
by the moment Custom1.provideComponentContext gets 'parent'
it has already been made read-only.

The solution is not to make it read-only in

    custom0.provideComponentContext()

But when to make it read only then?

My answer is: at the very top, in AbstractContainer.
But we may do that only if we know what exact type
has been returned to us, _or_ if the object returned
implements a special interface providing such method.

We already know that there is Keel framework based on
Avalon that surely provides its own ServiceManager
to child components, KeelServiceManager. It is easy
to imagine that Keel's container will be subclassed
further in applications of Keel framework. So the
hierarchies I have described are not only quite
feasible but even likely to appear.

Then, I beleive that this is a sufficiently general
problem: pattern FactoryMethod is extremely widely
used (and this is what I address). And I beleive
that it will be a common desire (getting back to
our example) not to replace the code in

    super.provideComponentContext()

blindly overriding parent's implementation, but
to get something that parent has created and
slightly modify it. See Fortress

    initializeServiceManager() in
    ContextManager.java

for another example. Users won't be able to
completely replace it (or they will have to replicate
all the code from our implementation which will
be a bad idea from the maintenance point of view).

And it may be impractical
to chain serverl DefaultServiceManagers one on
top another only to override one or two entries.

_If_ the WriteProtectable interface will be introduced
(as I propose) then an overriden implementation of any
factory method will be able to call the parent's
implementation and provided it knows precisely what
type of object the parent generates it will be able to
modify _that_ object without wrapping it.


I beleive this may be a common enough applicaiton
of "Factory Method" patter. Shall we call it
"Augmented Factory Method"? ;-)


To rely on the type of object returned from parent
is still better then to copy and paste code from
parent. And even if this knowledge falls out of
date, the overriden implementation of factory
method may always fall back to the "good old"
wrapping strategy _if_ the runtime type check fails
(like in my examples).

NH> Is there a "time"/"sequence" constraint on when
NH> a WriteProtectable turns into a ReadOnly?
err..., now _I_ may be the one who does not understand :-)
I would reply to this that WriteProtectable never changes
into a ReadOnly as only one of these interfaces may
be implemented by a particular object, but I must have
misunderstood the question. The invoker of the factory
method descides when to make the object returned
from the factory method readOnly.

The reason I'm introducing ReadOnly at the same time
as WriteProtectable is that I want an XXXUtil.makeReadOnly
method to function like this:

if ( obj instanceof WriteProtectable ) { ... .makeReadOnly() }
else if ( obj instance of ReadOnly ) { /*do nothing*/ }
else { throw new IllegalArgumentException( "neither WP nor RO" ); }

the reason to want this is to enforce security.
Unless an object has provided a method to make it readonly
(implements WriteProtecteable)
or has been marked as being ReadOnly by nature
(FortressServiceManager - we can only read data from
it, not write)
then this object _may_ be read-write - the author of
this object just did not care about this.
Hence we do not want this object, it's insecure, we
want to blow up.

NH> You mention that it would be used on ServiceManagers, but if the 
NH> ServiceManager user does not need to know, then it is an implementation 
NH> detail and irrelevant to Framework.
I hope that my examples above have shown that althoug
users by no means have to know if their ServiceManager is
WriteProtectable or ReadOnly or anything, the
fortress/impl/AbstractContainer should be empowered
to make the objects created by its factory methods
read-only.

Also, I beleive that these classes will have an
application in user-space too. As I mentioned, what
I'm trying to do is to "augment" the "factory method"
pattern with an ability to modify the object created
by the implementation that is being overriden. I think
that it is equally suitable both for the container
internals and for client components (which too will
have factory methods and overriden implementations
thereof).

NH> Maybe I missed something important...
That's what we're here to -- to talk, to communicate,
it's my pleasure, let's do it!
Will be glad to answer further questions :-)

WBR, Anton


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Proposal] WriteProtectable/ReadOnly interfaces

Posted by Niclas Hedhman <ni...@hedhman.org>.
Hi,
Sorry if I don't fully appreciate your example, but;

Could you provide some reasoning around what you are trying to achieve?

Let me attempt;
You want to have a way to force that an object can no longer be modified, 
after some point in time. The ReadOnly interface is intended as a marker that 
an object can not be modified, and the WriteProtectable is an interface to 
"turn on" the ReadOnly functionality.

Provided this is the case, why do you need to "pollute" the Avalon Framework
interfaces with such a construct?
How do you see that the containers need to be involved in this scheme at all? 
Is there a "time"/"sequence" constraint on when a WriteProtectable turns into 
a ReadOnly?
You mention that it would be used on ServiceManagers, but if the 
ServiceManager user does not need to know, then it is an implementation 
detail and irrelevant to Framework.

Maybe I missed something important...

Niclas

On Tuesday 10 June 2003 12:15 am, Anton Tagunov wrote:
> Hi, All!
>
> I think that we have got one more interface
> crystalized in our works:
>
>     public interface WriteProtectable
>     {
>         void makeReadOnly();
>     }
>
> As I will show later it also needs a twin
> marker interface ReadOnly:
>
>     public interface ReadOnly
>     {
>     }
>
> For instance DefaultServiceManager is WriteProtectable
> while FortressServiceManager is ReadOnly.
>
> -------------
>
> This interfaces are proposed to have a XXXUtil.makeReadOnly()
> method to operate them: (a sketch)
>
>     public void makeReadOnly( Object obj )
>     {
>         if ( obj instanceof WriteProtectable )
>         {
>             ((WriteProtectable)obj).makeReadOnly();
>         }
>         else if ( obj instanceof ReadOnly )
>         {
>             //do nothing
>         }
>         else
>         {
>             throw new IllegalArgumentException( "..." );
>         }
>     }
>
> --------------
>
> This methods may be usefull when we extend any kind of
> class via subcalssing, f.e. a container or a component.
>
> Here's a usage example:
>
>     class Abstract
>     {
>         protected void initializeGreat()
>         {
>             m_great = createGreat();
>             XXXUtil.makeReadOnly( m_great );
>         }
>
>         protected Great createGreat()
>         {
>             DefaultGreat great = new DefaultGreat();
>             great.put( foo );
>             great.put( bar );
>             return great;
>         }
>     }
>
>     class Derived extends Abstract
>     {
>         protected Great createGreat()
>         {
>             Great parent = super.createGreat();
>             final DefaultGreat great;
>             if ( parent instanceof DefaultGreat )
>             {
>                 great = (DefaultGreat) parent;
>             }
>             else
>             {
>                 great = new DefaultGreat( parent );
>             }
>             great.put( blah );
>             return great;
>         }
>     }
>
>
> --------
>
> Great could be Context, ServiceManager, etc.
>
> --------
>
> This mail is on introduction of WriteProtectable/ReadOnly.
> Do you think it's a good idea to put them somewhere to the
> framework, say o.a.a.f.writeprotection (bad name :-((  )
> and make all the classes that have a makeReadOnly() method
> implement WriteProtectable?
>
> --------
>
> Where can XXXUtil.makeReadOnly() go?
> (My other mail is on a similar subject,
> XXXUtil.get( context,key,defaultValue ), where can that go?
> Should they both go to one class? Where can it live?)
>
> WBR, Anton
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
> For additional commands, e-mail: dev-help@avalon.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


sorry

Posted by Anton Tagunov <at...@mail.cnt.ru>.
sorry, somehow I failed to trim the quotes on top of my text (they
just got out of the viewport) meaningfull mail begins from the line

AT> I will try to reply to bits of your mail...


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


again sorry

Posted by Anton Tagunov <at...@mail.cnt.ru>.
LS> Also, I bet that answer's longer than you expected! 8-)
AT> Absolutely! I win the bet ;-)

err.. I meant YOU win the bet, what has happened to my
fingertips?

Anton :-)


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re[2]: [Proposal] WriteProtectable/ReadOnly interfaces

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello Leo,

Tuesday, June 10, 2003, 4:11:07 PM, you wrote:

LS> Anton Tagunov wrote:
>> This mail is on introduction of WriteProtectable/ReadOnly.
>> Do you think it's a good idea to put them somewhere to the
>> framework

LS> WriteProtectable and ReadOnly are not really part of the 
LS> container-component contract: a container does not tell a hosted 
LS> component to become "readonly". The container doesn't care; this kind of 
LS> behaviour can be configured using a configuration or perhaps metadata.

LS> In avalon, the currently existing makeReadOnly() calls are not made on 
LS> things which classify as "avalon components" and/or "avalon services", 
LS> rather, they are implementation-specific.

LS> As such, a WriteProtectable would fit roughly the same role inside 
LS> avalon-framework as, for example, CascadingThrowable currently does. 
LS> Just like in an indeal world we would replace CascadingThrowable with 
LS> Nestable inside commons-lang, WriteProtectable might live there as well.

LS> What we have here is a *generic aspect*: "read/write capability" of a 
LS> generic java class. Here's a grid which one might fill in any way:

LS>         |yes | no | configurable (once) | configurable n times
LS> -------------------------------------------------------------
LS> read   |    |    |                     |
LS> write  |    |    |                     |
LS> -------------------------------------------------------------

LS> where for a particular component there is one type of "read" behaviour 
LS> and one type of "write" behaviour.

LS> You could model as follows:

LS> interface Readable {}
LS> interface ReadProtectable extends Readable { void disableRead() }
LS> interface ReadConfigurable extends Writeable { void enableRead() }

LS> interface Writeable {}
LS> interface WriteProtectable extends Writeable { void disableWrite() }
LS> interface WriteConfigurable extends WriteProtectable {
LS>                 void enableWrite() }

LS> where you pick one from both lists, and for a class failing to do that a 
LS> sensible default is decided upon.

LS> For these interfaces to make most sense, they should probably live in 
LS> java.lang, and be universally adopted early on. Doing this for lots of 
LS> concerns means you get lots and lots of tiny interfaces, some of which 
LS> might not be used.

LS> Which really doesn't work so well. Consider the amount of ServiceManager 
LS> implementations in existence which expose a makeReadOnly() method but do 
LS> not implement WriteProtectable, for example.

LS> A "language extension" of some kind is in order:

LS> class MyBean [Readable,Writeable] { /* ... */ }

LS> of course, language extensions usually are problematic (despite the 
LS> success of AspectJ, which is just not quite successful enough), so 
LS> there's various ways to do the same thing. Naming conventions perhaps 
LS> (use introspection to search for "makeReadOnly()" and/or 
LS> "makeWriteable()" methods for example, in place of instanceof), or a 
LS> MyBeanBeanInfo class describing the behaviour for example, or an 
LS> .xprofile xml descriptor file doing the same, or information stored 
LS> inside the class definition based on javadoc tags

LS> /** @bean readable="true" writeable="configurable" */
LS>   class MyBean { /* ... */ }

LS> Using any of those options helps keep the codebase leaner and meaner and 
LS> scales better with the addition of different aspects. So in conclusion I 
LS> think that the interfaces you propose might make sense to include in 
LS> java.lang (failing that, commons-lang :D), that they should not live in 
LS> avalon-framework as they are more generic than the rest of 
LS> avalon-framework and have nothing to do with the container-component, 
LS> but that,

I will try to reply to bits of your mail
out of order, please let this not confuse you.

LS> Also, I bet that answer's longer than you expected! 8-)
Absolutely! I win the bet ;-)

For one, Berin has already made me understand
that only one class would be enough for what
I want. And ReadOnly marker interface would
be an evil as a derived class might already
be quite read-write while not being able
to remove the "implements ReadOnly" from itself.

LS>         |yes | no | configurable (once) | configurable n times
LS> -------------------------------------------------------------
LS> read   |    |    |                     |
LS> write  |    |    |                     |
LS> -------------------------------------------------------------
yes, this looks like being most generic, but
for what I'm speaking about (see my mail to Niclas)
"augmenting factory method" pattern, a WriteProtecteable
would be enough (with a no-op implementation for
what we have called ReadOnly objects).

LS> As such, a WriteProtectable would fit roughly the same role inside
LS> avalon-framework as, for example, CascadingThrowable currently does. 
LS> Just like in an indeal world we would replace CascadingThrowable with 
LS> Nestable inside commons-lang, WriteProtectable might live there as well.

Absolutely!

LS> given the fact that they would be added as an afterthought
LS> which would require source code modification for any existing 
LS> implementations of the behaviour, are probably better modelled in a 
LS> different way.

yes and no here, see bellow...

LS> Consider the amount of ServiceManager
LS> implementations in existence which expose a makeReadOnly() method but do 
LS> not implement WriteProtectable, for example.

It's even worse. I want to oblidge _every_ implementation of
ServiceManager that would be possible to be return from the

     fortress/impl/AbstractContainer.java|provideServiceManager()

method to implement WriteProtectable. (Before I wanted it to be
either WP or RO, but as we have just nuked RO only WP remains).

But it's also better then what you describe.
I want only objects returnable from

     fortress/impl/AbstractContainer.java|provideServiceManager()
     fortress/impl/AbstractContainer.java|provideComponentContext()

methods to be oblidged to implement WriteProtectable.
That's not that bad. I do not want _all_ the ServiceManager-s
in the world to implement this, but only those returnable
from _new_ methods.

(Well, the fact that Fortress has been released a little spoils
this beautifull picture, but still it is not that bad yet,
if a new release is rolled out soon, then probably not too
many people will implement these methods

     fortress/impl/AbstractContainer.java|provideServiceManager()
     fortress/impl/AbstractContainer.java|provideComponentContext()

So I want WP only for objects returned from _new_ methods,
and that's not that bad.

In fact I want

     fortress/impl/AbstractContainer.java|provideServiceManager()

to return a ServiceManager that _also_ implements WriteProtectable.

<uneasily-shrugging>
Maybe introduce a new ServiceManager, WPServiceManager for this case?
</uneasily-shrugging>

     
LS> And the "different way" we currently are all most happy with here @
LS> avalon seems to be meta tags transformed into xml :D

Excellent and beautifull! But makes me feel a little worried
on how heavy-weight it is: it's ok for components but I'm speaking
on a level much lower. I think would personally prefer smth
lightweight there..


Thoughts?

- Anton


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: Would it be ok for framework to depend on commons-lang?

Posted by Berin Loritsch <bl...@apache.org>.
Anton Tagunov wrote:
> Hello Leo and All!
> 
> LS> As such, a WriteProtectable would fit roughly the same role inside
> LS> avalon-framework as, for example, CascadingThrowable currently does. 
> LS> Just like in an indeal world we would replace CascadingThrowable with 
> LS> Nestable inside commons-lang, WriteProtectable might live there as well.
> 
> would it be okay for avalon-framework to depend on
> commons-lang?

:/

We strive to make sure that Framework has no dependencies.  The thing is
that if Commons Lang ever introduces a dependency on Commons Logging,
that would definitely be bad for us.  Let's KISS.  I personally don't
ever use anything from Commons Lang, as I haven't found a need for it
yet.



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


RE: Would it be ok for framework to depend on commons-lang? (was: [Proposal] WriteProtectable/ReadOnly interfaces)

Posted by Leo Sutic <le...@inspireinfrastructure.com>.

> From: Anton Tagunov [mailto:atagunov@mail.cnt.ru] 
> 
> would it be okay for avalon-framework to depend on commons-lang?

For a good reason, yes. But the WriteProtectable / ReadOnly isn't
a good reason.

/LS


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Would it be ok for framework to depend on commons-lang? (was: [Proposal] WriteProtectable/ReadOnly interfaces)

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hello Leo and All!

LS> As such, a WriteProtectable would fit roughly the same role inside
LS> avalon-framework as, for example, CascadingThrowable currently does. 
LS> Just like in an indeal world we would replace CascadingThrowable with 
LS> Nestable inside commons-lang, WriteProtectable might live there as well.

would it be okay for avalon-framework to depend on
commons-lang?

- Anton


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Proposal] WriteProtectable/ReadOnly interfaces

Posted by Leo Simons <le...@apache.org>.
Anton Tagunov wrote:
> LS> The ReadOnly interface messes up the contracts for absolutely no 
> LS> benefit.
> Agreed. Just my lack of experience! :-)

you are experiencing the steep IoC/SoC learning curve that is the most 
difficult part of avalon, and the biggest gain to your software when 
done right!

It's not just lack of experience, this whole thing is also rather 
difficult to capture in a nice way in documentation. If, while building 
up your experience, you figure out a way to explain things in a better 
way, this is one of the main challenges surrounding avalon-framework :D

In the meantime, I'm just placing my bets on Berin's book ;)

- LSD



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re[2]: [Proposal] WriteProtectable/ReadOnly interfaces

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Hi Berin!

BL> Anton, I can understand any frustration that you might be feeling.

I'm happy not frustrated =)
Good argumentation is good argumentation after all,
Thanks to everybody!


Leo Sutic has given me some thinking food with
his ModifiableContext -- so don't be surprised
if one day I bring the issue back afloat -- with
a different flavour.

- Anton


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Proposal] WriteProtectable/ReadOnly interfaces

Posted by Berin Loritsch <bl...@apache.org>.
Anton Tagunov wrote:
> 
> For instance because the type of the objects returned from the
> factory includes the WriteProtectable interface explicitly.


:)

Anton, I can understand any frustration that you might be feeling.
It is important to realize that we become very jealous of Avalon
Framework.  It HAS to work compatibly in all situations.  We already
have some cruft in there we would like to remove--but we can't due
to backwards compatibility issues.  As a result, we are generally
very resistant to adding anything new to Framework.

If all three containers did the exact same things, then we might
be a little bit more relaxed--but only a little.  The thing is
that all of the artifacts (the Context, Logger, ServiceManager,
Configuration, Parameters, etc.) are all supposed to be read only.
We all know that they need to be initially set up, so certain
items have used the "makeReadOnly()" idiom that you see here.

Any time we add a new interface, we add a new contract.  Contracts
are heavy, so we try to avoid them unless they add more value than
they cost.

In this particular case, the cost/benefit ratio is really not that
favorable.  I understand that you would like to have some central
utils to refactor things a bit.  However, most folks will be using
the implementations of the artifacts we provide--so the benefits of
having the interface and util go down.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


RE: Re[2]: [Proposal] WriteProtectable/ReadOnly interfaces

Posted by Leo Sutic <le...@inspireinfrastructure.com>.

> From: Anton Tagunov [mailto:atagunov@mail.cnt.ru] 
> 
> Still not completely convinced.
> Please refer to the examples in the letter to
> Niclas, don't they protect the opposite opinion?

I don't think so. Your example is this:

   Context ctx = makeNewContextSomehow ();

   ... do stuff to context ...

   if (ctx instanceof WriteProtectable) {
       ((WriteProtectable) ctx).makeReadOnly ();
   }

Except you have factored out the if () test into a separate method. 

The questions are now, given that the ctx instance implements
WriteProtectable:

  1. Does the ctx object implement ReadOnly? It should implement
     it after it had been made ReadOnly. But not before.

  2. Why do I have to do a instanceof test?

> This may be part of object's contract: it still allowes modification
> of its contents after creation and then "sealing" it. Why can not
> such contract exist?

    *** Because it has to be explicitely tested for. ***

> LS> If you don't know everything about the object you are
initializing,
> LS> for example, if you use an abstract factory to create the
instance,
> LS> how can you be sure that you are allowed to make it read-only?
> 
> For instance because the type of the objects returned from the
> factory includes the WriteProtectable interface explicitly.

BAD:

   Context ctx = makeContext();
   ...do stuff..
   if (ctx instanceof WriteProtectable) {
       ((WriteProtectable) ctx).makeReadOnly ();
   }

GOOD:
   interface ModifiableContext extends Context {
       public void makeReadOnly ();
       public void put (String key, Object value);
   }

   ModifiableContext ctx = makeContext();
   ...do stuff..
   ctx.makeReadOnly ();

In the BAD example, you are not sure just what you get back and have to
do typecasts and all sorts of things in client code. Just more things
that
can go wrong.

In the GOOD example, you will know, and the compiler will know, that 
you can call makeReadOnly().

However, we can do one step better by applying IoC and thus *ensuring
that
makeReadOnly is called*:

BETTER:
   interface ModifiableContext extends Context {
       public void put (String key, Object value);
   }

   protected Context makeContext () {
       DefaultModifiableContext mctx = new DefaultModifiableContext ();

       ... very basic init ...
       
       initializeContext (mctx);
       mctx.makeReadOnly(); // guaranteed to be done
       return mctx;
   }

   protected void initializeContext (ModifiableContext mctx) {
       ... do stuff to mctx ...
   }

   Context ctx = makeContext();

Here everything is type-safe. No instanceof tests, no casting.
If you get an instance of type T then you *only* have to worry about
the T contract.

/LS


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re[2]: [Proposal] WriteProtectable/ReadOnly interfaces

Posted by Anton Tagunov <at...@mail.cnt.ru>.
LS> The ReadOnly interface messes up the contracts for absolutely no 
LS> benefit.
Agreed. Just my lack of experience! :-)

LS> Regarding the WriteProtectable interface:

LS> Making something read-only is almost always done as a part of the 
LS> creation process: You create an object, then you initaialize it
LS> somehow, then you make it read only and finally you pass it to
LS> clients.

Still not completely convinced.
Please refer to the examples in the letter to
Niclas, don't they protect the opposite opinion?

LS> The thing is that if you are the one creating an object, you already
LS> know everything about it, and you should call the object's own
LS> makeReadOnly() method.

This may be part of object's contract: it still allowes modification
of its contents after creation and then "sealing" it. Why can not
such contract exist?

LS> If you don't know everything about the object you are initializing,
LS> for example, if you use an abstract factory to create the instance,
LS> how can you be sure that you are allowed to make it read-only?

For instance because the type of the objects returned from the
factory includes the WriteProtectable interface explicitly.

- Anton


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


RE: [Proposal] WriteProtectable/ReadOnly interfaces

Posted by Leo Sutic <le...@inspireinfrastructure.com>.
Anton Tagunov wrote:
> This mail is on introduction of WriteProtectable/ReadOnly.
> Do you think it's a good idea to put them somewhere to the framework
 
No.

The concept of something being read-only should be specified in the
interface the client uses to interact with the object. Preferably by
not providing any methods the client can use to change the object.

I.e. If I give you a XBean class, then
the XBean contract is ***all*** you have to care about. You shouldn't 
have to worry about whether the XBean instance you got may also
implement
ReadOnly or whatever.

For example, consider this:

    class Bean {
        int i;
        public void set (int i) { ... };
        public int get () { ... };
    }

    class ReadOnlyBean extends Bean implements ReadOnly {
        public void set (int i) { throw new
UnsupportedOperationException(); };
    }

Why is this bad architecture? Because if you have a method:

    public void useBean (Bean b) {
        // Is it safe to call Bean.set here?
        if (b instanceof ReadOnly) // grumble, grumble why do I have to
test this
                                   // EVERY TIME???
    }

Better way:

    class ReadOnlyBean {
        protected int i;
        public int get () { ... };
    }

    class Bean extends ReadOnlyBean {
        public void set (int i) { ... };
    }

Then you know that you can call any method provided to you without
having to worry about some of them maybe not being there. == Stronger
contracts == fewer bugs.

The ReadOnly interface messes up the contracts for absolutely no 
benefit.

Regarding the WriteProtectable interface:

Making something read-only is almost always done as a part of the 
creation process: You create an object, then you initaialize it
somehow, then you make it read only and finally you pass it to
clients.

The thing is that if you are the one creating an object, you already
know everything about it, and you should call the object's own
makeReadOnly() method.

If you don't know everything about the object you are initializing,
for example, if you use an abstract factory to create the instance,
how can you be sure that you are allowed to make it read-only?

/LS


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Proposal] WriteProtectable/ReadOnly interfaces

Posted by Leo Simons <le...@apache.org>.
Anton Tagunov wrote:
> This mail is on introduction of WriteProtectable/ReadOnly.
> Do you think it's a good idea to put them somewhere to the
> framework

WriteProtectable and ReadOnly are not really part of the 
container-component contract: a container does not tell a hosted 
component to become "readonly". The container doesn't care; this kind of 
behaviour can be configured using a configuration or perhaps metadata.

In avalon, the currently existing makeReadOnly() calls are not made on 
things which classify as "avalon components" and/or "avalon services", 
rather, they are implementation-specific.

As such, a WriteProtectable would fit roughly the same role inside 
avalon-framework as, for example, CascadingThrowable currently does. 
Just like in an indeal world we would replace CascadingThrowable with 
Nestable inside commons-lang, WriteProtectable might live there as well.

What we have here is a *generic aspect*: "read/write capability" of a 
generic java class. Here's a grid which one might fill in any way:

        |yes | no | configurable (once) | configurable n times
-------------------------------------------------------------
read   |    |    |                     |
write  |    |    |                     |
-------------------------------------------------------------

where for a particular component there is one type of "read" behaviour 
and one type of "write" behaviour.

You could model as follows:

interface Readable {}
interface ReadProtectable extends Readable { void disableRead() }
interface ReadConfigurable extends Writeable { void enableRead() }

interface Writeable {}
interface WriteProtectable extends Writeable { void disableWrite() }
interface WriteConfigurable extends WriteProtectable {
		void enableWrite() }

where you pick one from both lists, and for a class failing to do that a 
sensible default is decided upon.

For these interfaces to make most sense, they should probably live in 
java.lang, and be universally adopted early on. Doing this for lots of 
concerns means you get lots and lots of tiny interfaces, some of which 
might not be used.

Which really doesn't work so well. Consider the amount of ServiceManager 
implementations in existence which expose a makeReadOnly() method but do 
not implement WriteProtectable, for example.

A "language extension" of some kind is in order:

class MyBean [Readable,Writeable] { /* ... */ }

of course, language extensions usually are problematic (despite the 
success of AspectJ, which is just not quite successful enough), so 
there's various ways to do the same thing. Naming conventions perhaps 
(use introspection to search for "makeReadOnly()" and/or 
"makeWriteable()" methods for example, in place of instanceof), or a 
MyBeanBeanInfo class describing the behaviour for example, or an 
.xprofile xml descriptor file doing the same, or information stored 
inside the class definition based on javadoc tags

/** @bean readable="true" writeable="configurable" */
  class MyBean { /* ... */ }

Using any of those options helps keep the codebase leaner and meaner and 
scales better with the addition of different aspects. So in conclusion I 
think that the interfaces you propose might make sense to include in 
java.lang (failing that, commons-lang :D), that they should not live in 
avalon-framework as they are more generic than the rest of 
avalon-framework and have nothing to do with the container-component, 
but that, given the fact that they would be added as an afterthought 
which would require source code modification for any existing 
implementations of the behaviour, are probably better modelled in a 
different way.

And the "different way" we currently are all most happy with here @ 
avalon seems to be meta tags transformed into xml :D

Also, I bet that answer's longer than you expected! 8-)

greetz!

- Leo



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re[2]: [Proposal] WriteProtectable/ReadOnly interfaces

Posted by Anton Tagunov <at...@mail.cnt.ru>.
Thanks, Berin!

BL> Marker Interface == Bad.

BL> One thing that we have learned developing in Cocoon land is
BL> that using marker interfaces to record class meta information
BL> is bad practice.  What happens if the class is extended and
BL> it is no longer ReadOnly?  You can't get rid of the interface
BL> from the list of implements clauses.

I see that I can really learn a lot from you!
Then a better solution would be a no-op imlementation
of the makeReadOnly() method in the objects that
are read-only by nature like FortressConfig.

- Anton :-)


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: [Proposal] WriteProtectable/ReadOnly interfaces

Posted by Berin Loritsch <bl...@apache.org>.
Anton Tagunov wrote:
> Hi, All!
> 
> I think that we have got one more interface
> crystalized in our works:
> 
>     public interface WriteProtectable
>     {
>         void makeReadOnly();
>     }
> 
> As I will show later it also needs a twin
> marker interface ReadOnly:
> 
>     public interface ReadOnly
>     {
>     }
> 
> For instance DefaultServiceManager is WriteProtectable
> while FortressServiceManager is ReadOnly.

Marker Interface == Bad.

One thing that we have learned developing in Cocoon land is
that using marker interfaces to record class meta information
is bad practice.  What happens if the class is extended and
it is no longer ReadOnly?  You can't get rid of the interface
from the list of implements clauses.



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org