11.7.  Connecting Complex Artifacts

In this section we will examine the different possibilities to define connections between complex artifacts. Let us assume we use the following aspect file to describe the inner structure of a business module:

// File layering.arc
exposed artifact UI
{
    include "**/ui/**"
    connect to Business
}
exposed artifact Business
{
    include "**/business/**"

    interface default
    {
        // Only classes in the "iface" package can be used from outside
        include "**/iface/*"
    }
    
    connect to Persistence
}
artifact Persistence
{
    include "**/persistence/**"
}
exposed public artifact Model
{
    include "**/model/**"
}
    

This example also show a special feature of our DSL. You can redefine the default interface if you want to restrict incoming dependencies to a subset of the elements assigned to an artifact. Our layer "Business" is now only accessible over the classes in the "iface" package.

Now lets bring in some business modules:

// File modules.arc
artifact Customer
{
    include "Customer/**" // All in module "Customer"
    apply "layering"
    connect to Core
}
artifact Product
{
    include "Product/**" // All in module "Product"
    apply "layering"
    connect to Core
}
artifact Core
{
    include "Core/**" // All in module "Core"
    apply "layering"
}
    

Here "Customer" and "Product" are connected to "Core". We used the most simple way to connect those artifacts which means that all elements in "Customer" or "Product" can use everything in the default interface of "Core". Since we redefined the default interface of "Business" this is not everything in "Core". The default interface of "Core" exports all default interfaces of non-hidden nested artifacts which means that the restrictions defined in "Business" are respected by surrounding artifacts.

Nevertheless this way of connecting artifacts does not give us enough control. For example "Product.Model" could now access "Core.UI" - not pretty. That means we need to put a bit more effort into the connection:

// File modules.arc
artifact Customer
{
    include "Customer/**" // All in module "Customer"
    apply "layering"
    
    connect UI to Core.UI, Core.Controller, Core.Model
    connect Controller to Core.Controller, Core.Model
    connect Model to Core.Model
}
artifact Product
{
    include "Product/**" // All in module "Product"
    apply "layering"
    
    connect UI to Core.UI, Core.Controller, Core.Model
    connect Controller to Core.Controller, Core.Model
    connect Model to Core.Model
}
artifact Core
{
    include "Core/**" // All in module "Core"
    apply "layering"
}
    

Now we are more specific about the details of our connection. Please note that we can only connect to "UI", "Controller" and "Model" of "Core" because we have marked those artifacts as exposed. Otherwise they would be encapsulated and not directly accessible. The "Persistence" layer is not exposed and can therefore only be used from inside its enclosing artifact.