polygene-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Niclas Hedhman <nic...@hedhman.org>
Subject Re: Assembly proposal
Date Mon, 15 Jun 2015 02:47:31 GMT
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
-- 
Niclas Hedhman, Software Developer
http://zest.apache.org - New Energy for Java

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message