-
Notifications
You must be signed in to change notification settings - Fork 0
Home
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
...
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.
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.
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.
- 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.
There are a few key things to keep in mind when defining DNA:
- Basic & Expanded Form
- Conventions
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
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 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.
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 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
...
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
These are the available property types:
String
-
Integer
- reserved for integers, no floats/decimals -
Number
- floats/decimals -
Boolean
-True
orFalse
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 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. ADateFormat
, for example, may be desirable in a UI or schema context but not in a data storage context. A property may also beRequired
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 are typically used in APIs and Events, and they are essentially a unique combination of Objects and Properties for a particular use case.
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.
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: ...
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: ...
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
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