---
title: Creating a component and module structure
description: Declare templates, modules, libraries and bundles with the Arciphant DSL.
icon: component
sidebar:
  label: Declare Structure
---

## A simple example

Assume you have a modulithic application with 4 domain modules. In each module, you want to have a
clean-architecture-like structure with the domain in the middle:

<Frame caption="Four modules sharing the same clean-architecture-like component structure.">

![Four modules with the components domain, application, web and db](/arciphant/blume-assets/content/content/images/structure-01-modules.svg)

</Frame>

Building this structure with plain nested Gradle projects means a lot of duplicated build setup. With Arciphant you can
configure a template that defines the structure of the components (rings) of a module and then use this template to
create (instantiate) the 4 modules:

```kotlin settings.gradle.kts
arciphant {
    val moduleTemplate = template()
        .createComponent(name = "domain")
        .createComponent(name = "application", apiDependencies = setOf("domain"))
        .createComponent(name = "web", dependencies = setOf("application"))
        .createComponent(name = "db", dependencies = setOf("application"))

    module(name = "module-a", template = moduleTemplate)
    module(name = "module-b", template = moduleTemplate)
    module(name = "module-c", template = moduleTemplate)
    module(name = "module-d", template = moduleTemplate)
}
```

The above configuration creates the following structure and sets up the dependencies between the components (domain,
application, web, db) in each module. How the components are mapped to Gradle depends on the configured
[component layout](/component-layouts):

**Project layout**

Every component becomes its own nested Gradle project (<Icon class="inline" name="package" size={15} />) with the
    standard Gradle source sets (<Icon class="inline" name="folder-code" size={15} />):

<Tree>
  <Tree.Folder name="root-project" icon="package" defaultOpen>
    <Tree.Folder name="module-a" icon="package" defaultOpen>
      <Tree.Folder name="domain" icon="package" defaultOpen>
        <Tree.Folder name="src" defaultOpen>
          <Tree.Folder name="main" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="test" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="testFixtures" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>
      <Tree.Folder name="application" icon="package" defaultOpen>
        <Tree.Folder name="src" defaultOpen>
          <Tree.Folder name="main" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="test" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="testFixtures" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>
      <Tree.Folder name="web" icon="package" defaultOpen>
        <Tree.Folder name="src" defaultOpen>
          <Tree.Folder name="main" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="test" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="testFixtures" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>
      <Tree.Folder name="db" icon="package" defaultOpen>
        <Tree.Folder name="src" defaultOpen>
          <Tree.Folder name="main" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="test" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="testFixtures" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>
    </Tree.Folder>
    <Tree.Folder name="module-b" icon="package" defaultOpen>
      <Tree.Folder name="domain" icon="package">
        <Tree.Folder name="src">
          <Tree.Folder name="main" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="test" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="testFixtures" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>
      <Tree.Folder name="application" icon="package">
        <Tree.Folder name="src">
          <Tree.Folder name="main" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="test" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="testFixtures" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>
      <Tree.Folder name="web" icon="package">
        <Tree.Folder name="src">
          <Tree.Folder name="main" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="test" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="testFixtures" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>
      <Tree.Folder name="db" icon="package">
        <Tree.Folder name="src">
          <Tree.Folder name="main" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="test" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="testFixtures" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>
    </Tree.Folder>
    <Tree.Folder name="module-c" icon="package" defaultOpen>
      <Tree.Folder name="domain" icon="package">
        <Tree.Folder name="src">
          <Tree.Folder name="main" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="test" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="testFixtures" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>
      <Tree.Folder name="application" icon="package">
        <Tree.Folder name="src">
          <Tree.Folder name="main" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="test" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="testFixtures" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>
      <Tree.Folder name="web" icon="package">
        <Tree.Folder name="src">
          <Tree.Folder name="main" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="test" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="testFixtures" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>
      <Tree.Folder name="db" icon="package">
        <Tree.Folder name="src">
          <Tree.Folder name="main" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="test" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="testFixtures" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>
    </Tree.Folder>
    <Tree.Folder name="module-d" icon="package" defaultOpen>
      <Tree.Folder name="domain" icon="package">
        <Tree.Folder name="src">
          <Tree.Folder name="main" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="test" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="testFixtures" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>
      <Tree.Folder name="application" icon="package">
        <Tree.Folder name="src">
          <Tree.Folder name="main" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="test" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="testFixtures" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>
      <Tree.Folder name="web" icon="package">
        <Tree.Folder name="src">
          <Tree.Folder name="main" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="test" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="testFixtures" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>
      <Tree.Folder name="db" icon="package">
        <Tree.Folder name="src">
          <Tree.Folder name="main" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="test" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
          <Tree.Folder name="testFixtures" icon="folder-code">
            <Tree.Folder name="kotlin" />
          </Tree.Folder>
        </Tree.Folder>
      </Tree.Folder>
    </Tree.Folder>
  </Tree.Folder>
</Tree>

    `src/testFixtures` is only present once the optional `java-test-fixtures` plugin is applied — see
    [Structure test code](#structure-test-code).

**Source set layout**

Every module becomes one Gradle project (<Icon class="inline" name="package" size={15} />) whose components are
    source sets (<Icon class="inline" name="folder-code" size={15} />):

<Tree>
  <Tree.Folder name="root-project" icon="package" defaultOpen>
    <Tree.Folder name="module-a" icon="package" defaultOpen>
      <Tree.Folder name="src" defaultOpen>
        <Tree.Folder name="domain" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="domainTest" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="domainTestFixtures" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="application" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="applicationTest" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="applicationTestFixtures" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="web" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="webTest" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="webTestFixtures" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="db" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="dbTest" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="dbTestFixtures" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
      </Tree.Folder>
    </Tree.Folder>
    <Tree.Folder name="module-b" icon="package" defaultOpen>
      <Tree.Folder name="src" defaultOpen>
        <Tree.Folder name="domain" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="domainTest" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="domainTestFixtures" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="application" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="applicationTest" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="applicationTestFixtures" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="web" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="webTest" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="webTestFixtures" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="db" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="dbTest" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="dbTestFixtures" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
      </Tree.Folder>
    </Tree.Folder>
    <Tree.Folder name="module-c" icon="package" defaultOpen>
      <Tree.Folder name="src" defaultOpen>
        <Tree.Folder name="domain" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="domainTest" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="domainTestFixtures" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="application" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="applicationTest" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="applicationTestFixtures" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="web" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="webTest" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="webTestFixtures" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="db" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="dbTest" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="dbTestFixtures" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
      </Tree.Folder>
    </Tree.Folder>
    <Tree.Folder name="module-d" icon="package" defaultOpen>
      <Tree.Folder name="src" defaultOpen>
        <Tree.Folder name="domain" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="domainTest" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="domainTestFixtures" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="application" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="applicationTest" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="applicationTestFixtures" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="web" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="webTest" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="webTestFixtures" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="db" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="dbTest" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
        <Tree.Folder name="dbTestFixtures" icon="folder-code">
          <Tree.Folder name="kotlin" />
        </Tree.Folder>
      </Tree.Folder>
    </Tree.Folder>
  </Tree.Folder>
</Tree>

    The `…Test` and `…TestFixtures` source sets are created by default; they can be renamed or disabled — see
    [Component layouts](/component-layouts) for the details.

## Dependency types

You probably noticed the two attributes for setting up dependencies between components:

- `dependencies`: Creates an _implementation_ dependency from component _A_ to component _B_
- `apiDependencies`: Creates an _api_ (transitive) dependency from component _A_ to component _B_, meaning that every
  component depending on _A_ gets access to _B_

In the above example this means that _web_ and _db_ can access _domain_ thanks to the API dependency of _application_.

:::info[Transitive dependencies in Clean Architecture]
Whether transitive dependencies (i.e. `apiDependencies`) are reasonable in a clean architecture or whether each ring (component) should only access the next inner ring is an interesting discussion.

Since Arciphant is a tool and not a methodology, it provides the ability without making a statement whether to use it or not.
:::

## Shared code

Now assume that for each of the components (rings) you need some shared code (e.g. some shared utility for all
db-components). So what you can do is create a shared library module with the same component structure. The following
image shows this setup (with only two modules for simplicity):

<Frame caption="A shared library module with the same component structure (shown with two modules for simplicity).">

![Two modules whose components depend on the same-named components of a shared library module](/arciphant/blume-assets/content/content/images/structure-02-library.svg)

</Frame>

Normally you would have to manage all these dependencies manually, which is error-prone and pollutes the Gradle build
setup with repetitive code.

Arciphant instead provides an out-of-the-box mechanism: you can specify a library module:

```kotlin
library(name = "shared", template = moduleTemplate)
```

Each component of each domain module automatically gets an <Tooltip headline="api dependency" tip="A transitive dependency: whatever depends on the component also gets access to the shared library code." cta="Dependency types" href="#dependency-types">`api` dependency</Tooltip> on the same-named component in the library
module.

<Expandable title="Complete settings.gradle.kts">

```kotlin settings.gradle.kts {8}
arciphant {
    val moduleTemplate = template()
        .createComponent(name = "domain")
        .createComponent(name = "application", apiDependencies = setOf("domain"))
        .createComponent(name = "web", dependencies = setOf("application"))
        .createComponent(name = "db", dependencies = setOf("application"))

    library(name = "shared", template = moduleTemplate)

    module(name = "module-a", template = moduleTemplate)
    module(name = "module-b", template = moduleTemplate)
    module(name = "module-c", template = moduleTemplate)
    module(name = "module-d", template = moduleTemplate)
}
```

</Expandable>

:::info[Shared libraries for independent modules?]
Whether a shared library is reasonable for independent domain modules may vary from case to case.
It is probably more accepted in case of a modulith than with microservices. Again, Arciphant provides the ability
without making a statement whether to use it or not.
:::

## Different shapes

Now assume that some modules (e.g. Module C and Module D) need access to a file store (e.g. MinIO). You want to put this
code into a separate component called `fs` like the following:

<Frame caption="Modules C and D with an additional `fs` component.">

![Modules C and D with an additional fs component, modules A and B without](/arciphant/blume-assets/content/content/images/structure-03-different-shapes.svg)

</Frame>

You can solve this problem by creating another template, extending from the existing template:

```kotlin
val moduleWithFsTemplate = template()
    .extends(moduleTemplate)
    .createComponent(name = "fs", dependencies = setOf("application"))
```

<Expandable title="Complete settings.gradle.kts">

```kotlin settings.gradle.kts {8-10,12,16-17}
arciphant {
    val moduleTemplate = template()
        .createComponent(name = "domain")
        .createComponent(name = "application", apiDependencies = setOf("domain"))
        .createComponent(name = "web", dependencies = setOf("application"))
        .createComponent(name = "db", dependencies = setOf("application"))

    val moduleWithFsTemplate = template()
        .extends(moduleTemplate)
        .createComponent(name = "fs", dependencies = setOf("application"))

    library(name = "shared", template = moduleWithFsTemplate)

    module(name = "module-a", template = moduleTemplate)
    module(name = "module-b", template = moduleTemplate)
    module(name = "module-c", template = moduleWithFsTemplate)
    module(name = "module-d", template = moduleWithFsTemplate)
}
```

</Expandable>

:::note
Even though not all modules require the additional `fs` component, the library can be constructed out of
`moduleWithFsTemplate`. For modules without `fs` component, this is ignored.
:::

## Individual shapes

Of course, it is also possible to declare individual components in particular modules. E.g. if Module D requires the
integration of an external API, you want to create a dedicated component 'ext-api' for the integration code:

<Frame caption="Module D with an individual `ext-api` component.">

![Module D with an individual ext-api component](/arciphant/blume-assets/content/content/images/structure-04-individual-shapes.svg)

</Frame>

To do so, you can create a component for the specific module:

```kotlin
module(name = "module-d", template = moduleWithFsTemplate)
    .createComponent(name = "ext-api", dependencies = setOf("application"))
```

<Expandable title="Complete settings.gradle.kts">

```kotlin settings.gradle.kts {18}
arciphant {
    val moduleTemplate = template()
        .createComponent(name = "domain")
        .createComponent(name = "application", apiDependencies = setOf("domain"))
        .createComponent(name = "web", dependencies = setOf("application"))
        .createComponent(name = "db", dependencies = setOf("application"))

    val moduleWithFsTemplate = template()
        .extends(moduleTemplate)
        .createComponent(name = "fs", dependencies = setOf("application"))

    library(name = "shared", template = moduleWithFsTemplate)

    module(name = "module-a", template = moduleTemplate)
    module(name = "module-b", template = moduleTemplate)
    module(name = "module-c", template = moduleWithFsTemplate)
    module(name = "module-d", template = moduleWithFsTemplate)
        .createComponent(name = "ext-api", dependencies = setOf("application"))
}
```

</Expandable>

## Extending components

A template defines which dependencies a component has by default. Sometimes a single module needs an _additional_
dependency between components it inherited from the template. Continuing the example above: in Module D, the `web`
component should also be able to use the new `ext-api` component. Declaring `createComponent(name = "web", ...)` again
would fail because the component already exists — use `extendComponent` instead:

```kotlin {3}
module(name = "module-d", template = moduleWithFsTemplate)
    .createComponent(name = "ext-api", dependencies = setOf("application"))
    .extendComponent(name = "web", dependencies = setOf("ext-api"))
```

`extendComponent` adds the given `dependencies` and/or `apiDependencies` to the already declared component. Everything
else (the registered plugin and the existing dependencies) remains untouched. It is also available on templates, so a
template that `extends` another template can add dependencies to the inherited components as well.

:::note
`createComponent` and `extendComponent` are strict: creating a component that already exists fails, and so does
extending a component that does not exist. Each component can be extended at most once per module or template.
:::

## Multiple templates

A module or library can also be created from _several_ templates at once. The components of all templates are combined:

```kotlin
val messagingTemplate = template()
    .createComponent(name = "events", dependencies = setOf("application"))

module(name = "module-e", templates = setOf(moduleTemplate, messagingTemplate))
```

Each component name may only be declared by one of the combined templates — combining templates that both declare a
component of the same name is a configuration error.

Templates are optional, by the way: a module can also be declared without any template and consist solely of individual
components:

```kotlin
module(name = "tooling")
    .createComponent(name = "cli")
```

## Bundle modules

Domain modules should typically remain as isolated as possible. However, to package an application we need some kind of
bundle module that brings together all the modules. In Arciphant, it is possible to define bundle modules:

```kotlin
bundle(name = "my-app")
```

This creates a module `my-app` that has a dependency to all components of all <Tooltip headline="Functional module" tip="Domain and library modules — modules that consist of components. Bundle modules are not functional modules." cta="Concepts" href="/concepts#module">functional modules</Tooltip>. The bundle module itself does not
have any components. A convention plugin (e.g. for packaging the application with Spring Boot) can be registered for a
bundle — see [Bundle plugins](/using-plugins#bundle-plugins).

It is also possible to declare explicit dependencies, e.g. if you need multiple different bundles that should _not_
automatically depend on all functional modules:

```kotlin
bundle(name = "bundleX", includes = setOf(coreModuleA, coreModuleB, specificModuleX))
bundle(name = "bundleY", includes = setOf(coreModuleA, coreModuleB, specificModuleY))
```

Bundles can also include other bundles. So the above example could also be specified as follows to reduce duplication:

```kotlin
val coreBundle = bundle(name = "core", includes = setOf(coreModuleA, coreModuleB))
bundle(name = "bundleX", includes = setOf(coreBundle, specificModuleX))
bundle(name = "bundleY", includes = setOf(coreBundle, specificModuleY))
```

## Structure test code

`java-test-fixtures` is a nice little Gradle plugin to deal with reusable test setup code. It basically creates an
additional source set `testFixtures` in between `main` and `test`. While `test` code should remain isolated, the idea of
`testFixtures` is that this code can be reused in other Gradle projects.
See [official documentation](https://docs.gradle.org/current/userguide/java_testing.html#sec:java_test_fixtures) for
further information.

Arciphant plays nicely with `java-test-fixtures`: If `java-test-fixtures` is applied in the Gradle build, it
automatically creates the dependencies for the `testFixtures` source sets between components. So if e.g. the
_application_ component depends on _domain_, the `testFixtures` of `domain` will be usable in `testFixtures` and `test`
of `application`. Of course, if it is an api dependency, the transitivity is also taken into account.

:::note[Source set layout]
This describes the default project layout. In the source set layout, Arciphant creates dedicated production,
test-fixtures, and test source sets itself; the `java-test-fixtures` plugin is not required.
See [Component Layouts](/component-layouts#test-source-set-configuration) for configuration details.
:::

## Debug project dependencies

:::tip[Print the wired dependencies]
To verify whether the dependencies Arciphant wired are as expected, run `./gradlew -q projectDependencies` — see
[Gradle tasks](/tasks#projectdependencies). The task only prints dependencies between Gradle projects; in the source
set layout, the component wiring inside a module does not appear.
:::
