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 Simons <le...@apache.org> on 2003/10/04 17:02:53 UTC

[RT] avalon (merlin) == safe == programmer effort (was: Re: Jini 2.0 Configuration Files)

hammett wrote:
>> (as opposed to the conceptually very clean avalon-style
>> configuration where a component is allowed to "read" from its
>> configuration, but the configuration itself is passive),
> 
> Biased! Biased! :-p

ROTFL! Me? Nah..... ;)

Seriously, one could only consider it conceptually very clean, don't you 
think?

The avalon picture
------------------
- a container is responsible for finding/creating the configuration 
according to preset rules (delegating this responsibility to a 
specialized component of course), usually allowing for various people in 
various roles (end users, assemblers, component writers) to follow 
various contracts to define the configuration,

- a configuration object is then responsible only for existing 
(implementing the Configuration interface)

- a component is responsible for obeying the directives provided to it 
by the container in the form of the configuration it receives (and 
complaining if it doesn't know how).

Clean. Add in some more enforcable rules (like requiring component 
authors to provide a container-verifiable schema for the configuration 
format (like a DTD for XML) and component configurators to follow that 
schema), and, save for bugs, all behaviour is completely deterministic. 
Clean, safe, sound, understandable.

The downside? In practice, especially with java and xml, it means way 
many lines of code to write.

Note: its perfectly possible to write a very dynamic scripted 
avalon-framework container. It just happens to be the case that avalon 
(especially with Merlin) is moving further and further into the sound 
and safe, predictable and verifiable corner. In fact, some people (like 
Steve) assert that a container which is not predictable is a Bad 
Thing(tm). Me, I strongly disagree with that assertion :D


The scripted picture
--------------------
- a container will look for a configuration script according to preset 
rules and run it according to some more rules

- a configuration script had better exist and follow the rules

- a component is not required to do anything special

You lift some responsibility from the component and from the container 
at the price of requiring the end user to write a sensible configuration 
script or suffer the consequences.

The upside? Every piece in this system is a lot simpler, and usually you 
end up with less lines of code everywhere.

The balance
-----------
You have a few axes that are not orthogonal:

	clean       <---------------------------> dirty
	safe        <---------------------------> unsafe
	complex     <---------------------------> simple
	static      <---------------------------> flexible
	much effort <---------------------------> little effort

Sacrifice some conceptual cleanness and predictability and you end up 
with a system that is both simpler and more flexible, and, most 
importantly, requires less typing.

Choice
------
In a banking application, you had better make sure that a 
misconfiguration does not ever result in anything bad happening. I 
wouldn't want scriptable ATMs. In your average web server, its okay if a 
web page decides to topple over every now and then, as long as it is 
easily and quickly fixed.

cheers!

- Leo



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


Re: [RT] avalon (merlin) == safe == programmer effort

Posted by Alexis Agahi <al...@users.sf.net>.
On Sunday 05 October 2003 13:32, Leo Simons wrote:

> The point is in seeing that back when we all (as IT community) chose
> XML, it was in some places a very bad choice :D

sure, XML is not designed for programatic stuffs (well maybe it depends on our 
background, because I've seen incredible XSLT programming stuff, done by 
people who had never seen anything like java).

> I'm not saying avalon's XML configuration mechanism should go. That
> would horrify everyone. I'm saying that, if you feel like replacing the
> de-facto standard of using XML with anything else (like the Jini 2.0
> config format we started this topic with), a scripting language like
> BeanShell or ruby is a better choice than anything else.

Ok, why not. 
But sometime more choice equals more confusion. It is currently a bit hard to 
explain the configuration IoC principle to devlopper, if you add scripting, 
this could drive them to confusion and heterogeneity.

But I aggree that for quick dev/test phase this could help.



> But you'll have a hard time finding a seasoned sysop who prefers XML
> configuration to the Apache HTTPD config file (which is basically a
> custom scripting language), or the Samba one.

It depends.
If you consider "old style *nu|ix sysop" you are probably right.


> Its easy to find a java programmer who prefers an XML config file to a
> scripted one. But I just think all those people are being silly and I'm
> not :D

ok ;)

> > (even javascript is far from java).
>
> indeed. BeanShell has full support for java syntax. You could have java
> programmers write configurations in java (as per the examples I gave).
> You could have sysops write configurations in python or ruby.

yeahh. in your dreams ;) Most of the sysop (I'm not talking about sysop/hacker 
profile) just want the application to run without having anything to do or 
configure. Just take a look at how many IIS are running with default conf, to 
see what I mean.
But ok, this does not mean that we should close all the doors.

> > Also XML is now well known for most of the sysop,
>
> I think its well-known to sysops who manage java applications. Outside
> that subset, I suspect most sysops don't know xml that well.

I'm not so sure.



> > XML config files are human readable,
>
> excuse me? Human-readable?
>
> http://cvs.apache.org/viewcvs.cgi/avalon/buildsystem/maven-common.xml?rev=1
>.9&content-type=text/vnd.viewcvs-markup

lol, ok.
easy shot. Do you want me to write you an url of unreadable sendmail config 
file?


> barely. If I were to show my non-programmer flatmates your average
> tomcat config file as compared to your average apache httpd config file,
> I doubt any of them would go for the former.


The fact is that most of good programmers with the help of good frameworks 
(;)) use to externalize *all* static value in config file. So this drives you 
to huge conf file with 99% of value that you will never touch in most of the 
time (take a look at jboss config).
For that, Merlin offers a good solution based on "defaut" .xconfig files for 
each component, and help to reduce the main conf file (an increase 
readability).

This is not a common practice in C/C++ *traditionnal* programming approch 
(even if I guess that it is now more the case).



> in summary:
>    "XML combines all the inefficiency of text-based formats with most of
>    the unreadability of binary formats." -- Oren Tirosh, comp.lang.python

LOL
XML is just a self describing hierachical text format.


>  > What could be done is having "Scriptable" components (such as
>  > Initializable, or Configurable) that could be scripted during
>  > component lifecycle.
>
> Hmmm. What would that interface look like? Something like:

>    public interface Scriptable {}
>
> well, maybe a metadata tag would work better:
>
>    /** @@Scriptable */
>    public class MyBlah { /* ... */ }
>
> but, this metadata is also available by virtue of the script file being
> available. So strip that, too, and implement some simple logic like:
>
>    if <<scriptfile exists for class>>		// pseudocode
>      try
>        <<initialize using scriptfile>>
>      catch
>        <<issue warning>>
>        <<initialize using avalon-framework>>
>    else
>      <<initialize using avalon-framework>>
>
> This, of course, leads to a lot of logic implemented in the container
> which is inflexible (if/elseif/elseif/else considered harmful). The fix
> is obvious: allow for a ComponentFactory/ComponentAdapter idiom (like
> fortress has, as does PicoContainer) and get more flexibility:
>
>    factory = factories.select( class )		// pseudocode
>    return factory.instance()
>
>    class ScriptingFactory
>      instance() return <<initialize using scriptfile>>
>    class AvalonFactory
>      instance() return <<initialize using avalon-framework>>
>
>    class PolicyFactory
>      instance()
>        try
>          return <<delegate to ScriptingFactory>>
>        catch
>          return <<delegate to AvalonFactory>>



As you wish. :)

All I've to say is that "scriptable" features could be nice (even if I'm not 
really 100% convinced) for some applications, and could be availble as 
lifecycle stage of the component.




> Implementation in merlin
> ------------------------
> I looked at that some time ago, and it is simply too much of a hassle.
> Merlin in its current form is simply not built with this kind of
> extensibility in mind. Which leads to the conclusion that, for the near
> future, probably no avalon container will be scriptable :D

ouch ;)
it is time to join the forces ;)

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


RE: [RT] avalon (merlin) == safe == programmer effort

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

> From: news [mailto:news@sea.gmane.org] On Behalf Of Leo Simons
>
> well, maybe a metadata tag would work better:
> 
>    /** @@Scriptable */
>    public class MyBlah { /* ... */ }

I have though about things like:

    public class MyComponent implements ... {

        /** @@Configurable ("./@numThreads") */
        private final int numThreads;

    }

    <component role="..." class="MyComponent" numThreads="15"/>

So you use an XPath expression to have the container set the field 
values.

The problem is when you have configurations like the one the ECM uses,
where you're not just setting field = value, but have to iterate over
child
configurations and create objects based on them:

    <component role="..." class="MyComponent">
        <subcomponent class="..."/>
        <subcomponent class="..."/>
        ...
    </component>

Maybe:

    public class MyComponent implements ... {

        /** @@SubComponents ("subcomponent") */
        private final Collection subComponents;

    }

But the thing here is that we're moving into the "too much magic" land.
What if only one of the subcomponents should be created. Or what if a
special handler is desired? Of course, we could have the @@SubComponent
mean that a Collection not of the actual components but of a component
descriptor or factory should be created, but try to formalize that
contract
for compile-time safety...

/LS


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


Re: [RT] avalon (merlin) == safe == programmer effort

Posted by Leo Simons <le...@apache.org>.
"We can't lose XML!"
--------------------

Alexis Agahi wrote:
> I dont think having scripting configuration should override current XML config 
> model.

indeed. You point out how XML has been ingrained into daily life of 
programmer and sysop. Its neither straightforward nor desirable to move 
away from XML.

> <disclaimer>I'm not sure to understand exactly your point</disclaimer>

The point is in seeing that back when we all (as IT community) chose 
XML, it was in some places a very bad choice :D

I'm not saying avalon's XML configuration mechanism should go. That 
would horrify everyone. I'm saying that, if you feel like replacing the 
de-facto standard of using XML with anything else (like the Jini 2.0 
config format we started this topic with), a scripting language like 
BeanShell or ruby is a better choice than anything else.

For the sake of argument...
---------------------------
Just for fun, let me play advocate of the devil some more....

> Having script means knowing another language

that all depends on what "another language", and to "whom" it will be 
"another". You are right, of course, that many programmers and sysops 
know XML.

But you'll have a hard time finding a seasoned sysop who prefers XML 
configuration to the Apache HTTPD config file (which is basically a 
custom scripting language), or the Samba one.

Its easy to find a java programmer who prefers an XML config file to a 
scripted one. But I just think all those people are being silly and I'm 
not :D

> (even javascript is far from java).

indeed. BeanShell has full support for java syntax. You could have java 
programmers write configurations in java (as per the examples I gave). 
You could have sysops write configurations in python or ruby.

> Also XML is now well known for most of the sysop,

I think its well-known to sysops who manage java applications. Outside 
that subset, I suspect most sysops don't know xml that well.

> and proposing them 
> "exotic" config file could fear them.

indeed. However, providing the choice of a format that is otherwise 
quite a bit more familiar to them (RPM, for example, uses python scripts 
for configuration) than xml might give some interesting results :D

Also, I place much more trust in sysops

> XML config files are human readable,

excuse me? Human-readable?

http://cvs.apache.org/viewcvs.cgi/avalon/buildsystem/maven-common.xml?rev=1.9&content-type=text/vnd.viewcvs-markup

barely. If I were to show my non-programmer flatmates your average 
tomcat config file as compared to your average apache httpd config file, 
I doubt any of them would go for the former.

> and application friendly (I mean you could have for exemple a main 
> application that could generate XML config for all your running apps).

This is a /really/ great feature of XML. Had XML not bean 
machine-readable, it would have never gotten anywhere. It requires about 
a megabyte of jar files and a complex and heavy beast called xerces 
(roughly as complex as, say, GCC) to implement, but yes, it can be 
parsed by machines.

Scripting languages like python and ruby go *way* further than that 
though. They provide built-in serialization/deserialization of any object.

Go further with something like YAML [1], and you can 
serialize/deserialize just about any object into a format that is way 
more human-readable than the most beautiful XML.

in summary:
   "XML combines all the inefficiency of text-based formats with most of
   the unreadability of binary formats." -- Oren Tirosh, comp.lang.python

Implementation in a container
-----------------------------
 > What could be done is having "Scriptable" components (such as
 > Initializable, or Configurable) that could be scripted during
 > component lifecycle.

Hmmm. What would that interface look like? Something like:

   public interface Scriptable {}

well, maybe a metadata tag would work better:

   /** @@Scriptable */
   public class MyBlah { /* ... */ }

but, this metadata is also available by virtue of the script file being 
available. So strip that, too, and implement some simple logic like:

   if <<scriptfile exists for class>>		// pseudocode
     try
       <<initialize using scriptfile>>
     catch
       <<issue warning>>
       <<initialize using avalon-framework>>
   else
     <<initialize using avalon-framework>>

This, of course, leads to a lot of logic implemented in the container 
which is inflexible (if/elseif/elseif/else considered harmful). The fix 
is obvious: allow for a ComponentFactory/ComponentAdapter idiom (like 
fortress has, as does PicoContainer) and get more flexibility:

   factory = factories.select( class )		// pseudocode
   return factory.instance()

   class ScriptingFactory
     instance() return <<initialize using scriptfile>>
   class AvalonFactory
     instance() return <<initialize using avalon-framework>>

   class PolicyFactory
     instance()
       try
         return <<delegate to ScriptingFactory>>
       catch
         return <<delegate to AvalonFactory>>


Implementation in merlin
------------------------
I looked at that some time ago, and it is simply too much of a hassle. 
Merlin in its current form is simply not built with this kind of 
extensibility in mind. Which leads to the conclusion that, for the near 
future, probably no avalon container will be scriptable :D


cheers!


- Leo

[1] - http://www.yaml.org/



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


Re: [RT] avalon (merlin) == safe == programmer effort

Posted by Alexis Agahi <al...@users.sf.net>.
Leo,

I dont think having scripting configuration should override current XML config 
model.

<disclaimer>I'm not sure to understand exactly your point</disclaimer>

Having script means knowing another language (even javascript is far from 
java). Also XML is now well known for most of the sysop, and proposing them 
"exotic" config file could fear them. XML config files are human readable, 
and application friendly (I mean you could have for exemple a main 
application that could generate XML config for all your running apps).

What could be done is having "Scriptable" components (such as Initializable, 
or Configurable) that could be scripted during component lifecycle.


Cheers

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


Re: [RT] avalon (merlin) == safe == programmer effort

Posted by hammett <ha...@apache.org>.
> MyBlah.configurator.strict.bsh
> ------------------------------------------------------------------------
> import org.apache.avalon.framework.configuration.Configurator;
> import com.blah.MyBlah;
>
> public class MyBlahConfigurator implements Configurator
> {
>    public void configure( Object component )
>    {
>      assert component instanceof MyBlah :
>          "component must be instance of MyBlah!";
>
>      MyBlah blah = (MyBlah)component;
>      component.setNumberOfThreads( 15 );
>    }
> }

What's the difference? In order to perform configuration from Script
languages or a subset of java, the user will face a simple choice. We can
try for hours imagine if its human readable, if sysops will not suffer a
heart attack, but the actual decision is from users - who actually knows the
best for them.

I'd like to point out why Jini works the way it is. A server application,
which exports one or more services usually will have to choose a exporting
strategy, a simple proxy, RMI, or whatever exists or will be invented. So
this config file returns the exactly implementation of the desired Exporter
selected at runtime for that particulary environment. What? Are you saying
that this can be done through XML?

<component>
  <exporter type="RMI" />
</component>

Ok, that's valid. So a component needs to know every type of exporting
possibilities and know how to configure each of them.

What?

<component>
  <exporter class="net.jini.exporters.BasicExporter" />
</component>

Oh! That's better. And how the BasicExporter should be initiallized? It has
a important constructor, you know.

So now you see what they tried to solve :-)
Leo, you can shoot me now!  :-P


Regards,

hammett


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


Re: [RT] avalon (merlin) == safe == programmer effort

Posted by Leo Simons <le...@apache.org>.
Stephen McConnell wrote:
> BZZZZT (private joke)

:D:D

> On the other-hand, maybe I'm missing the point ...

that seems to be the case. It'll probably be difficult to get it across 
though. Lets try a different approach....

Abstract
========================================================================

     Scripting languages have an ideal syntax for configuration
     files. They are *way* cleaner and simpler than XML, making
     things simpler for the user. They are *way* more 'natural'
     than any other solution, making things simpler for the
     component author. They are easier to support in a container
     than XML.

     A scripting language like BeanShell can 'pretend' to be java,
     allowing all the type safety features in java development
     tools to kick in.

     The downside with scripts might be that they are usually
     active rather than passive, and that can be a security risk.
     Though standard java security management can be used to avoid
     those risks.

     My earlier e-mail was mostly about the worries you have
     when you take the next step after a scriptable configuration:
     a scriptable lifecycle (or even scriptable everything).


Avalon-style Configuration
========================================================================
Configuration, avalon-style, is essentially the capturing of the 
component-intrinsic variants of a component (as opposed to its 
invariants or the container-intrinsic variants) into a generic value 
object. This value object is created by end users, typically using xml, 
according to a specification provided by the component author (ideally 
an xml schema, often some javadoc examples), and provided to the 
component by the container during the component startup phase.

Configuration validation would ideally be part of the container's 
featureset, however, currently, most containers don't do configuration 
validation and such validation is, in practice, left up to the 
components. Also, in practice, xml-based configuration validation can be 
very hard; xml simply isn't built for programming. Example:

MyBlah.xconf
--------------------------------------------------------------fragment--
<config>
	<numberOfThreads>15</numberOfThreads>
	<!-- ... -->
</config>

MyBlah.xconf.wrong
--------------------------------------------------------------fragment--
<config>
	<numberOfThreads>fifteen</numberOfThreads>
	<!-- ... -->
</config>

MyBlah.xconf.wrong2
--------------------------------------------------------------fragment--
<config>
	<numberOfThreads>101</numberOfThreads>
	<!-- ... -->
</config>

MyBlah.xconf.wrong3
--------------------------------------------------------------fragment--
<config>
	<numberOfThread>20</numberOfThread>
	<!-- ... -->
</config>

MyBlah.java
------------------------------------------------------------------------
import org.apache.avalon.framework.configuration.*;

package com.blah;

public class MyBlah implements Blah, Configurable
{
   private int m_threads;

   public void configure( Configuration config )
     throws ConfigurationException
   {
     setNumberOfThreads(
         config.getChild("numberOfThreads").getValueAsInteger() );
						// will fail
   }

   public void setNumberOfThreads( int threads )
   {
     assert  threads > 0 : "number of threads must be bigger than 1";
     assert  threads < 100 :
		"number of threads must be smaller than 100";

     m_threads = threads;
   }
}

Fail-safe components thus do something like
--------------------------------------------------------------fragment--
   public void configure( Configuration config )
   {
     int numberofthreads;
     try
     {
       numberofthreads =
           config.getChild("threads").getValueAsInteger();
     }
     catch( ConfigurationException ce )
     {
       numberofthreads = DEFAULT_NUMBER_OF_THREADS;
       getLog().warn(
         "An error occured parsing the configuration: unable figure out"
         + " the number of threads; proceeding with the default value: "
         + DEFAULT_NUMBER_OF_THREADS, ce );
     }
     setNumberOfThreads( numberofthreads );
   }
   public final static int DEFAULT_NUMBER_OF_THREADS = 15;
------------------------------------------------------------------------

There is quite a bit of argument verification (a try/catch clause, 
provision of default values on failure, two assertions) in addition to 
requiring the component author to deal with conversion from a generic 
configuration interface into the component-specific information.

Any of the failures in the config files above will only be detected at 
runtime (unless the component author provides a DTD and the user has an 
editor that checks against that DTD *and* takes the time to configure 
the tool to use the DTD). An error message might look like (in the case 
of a good component writer and a good container):

container.log
--------------------------------------------------------------fragment--
ERROR - MyBlah - An error occured parsing the configuration: unable
   figure out the number of threads; proceeding with the default
   value: 15
   A configuration error occured on line 2 of MyBlah.xconf.wrong2:
   <stack trace goes here/>

but in practice its usually not quite as neat.


Scripted-style configuration
========================================================================
Configuration, scripted, is essentially the capturing of the 
component-intrinsic variants of a component (as opposed to its 
invariants; often the container-intrinsic variants are subject to some 
scripting somewhere as well) either into a component-specific value 
object or directly into the component state. In both cases, the creation 
of the value object or the setting of the state happens in a script.

The creation of the component-specific value object or the setting of 
the component state is done by end users, typically using a scripting 
language, according to a specification provided by the component author 
(in the case of a component-specific value object, the specification is 
encoded into the value object, in the case of component state, the 
specification is encoded into the component its work interface).

Configuration validation would ideally built into an end user tool that 
enforces appropriate contracts (in the case of configuration specified 
as java code, an IDE works very well). In practice, that is only 
feasible using beanshell in 'strict' mode; dominant in the field are 
other scripting languages and a trial-and-error approach.

Consider the above MyBlah class as a POJO component which is scripted by 
a beanshell script in 'strict' mode (that means only actual java syntax 
is allowed, no beanshell-specific shortcuts):

MyBlah2.java
------------------------------------------------------------------------
package com.blah;

public class MyBlah implements Blah
{
   public final static int DEFAULT_NUMBER_OF_THREADS = 15;
   int numberofthreads = DEFAULT_NUMBER_OF_THREADS;

   public void setNumberOfThreads( int threads )
   {
     assert  threads > 0 : "number of threads must be bigger than 1";
     assert  threads < 100 :
		"number of threads must be smaller than 100";

     m_threads = threads;
   }
}

MyBlah.configurator.strict.bsh
------------------------------------------------------------------------
import org.apache.avalon.framework.configuration.Configurator;
import com.blah.MyBlah;

public class MyBlahConfigurator implements Configurator
{
   public void configure( Object component )
   {
     assert component instanceof MyBlah :
         "component must be instance of MyBlah!";

     MyBlah blah = (MyBlah)component;
     component.setNumberOfThreads( 15 );
   }
}
------------------------------------------------------------------------

trick your editor into believing ".bsh" files are similar java files, 
but should not be compiled, and you have near-complete type safety. We 
have just a little bit of error-checking left (three assertions), things 
are /completely/ type-safe, and any stack traces in the event of an 
error will likely provide a lot more clarity. The downside: your end 
user is required to know a bit of java. The configuration file is more 
than a bit complex (though, I would argue, not *that* much more complex 
than xml).

So we put beanshell into its "enhanced" mode, move some of the code into 
the container (the instanceof check, in particular; casts are not 
neccessary in beanshell, and we do a `with(component)`), and you reduce 
the above class definition to:

MyBlah.init.bsh (provided by end user)
------------------------------------------------------------------------
numberOfThreads = 15;

MyBlah.init.bsh.wrong (provided by end user)
------------------------------------------------------------------------
numberOfThreads = 150;

MyBlah.init.bsh.wrong2 (provided by end user)
------------------------------------------------------------------------
numberOfThread = 10;

MyBlah.init.default.bsh (provided by component developer)
------------------------------------------------------------------------
numberOfThreads = 15;

(yes, really, this can be a valid beanshell code snippet and I've got 
proof-of-concept code that illustrates this). The downside here is that 
there is currently no tool around which can ensure compile-time (let 
alone editor-time, like you get in 'strict' mode) safety. But it sure as 
hell is a lot cleaner, and because the format is so much simpler, 
mistakes might not be so easily made.

An error message might look like:

container.log
--------------------------------------------------------------fragment--
ERROR - MyBlah - An error occured parsing configuration file
   MyBlah.init.bsh.wrong on line 1: assertion failed: number of threads
   must be smaller than 100. Proceeding with the default value: 15
   <stack trace goes here/>

The configuration is a lot friendlier than using xml, any error message 
can be just as friendly and just as specific, the container code that 
handles all this can be just as simple, and, what's more, there is less 
checking to do for the component author.

The security issue
========================================================================
The potential downside with scripts is that they are active, whereas 
value objects are passive. Example:

MyBlah.init.bsh.trytohack (provided by end user)
------------------------------------------------------------pseudocode--
numberOfThreads = 15;

stop(); // attempt to stop the MyBlah component
dispose();

// wreak havoc
import com.blah.bank.AccountManager;

billGatesAccount = 12345;
myAccount = 54321;
AccountManager.transfer( 100000, billGatesAccount, myAccount );
------------------------------------------------------------------------

the solution here is to

- either implement a java security policy that denies a configuration 
script the ability to do anything but configure its component, or, more 
simple and more common, or

- to assume that whomever has capability of changing the configuration 
can be trusted.


Giving up a little more safety
========================================================================
So what was I all on about with sacrificing safety and soundness for 
flexibility and stuff? Well, the above just scripts configuration. 
However, it can often be a good idea to just script the complete startup 
sequence. The only thing you let the container do is the dependency 
management and provision of an "execution context"; the component 
instantation and initialization is all up to the script. So something like:

MyBlah.startup.bsh
------------------------------------------------------------pseudocode--
logger = context.getLogger()
workingDirectory = ContextUtil.getWorkingDirectory( context )
otherComponent = container.get( OtherComponent.ROLE )

component = MyBlah( logger, workingDirectory, otherComponent )
component.numberOfThreads = 15
component.initialize()
------------------------------------------------------------------------

you give up some safety here, because you are now depending on the 
configuration script to properly handle the lifecycle startup contract 
(in this case, the scripter might forget to call initialize(). What you 
gain, of course, is flexibility: you can support any component lifecycle 
with no extra container code or any kind of specification at all, by 
virtue of allowing a component-developer-provided, possibly end-user 
modified script to deal with it.

And you don't have to stop there. I'm currently experimenting with 
exactly how much functionality to move into scripts. I'm working on 
stuff which has the following in its Main class:

Main.java
--------------------------------------------------------------fragment--
     public final static void main( String[] args ) throws Exception
     {
         Log log = null;
         Server server = null;

         try
         {
             Interpreter i = new Interpreter();
             i.set( "args", args );
             i.source( "startup.bsh" );

             log = (Log)i.get( "log" );
             server = (Server)i.get( "server" );


Now, /this/ is definately an approach where "startup.bsh" is pretty 
elaborate and places a significant burden on its maintainer to make sure 
it works.


Conclusion
========================================================================
Scripted configuration is definately worth a big BZZZZT! Its way 
cleaner, cooler, faster, simpler, smarter and simply better than 
xml-based configuration.

You can go further than scripted configuration and script large parts of 
your application. Only *then* are you on slippery ground.

g'night!

- Leo



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


Re: [RT] avalon (merlin) == safe == programmer effort

Posted by Stephen McConnell <mc...@apache.org>.

Leo Simons wrote:

> hammett wrote:
>
>>> (as opposed to the conceptually very clean avalon-style
>>> configuration where a component is allowed to "read" from its
>>> configuration, but the configuration itself is passive),
>>
>>
>> Biased! Biased! :-p
>
>
> ROTFL! Me? Nah..... ;)
>
> Seriously, one could only consider it conceptually very clean, don't 
> you think?
>
> The avalon picture
> ------------------
> - a container is responsible for finding/creating the configuration 
> according to preset rules (delegating this responsibility to a 
> specialized component of course), usually allowing for various people 
> in various roles (end users, assemblers, component writers) to follow 
> various contracts to define the configuration,
>
> - a configuration object is then responsible only for existing 
> (implementing the Configuration interface)
>
> - a component is responsible for obeying the directives provided to it 
> by the container in the form of the configuration it receives (and 
> complaining if it doesn't know how).
>
> Clean. Add in some more enforcable rules (like requiring component 
> authors to provide a container-verifiable schema for the configuration 
> format (like a DTD for XML) and component configurators to follow that 
> schema), and, save for bugs, all behaviour is completely 
> deterministic. Clean, safe, sound, understandable.
>
> The downside? In practice, especially with java and xml, it means way 
> many lines of code to write. 

Is this really the case?  If a container does not provide the clean, 
safe, sound and understandable context then your simply transferring the 
responsibility to the component implementation to clean-up its act, 
practice safe sex, demonstrate soundness of judgement, while maintaining 
understandable code. 

Given a scenario of one container, 1,000 component developers, and a 
conservative 20 components per developer ... now let's imaging that each 
developer writes 10 amazingly efficient lines of code in order to 
facilitate responsible component semantics relative to the safe-sex 
viewpoint.  This means that we have a total 10x20x1000 lines of code 
dealing with safe-sex from a number of different positions.  That's 
200,000 lines of code - and we only dealing with one viewpoint! 

The alternative is to push safe-sex handling over to the container.  
Let's assume that a container deals with this with perhaps 200 lines of 
code (taking into account a broad spectrum of positional variations). 
What we have is three order of magnitude improvement in the efficiency 
and maintainability relative to the problems space.

>
>
> Note: its perfectly possible to write a very dynamic scripted 
> avalon-framework container. It just happens to be the case that avalon 
> (especially with Merlin) is moving further and further into the sound 
> and safe, predictable and verifiable corner. In fact, some people 
> (like Steve) assert that a container which is not predictable is a Bad 
> Thing(tm). Me, I strongly disagree with that assertion :D
>
>
> The scripted picture
> --------------------
> - a container will look for a configuration script according to preset 
> rules and run it according to some more rules
>
> - a configuration script had better exist and follow the rules
>
> - a component is not required to do anything special
>
> You lift some responsibility from the component and from the container 
> at the price of requiring the end user to write a sensible 
> configuration script or suffer the consequences.
>
> The upside? Every piece in this system is a lot simpler, and usually 
> you end up with less lines of code everywhere.
>
> The balance
> -----------
> You have a few axes that are not orthogonal:
>
>     clean       <---------------------------> dirty
>     safe        <---------------------------> unsafe
>     complex     <---------------------------> simple
>     static      <---------------------------> flexible
>     much effort <---------------------------> little effort
>
> Sacrifice some conceptual cleanness and predictability and you end up 
> with a system that is both simpler and more flexible, and, most 
> importantly, requires less typing. 


Just so I understand the arguments here ... what you saying is that we 
have this dirty little unsafe container.  And, the principal redeeming 
quality is the attribute of an absence of thought - woops, sorry - effort. 

Ok, I'm hooked, let's go with the flow ;-)

>
>
> Choice
> ------
> In a banking application, you had better make sure that a 
> misconfiguration does not ever result in anything bad happening. I 
> wouldn't want scriptable ATMs. In your average web server, its okay if 
> a web page decides to topple over every now and then, as long as it is 
> easily and quickly fixed. 


BZZZZT (private joke)

Doesn't work in a COP scenario.  You don't know in what context your 
component will be deployed - and without some notion of "quality of 
environment", your strategy destroys the potential for component reuse.  
Sure, if you have a bunch of dirty little components with all of the 
benefits of street-smart wits, running in a dirty little container, 
sure, you have economies of scale.  On the other-hand, maybe I'm missing 
the point ... but ... could you explain to me again why this is a good 
thing?

:-)

Cheers, Steve.

(a dirty little developer brought up in a dirty big container)

-- 

Stephen J. McConnell
mailto:mcconnell@apache.org




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