You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@avalon.apache.org by Leo Sutic <le...@inspireinfrastructure.com> on 2004/01/23 22:08:58 UTC

[RT] JavaBeans are even more evil than first thought

All,

the discussion of automatically setting fields in the component
based on a component to configuration mapping caused me to think
about the alternatives to reaching into a class and setting
private fields.

For example, we will use a class that has two fields - a minimum
and a maximum range.

    public class Radar {

        private int minRange;

        private int maxRange;

        // ...

    }

There's one invariant though - the minimum range is always less than
or equal to the maximum range: minRange <= maxRange

Additionally, I'll completely ignore the case of a negative range 
value. Focus on the invariant above.

OK, so how are we going to configure this thing?

Attempt 1: Standard Avalon Configuration

    public class Radar {

        private int minRange;

        private int maxRange;

        public void configure (Configuration config) 
            throws ConfigurationException {

            minRange = config.getAttributeAsInteger ("min-range");
            maxRange = config.getAttributeAsInteger ("max-range");

            if (minRange > maxRange) {
                throw new ConfigurationException ("min-range >
max-range");
            }
        }

        // ...

    }

OK, fine, but not very magic. Not magic enough, in fact, due to the
amount of 
boilerplate code.


Attempt 2: Deserialization from XML or similar

    public class Radar {

        private int minRange;

        private int maxRange;

        // ...

    }

Here we use XStream or similar. So we create an XML file:

    <radar>
        <minRange>1000</minRange>
        <maxRange>2000</maxRange>
    </radar>

And we're done. Or? Well, how about:

    <radar>
        <minRange>2000</minRange>
        <maxRange>1000</maxRange>
    </radar>

Oops. Broken invariant. No way to detect that unless we do some serious 
hackery. 


Attempt 3: Use Setters to Validate Values

    public class Radar {

        private int minRange;

        private int maxRange;

        public void setMaxRange (int _maxRange) {
            if (_maxRange < minRange) {
                throw new IllegalArgumentException ("maxRange <
minRange");
            }
            
            maxRange = _maxRange;
        }

        public void setMinRange (int _minRange) {
            if (_minRange > maxRange) {
                throw new IllegalArgumentException ("minRange >
maxRange");
            }
            
            minRange = _minRange;
        }

        // ...

    }

Here the problem is that we can't guarantee in what order the setters
will be
called. Unless they are called in the order setMaxRange, setMinRange,
we're
guaranteed to get an IllegalArgumentException. This is the problem of
constructing 
and object with setters - even though they are supposed to provide
validation 
of the parameters, due to them being called in sequence, none can
validate the
complete state of the instance before the object is fully constructed.

Anyway, that's why JavaBeans are Evil. Mmmkay?


Attempt 4: Auto-Configuration

    public class Radar {

        /**
         * @@ConfigurableField ("@min-range")
         */
        private int minRange;

        /**
         * @@ConfigurableField ("@max-range")
         */
        private int maxRange;

        // ...

    }

Fails for the same reasons as attempt 2: no validation.



Attempt 5: Auto-Configuration or Deserialization With
           Separate configure() Step

    public class Radar {

        /**
         * @@ConfigurableField ("@min-range")
         */
        private int minRange;

        /**
         * @@ConfigurableField ("@max-range")
         */
        private int maxRange;

        public void configure (Configuration config) 
            throws ConfigurationException {

            if (minRange > maxRange) {
                throw new ConfigurationException ("min-range >
max-range");
            }
        }

        // ...

    }

Well, *I* think this one is a winner. (Whether it is realized via
XStream
or attributes is not that relevant.)

/LS


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


RE: [RT] JavaBeans are even more evil than first thought

Posted by Leo Sutic <le...@inspireinfrastructure.com>.
There must be a nit to pick *somewhere*...

> From: news [mailto:news@sea.gmane.org] On Behalf Of Leo Simons
> 
>      public class Radar {
>          private int minRange;
>          private int maxRange;
> 
>          public Radar( int maxRange, int minRange )
>          {
>            // easy to do the ordering here :D
>            setMaxRange( maxRange );
>            setMinRange( minRange );

Boilerplate code. Nice when you have two parameters, ugly
when you have twenty.

/LS


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


Re: [RT] JavaBeans are even more evil than first thought

Posted by Leo Simons <le...@apache.org>.
Leo Sutic wrote:
<snip/>

and another good read! Is this all part of a "let's keep Berin around" 
campaign? :D

summary: we want to write just a little bit of code to handle 
configuration, and with that, have strong validation of our invariants 
and other types of assertions.

You highlight one way it could be done using javadoc tags, reflection 
and a configure() method which is essentially a validateInvariants() method.

IMHO: Too Much Magic!

You probably already knew that I was going to say that ;). Maybe we need 
to delve into .Net, where we wouldn't be needing a language extension...

Other possible 'solutions' include AOP-based validation (lots of AspectJ 
samples around), ugly xml-based interceptor validation (XWork, I think 
HiveMind as well), and...constructor dependency injection:

     public class Radar {
         private int minRange;
         private int maxRange;

         public Radar( int maxRange, int minRange )
         {
           // easy to do the ordering here :D
           setMaxRange( maxRange );
           setMinRange( minRange );
         }

         // made these protected; you could make them private
         protected void setMaxRange (int _maxRange)
         {
             if (_maxRange < minRange)
                 throw new IllegalArgumentException(
                   "maxRange < minRange");

             maxRange = _maxRange;
         }

         protected void setMinRange (int _minRange)
         {
             if (_minRange > maxRange)
                 throw new IllegalArgumentException(
                   "minRange > maxRange");

             minRange = _minRange;
         }

         // ...
     }
-- 
cheers,

- Leo Simons

-----------------------------------------------------------------------
Weblog              -- http://leosimons.com/
IoC Component Glue  -- http://jicarilla.org/
Articles & Opinions -- http://articles.leosimons.com/
-----------------------------------------------------------------------
"We started off trying to set up a small anarchist community, but
  people wouldn't obey the rules."
                                                         -- Alan Bennett



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


Re: [RT] JavaBeans are even more evil than first thought

Posted by Niclas Hedhman <ni...@hedhman.org>.
On Friday 23 January 2004 13:08, Leo Sutic wrote:

I have also spent some thinking of the "boilerplate" configuration you are so 
concerned about.

public class Radar 
{
    /** @configurable-property name="min-range" */
    private int minRange;
    /** @configurable-property name="max-range" */
    private int maxRange;

    public void configure (Configuration config)
        throws ConfigurationException 
    {
        ConfigurationUtility cu = new ConfigurationUtility();
        cu.poplute( this, config );
        if (minRange > maxRange) {
            throw new ConfigurationException ("min-range >
"max-range");
        }
    }
}

And the ConfigurationUtility class, would tie the XML elements to the private 
properties.
The ConfigUtility could even invoke more than one strategy (doc-tags, 
reflection, setters) accordingly.

It also removes it from being a container concern and has nothing to do with 
Framework.

Wouldn't something like this work fairly nicely?


Niclas

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