Basic Project Structure¶
AaC is unopinionated about project structures, so they can be very flexible. However, we do suggest storing models in an organized project directory structure, such as maintaining all AaC files under a top, or near-top level directory src/
. An example project might look like:
src
├── system
│ └── system.yaml
├── external
| ├── external_actors.yaml
│ └── external_interface_messages.yaml
├── service_one
| ├── service_one.yaml
│ └── service_one_misc.yaml
└── service_two
└── service_two.yaml
Because AaC does not require your models to be located within the same directory, you can house your model files however is necessary and logical for your project needs. An example of this might look like:
system └── system.yaml external ├── external_actors.yaml └── external_interface_messages.yaml service_one ├── service_one.yaml └── service_one_misc.yaml service_two └── service_two.yaml
Anatomy of an AaC file¶
Since AaC leverages YAML for its DSL, there are very few restrictions on how to store and organize AaC files and AaC definitions. The main consideration is that every AaC definition must be defined in its own YAML document or YAML file.
YAML provides a keyword/symbol ---
to denote a logical document separator for multiple YAML documents within a YAML file. This means that if we store multiple AaC definitions in the same file, they must be separated using the ---
symbol. If they aren’t separated correctly then the AaC file will not be recognized as a valid AaC definition.
These two examples are equivalent and both valid:
schemas.yaml
schema:
name: Schema1
fields:
- name: integer
type: int
---
schema:
name: Schema2
fields:
- name: string
type: string
schema1.yaml
schema:
name: Schema1
fields:
- name: integer
type: int
schema2.yaml
schema:
name: Schema2
fields:
- name: string
type: string
Referencing AaC Structures Across Files¶
Another consideration when deciding how to organize AaC definitions is which definitions reference each other. If definition A
references definition B
, then both definitions will need to be either declared in the same AaC file or definition A
will need to define an import
including the absolute or relative path to the file containing definition B
.
For this example, schemaA
references schemaB
, and both definitions are in separate files, as a result schemaA
is importing the file containing schemaB
.
Additionally, while it’s possible to have multiple import
definitions in a file, good style would suggest using a single import
list per file.
An example of a relative path import is: schemaA.yaml
import:
files:
- ./schemaB.yaml
---
schema:
name: schemaA
fields:
- name: sub-datastructure
type: schemaB
- name: integer
type: int
schemaB.yaml
schema:
name: schemaB
fields:
- name: string
type: string
An example of a an absolute path import is: schemaA.yaml
import:
files:
- C:/src/external/external_actors/schemaB.yaml
---
schema:
name: schemaA
fields:
- name: sub-datastructure
type: schemaB
- name: integer
type: int
schemaB.yaml
schema:
name: schemaB
fields:
- name: string
type: string
Embedding AaC files alongside your implementation¶
Because AaC can be used to generate code, users may find themselves with a project repository consisting of:
AaC files that describe the architecture and drive code-stub generation
Version-controlled implementation files that compliment the stub/interface code files generated by AaC
There is no requirement to maintain these files in any sort of relationship or directory structure as long as the AaC files can reference each other. The best practice would be to have your VCS ignore the generated/stubbed files and leverage automated workflows and user/developer environments to generate the stub/interface files as fresh artifacts every time they’re used – this helps prevent configuration drift between what is defined in your AaC files and the downstream artifacts.
Creating a User Library for your project¶
Because of the extensibility and reusability goals of AaC, a plugin can also be designed as a library for a project. By making a plugin to function more as a library, it exposes itself as a tool to be utilized in a larger context throughout the AaC space.
For more information on making a User Library, view Creating a User Library.