Niclas,
I agree that the ApplicationBuilder DSL gets messy easily. Just like any
home-made assembly using the low-level api. It's JSON support is neat
but I had no use of it yet, so ...
I like your approach for Layered applications. I can't see any limit to
what can be done that way and it feels cleaner than low-level assembly.
Probably much easier for newcomers.
Jiri, I agree, this solves only a part of the "problem". For "external
view", I'd say something like Tower or Stacks/BluePrints that we
discussed in the past will be needed.
My 0.2c.
/Paul
Niclas Hedhman a écrit :
> Gang, (again, a bit long...)
>
> I am comparing the ApplicationBuilder, with its DSL and the way I did it in
> my latest application.
> The ApplicationBuilder is cute that it supports JSON, but IMHO it doesn't
> read nicely in code, as there is no "natural" isolation/separation, and
> quickly gets rather 'unruly'. Such 'messy' tendency might become the case
> of the "magic" that I wrote about earlier in this thread as well, since I
> haven't tested that yet. That will be revisited later...
>
> But the ModuleAssembler, LayerAssembler and LayeredApplicationAssembler
> that I am using "feels" quite nice, at least to me and I think(!) that it
> is easier for a newbie to follow and "do the right thing" rather than the
> DSL, which easily gets messy without discipline.
>
> Let's look at a concrete example, and a STRESS that there are no "snips" in
> the assembler classes below other than "import", the classes below are
> complete...
>
> The top application ends up look like this;
>
> public class TestingLayeredApplicationAssembler extends
> LayeredApplicationAssembler
> {
> public TestingLayeredApplicationAssembler( String name, String version )
> throws AssemblyException
> {
> super( name, version );
> }
>
> @Override
> protected void assembleLayers( ApplicationAssembly assembly )
> throws AssemblyException
> {
> LayerAssembly configLayer = createLayer( ConfigurationLayer.class );
> ModuleAssembly configModule = configLayer.module(
> "Configuration Module" );
> LayerAssembly infraLayer = new InfrastructureLayer(
> configModule ).assemble( assembly.layer( InfrastructureLayer.NAME ));
> LayerAssembly domainLayer = createLayer( DomainLayer.class );
> LayerAssembly serviceLayer = createLayer( ServiceLayer.class );
> LayerAssembly connectivityLayer = createLayer(
> ConnectivityLayer.class );
>
> connectivityLayer.uses( serviceLayer );
> connectivityLayer.uses( domainLayer );
> serviceLayer.uses( domainLayer );
> domainLayer.uses( infraLayer );
> infraLayer.uses( configLayer );
> }
> }
>
> And Layers can either be 'manual' such as in the InfrastructureLayer
> example above, or can be 'magical' as the others are. Name to the layer is
> given through the classname of the LayerAssembler.
>
> So, the DomainLayer would look like;
>
> public class DomainLayer extends LayeredLayerAssembler
> {
> @Override
> public LayerAssembly assemble( LayerAssembly layer )
> throws AssemblyException
> {
> createModule( layer, InvoicingModule.class );
> createModule( layer, OrderModule.class );
> return layer;
> }
> }
>
>
> where again it is mostly 'magical' deriving names from the ModuleAssembler
> name, but can be 'manual' as we need in the InfrastructureLayer;
>
> public class InfrastructureLayer extends LayeredLayerAssembler
> implements LayerAssembler
> {
> public static final String NAME = "Infrastructure Layer";
> private final ModuleAssembly configModule;
>
> public InfrastructureLayer( ModuleAssembly configModule )
> {
> this.configModule = configModule;
> }
>
> @Override
> public LayerAssembly assemble( LayerAssembly layer )
> throws AssemblyException
> {
> new StorageModule( layer.module( StorageModule.NAME ),
> configModule ).assemble();
> new IndexingModule( layer.module( IndexingModule.NAME ),
> configModule ).assemble();
> createModule( layer, SerializationModule.class );
> return layer;
> }
> }
>
>
> since we are using the DSL in the Assemblers of storage and indexing.
>
> ModuleAssemblers have no 'magical' part, so they are fairly straight
> forward. So from the above, an OrderModuler could be;
>
> public class OrderModule implements ModuleAssembler
> {
> @Override
> public ModuleAssembly assemble( ModuleAssembly module )
> throws AssemblyException
> {
> module.entities( Order.class, Customer.class );
> module.values( Address.class );
> return module;
> }
> }
>
>
> and the IndexingModule would have something like;
>
> public class IndexingModule
> implements ModuleAssembler
> {
> private final ModuleAssembly configModule;
>
> public IndexingModule( ModuleAssembly configModule )
> {
> this.configModule = configModule;
> }
>
> @Override
> public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly
> module )
> throws AssemblyException
> {
> new FileConfigurationAssembler().assemble( module );
> new ESFilesystemIndexQueryAssembler()
> .visibleIn( Visibility.application )
> .withConfig( configModule, Visibility.application )
> .assemble( module );
> return module;
> }
> }
>
>
> So, what's the verdict? I have this more or less ready (need to document
> it), and although I think it "competes" with other ways of doing assembly,
> I think it is quite neat and tidy, helping newcomers to get structured (I
> create one package per layer, and its parent contains the
> ApplicationAssembler implementation)
>
>
> Cheers