Skip to content
Tim Kleier edited this page Feb 12, 2024 · 68 revisions

Declarative Notation for Applications (DNA)

In the human body, DNA functions as a set of instructions for development and functioning. This project aims to do the same for software applications. Declarative Notation for Applications (DNA) is designed to be a set of portable, language-agnostic, structured instructions for building software.

Here's a small snippet that describes an ArticlePublished schema:

DNA:
  Schemas:
    ArticlePublished:
      Description: Article is marked as published
      Version: 1.1
      Properties:
        Title:
          Description: The title of a blog post
          PropertyType: String
          MaxLength: 30
        Published: Boolean
        DatePublished: Date
    ...

Introduction

DNA may be best described as Configuration-as-Code or Specification-as-Code. Engineering teams define business and application logic in a specification (written in JSON/YAML) that can be imported into almost any programming environment. DNA can be used in traditional contexts and is apt for the emerging Generative AI space as well.

How It Works

DNA can be defined by hand (in YAML files), through a UI (DNA App), or GenAI (agents/LLMs/GPTs). Then it can be loaded into language parsers or a GenAI flow and used to generate code, documentation, etc.

How DNA Works

Scope

At some point in the future, DNA may cover application and infrastructure instructions. For now, it is focused on the core purpose of describing domain logic.

Use Cases

  • Defining Business Logic - DNA provides a clear structure for expressing business logic and forms a bridge between product requirements and code.
  • Code/App Generation - Generate code from a DNA spec in any programming language. Use DNA with AI agents to generate full applications.
  • Shared Object/Schema Library - Create and share objects/schemas across the frontend and backend or across microservices.
  • Documentation Generation - Leverage DNA to create documentation of business logic in plain text (for wikis), markdown, or images (for diagrams).
  • App Modernization - Use DNA to extract domain logic out of legacy apps so they can be modernized.

Usage

There are a few key things to keep in mind when defining DNA:

  1. Basic & Expanded Form
  2. Conventions

Basic & Expanded Forms

DNA specs can be written in Basic or Expanded form. You can switch between the two as needed.

Basic form is concise, simplifying Objects, for example, down to merely a set of Properties in this format: PropertyName: PropertyType.

Article:
  Title: String
  Published: Boolean
  PublishedDate: Date
  Comments: [Comment] # a Comment array, one-to-many

Expanded form is much more flexible and allows for the addition of a description and constraints (like MaxLength). You can also use basic form with expanded DNA.

Article:
  Description: A blog Post
  Properties:
    Title:
      Description: The title of a blog post
      PropertyType: String
      Required: True
      MaxLength: 30
    Published: Boolean # basic form
    PublishedDate: Date # basic form
    Comments:
      PropertyType: Array
      DataItemType: Comment
     

Conventions

Title/Pascal Case

For readability and preservation of business/operational names and titles, as well as flexibility in parsing/translating to target programming languages, DNA uses Title/Pascal case.

YAML vs JSON

YAML was chosen over JSON due to its readability and simplicity in expressing DNA instructions. However, YAML and JSON are almost completely interchangeable, so DNA can be converted to JSON as needed.

Specification

DNA aims to describe the business domain that applications support. It is made up of the following:

  • Objects (v1.0)
  • Properties (v1.0)
  • Schemas (v1.0)
  • Actions
  • Policies
  • Logic

Objects

Objects are the key nouns of the domain, like Products and Orders (eCommerce), Articles (blogging), or Loan (lending). Objects on their own are quite simple, as they are often used as a parent or grouping mechanism for Properties.

Objects can be expressed in basic or expanded form.

# basic
Article:
  Title: String
  Published: Boolean
  ...

# expanded
Article:
  Description: A blog Post
  Properties:
    Title: String
    Published: Boolean
    ...

Properties

A Property, also referred to as "attribute" or "field" in various languages/frameworks, describes particular traits of an Object or Schema. Properties typically contain a Name/Key, a Property Type, and an optional comment (for descriptive purposes).

Here's an example (in basic form) using the Article object:

Article: # a blog post
  Title: String
  Description: String
  Published: Boolean
  DatePublished: Date

Property Types

These are the available property types:

  • String
  • Integer - reserved for integers, no floats/decimals
  • Number - floats/decimals
  • Boolean - True or False only
  • Date - Date only (no time)
  • DateTime - Date and Time
  • Array - a list of values or properties
  • Object - a nested collection of properties

All of these can be used in Basic or Expanded form.

# basic
Title: String               # String
CopiesSold: Integer         # Integer
Price: Number               # Number
Published: Boolean          # Boolean
EventDetail: {Id: Integer}  # Object
AuthorNames: [String]       # Array of strings
Payments: [{Id: Integer}]   # Array of objects

# expanded
Title:  
  PropertyType: String      # String, but applies to Integer, Number, Boolean as well
Author:                     # Object, with properties
  PropertyType: Object
  Properties:
    FirstName: String
    LastName: String
Authors:                    # Array, with properties
  PropertyType: Array
  Properties:
    FirstName: String
    LastName: String

Constraints

Constraints can be added to Properties in any context (Objects, Schemas, Actions, etc.). Types of constraints include the following:

# All property types
Required: True|False

# String property type
StringMinLength: Integer # e.g. 5
StringMaxLength: Integer # e.g. 30
StringPattern: /regex/ # e.g. email validation

# Integer property type
IntegerMinimum: Integer # e.g. 0
IntegerMaximum: Integer # e.g. 999

# Number property type
NumberMinimum: Number # e.g. 15.5
NumberMaximum: Number # e.g. 99.9

# Boolean property type
BooleanEquals: True|False # e.g. for ArticlePublished, must be True

# Date property type (constraints not supported in v1.0)
DateMinimum: String # must match DateFormat or default YYYY-MM-DD
DateMaximum: String # must match DateFormat or default YYYY-MM-DD
DateFormat: String # e.g. YYYY-MM-DD (default)

# DateTime property type (constraints not supported in v1.0)
DateTimeFormat: String # e.g. ISO-8601

In expanded form, here are some examples of constraints:

Article:
  Title:
    PropertyType: String
    Required: True
    MaxLength: 30
  Description: String
  Published: Boolean
  DatePublished:
    PropertyType: Date
    DateFormat: YYYY-MM-DD

⚠️ Use constraints wisely. A DateFormat, for example, may be desirable in a UI or schema context but not in a data storage context. A property may also be Required in one context and not in another. When in doubt, err on the side of including constraints in context-specific Schemas or Actions rather than Objects.

Schemas

Schemas are typically used in APIs and Events, and they are essentially a unique combination of Objects and Properties for a particular use case.

Naming

The schema name is critical for expressing business functionality and must be unique. In general, schemas (and therefore schema names) represent a command or event.

Command

A command describes something to be done in the system. It parallels the imperative in human language. The typical format is [Verb][Noun] in the present tense.

GetArticle: ...
PublishArticle: ...
SendEmail: ...
CompleteOrder: ...

Event

Events describe something that was done in the system. It is like declarative (re: the past) in human language. Events usually follow this pattern: [Noun][Past Tense Verb].

ArticlePublished: ...
EmailSent: ...
OrderCompleted: ...

Attributes

Schemas include the following top-level attributes:

  • Description - A simple description of the schema
  • Version - Semantic version (only [Major].[Minor])
ArticlePublished:
  Description: String
  Version: 1.0

Examples

Here's an example of an ArticlePublished schema:

ArticlePublished:
  Description: An article that has been published
  Version: 1.0
  Properties:
    Title: String
    DatePublished: Date
    Published:
      PropertyType: Boolean
      BooleanEquals: True # "Published" must be true
    TimeStamp: DateTime
    Authors: [Author] # object on DNA spec