polygene-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Paul Merlin <p...@nosphere.org>
Subject Re: Assembly proposal
Date Thu, 21 May 2015 10:09:48 GMT
Niclas Hedhman a écrit :
> Gang, (warning; long)
Took me a while to ingest. Some comments inline.

> Long tima ago, when the Assembly system was first created, we had very
> little experience of what would be needed, and kept the API very
> minimalistic. One area that was left out completely (on purpose) was to
> provide a more declarative way author the application structure.
>
> A few applications later, I keep re-implementing the same thing over and
> over. It looks like this;
>
>
>     public interface LayerAssembler
>     {
>         LayerAssembly assemble() throws AssemblyException;
>     }
>
>     public interface ModuleAssembler
>     {
>         ModuleAssembly assemble()
>             throws AssemblyException;
>     }
>
> And then implementations of those becomes like this;
>
>     public class DomainLayer
>         implements LayerAssembler
>     {
>         public static final String NAME = "domain";
>         private final LayerAssembly layer;
>
>         public DomainLayer( LayerAssembly layer )
>         {
>             this.layer = layer;
>         }
>
>         @Override
>         public LayerAssembly assemble()
>             throws AssemblyException
>         {
>             new CommandLineModule( layer.module( CommandLineModule.NAME )
> ).assemble();
>             new HostModule( layer.module( HostModule.NAME ) ).assemble();
>             new ContainersModule( layer.module( ContainersModule.NAME )
> ).assemble();
>             return layer;
>         }
>     }
>
>
>     public class CommandLineModule
>         implements ModuleAssembler
>     {
>         public static final String NAME = "domain";
>         private final ModuleAssembly module;
>
>         public CommandLineModule( ModuleAssembly module )
>         {
>             this.module = module;
>         }
>
>         @Override
>         public ModuleAssembly assemble()
>             throws AssemblyException
>         {
>             module.services( CommandLineExecutor.class ).visibleIn(
> Visibility.layer );
>             module.values( CommandLine.class );
>             return module;
>         }
>     }
>
> The reason for injecting the layer and module into the constructor instead
> of assemble() method, is because every now and then additional arguments
> might be needed.
>
> So it is all put together as
>
>     public class MyAppAssembler
>         implements ApplicationAssembler
>     {
>         private static final String NAME = "My Application Name";
>         private static final String VERSION = "1.0";
>         private final Application application;
>
>         public MyAppAssembler()
>             throws AssemblyException
>         {
>             Energy4Java qi4j = new Energy4Java();
>             ApplicationDescriptor model = qi4j.newApplicationModel( this );
>             application = model.newInstance( qi4j.spi() );
>         }
>
>         public Application application()
>         {
>             return application;
>         }
>
>         public void start()
>             throws ActivationException
>         {
>             application.activate();
>         }
>
>         public void stop()
>             throws PassivationException
>         {
>             application.passivate();
>         }
>
>         @Override
>         public ApplicationAssembly assemble( ApplicationAssemblyFactory
> applicationFactory )
>             throws AssemblyException
>         {
>             ApplicationAssembly assembly =
> applicationFactory.newApplicationAssembly();
>             assembly.setName( NAME );
>             assembly.setName( VERSION );
>             LayerAssembly infraLayer = new InfrastructureLayer(
> assembly.layer( InfrastructureLayer.NAME ) ).assemble();
>             LayerAssembly domainLayer = new DomainLayer( assembly.layer(
> DomainLayer.NAME ) ).assemble();
>             LayerAssembly serviceLayer = new ServiceLayer( assembly.layer(
> ServiceLayer.NAME ) ).assemble();
>             LayerAssembly connectivityLayer = new ConnectivityLayer(
> assembly.layer( ConnectivityLayer.NAME ) ).assemble();
>
>             connectivityLayer.uses( serviceLayer );
>             serviceLayer.uses( domainLayer );
>             serviceLayer.uses( infraLayer );
>             domainLayer.uses( infraLayer );
>             return assembly;
>         }
>     }
>
>
> So, first I would like to add the ModuleAssembler and LayerAssembler as
> Core Bootstrap classes. Secondly, I would to create a abstract class,
> perhaps named LayeredApplicationAssembler, which encapsulates the
> boilerplate code, and defines a "Layer DSL", maybe something like this;
>
>     public class MyAppAssembler extends LayeredApplicationAssembler
>     {
>         public MyAppAssembler( String name, String version, Mode mode )
>         {
>             super( name, version, mode );
>         }
>
>         protected void onAssembly()
>         {
>             LayerAssembly infraLayer = layer().definedBy( new
> InfrastructureLayer() );
>             LayerAssembly domainLayer = layer().definedBy( new
> DomainLayer() ).uses( infraLayer );
>             LayerAssembly serviceLayer = layer().definedBy( new
> ServiceLayer() ).uses( domainLayer, infraLayer );
>             layer().definedBy( new ConnectivityLayer() ).uses( serviceLayer
> );
>         }
>     }
>
> IMHO, this is quite a nice improvement over the current flexibility that
> exists.
This LGTM and should work well with existing helpers in Assemblers
(config/identity/visibility).


> But, I have also previously mentioned that an annotated solution might be
> even cooler.
>
> public class MyAppAssembler extends AnnotatedApplicationAssembler
> {
>     @Uses( ServiceLayer.class )
>     interface ConnectivityLayer
>     {
>         ModuleAssembler MODULES = {
>             RestModule.class,
>             WebAppModule.class
>         };
>     }
>
>     @Uses( { DomainLayer.class, InfrastructureLayer.class } )
>     interface ServiceLayer
>     {
>         ModuleAssembler MODULES = {
>             DeploymentModule.class,
>             ManagementModule.class,
>             MonitoringModule.class
>         };
>     }
>
>     @Uses( InfrastructureLayer.class )
>     interface DomainLayer
>     {
>         ModuleAssembler MODULES = {
>             CommandLineModule.class,
>             HostsModule.class,
>             ContainersModule.class
>         };
>     }
>
>     interface InfrastructureLayer
>     {
>         ModuleAssembler MODULES = {
>             StorageModule.class,
>             ConfigModule.class,
>             IndexingModule.class
>         };
>     }
> }
>
> The entire application structure overview captured in a single document,
> with all the implementation detail noise removed.
Looks neat. Kind of magic. Shouldn't we wait to master assembly using
Java 8 constructs before adding something like that?

That's it for now.

Cheers

/Paul


Mime
View raw message