This document describes the convention used to describe data in feature design documents.
Data as structs
The core convention is describing data in terms of structs and slices, in the syntax of the Go programming language.
This will be in contrast to the more common convention of describing data in terms of relational tables.
This choice is deliberate. You can of course use relational tables to store the data. You can also use "json" documents to store the data.
The basic data types are going to be: int, float, string, boolean.
In addition, I will often refer to 'date' and 'timestamp' as if they were built-in types.
A 'date' is usually a string in the format 'yyyy-mm-dd'. The idea is that it has no time component, and no timezone. It's a little bit abstract in that sense.
A timestamp is probably stored as a 64bit millisecond with respect to some epoch (usually the unix epoch), along with a timezone (either as an identifier, or as a difference from utc). The details might vary from system to system, but the core assumption will be that it can be converted to some specific local time for the purpose of input/output on the user's machine.
Example:
type StoreItem struct {
Id int
Slug string // url slug; one per store item
Title string
Subtitle string
Description string
BrandId int // reference to some brand
Images []string // urls relative to the user images endpoint
UnitPrice int
UnitCurrency string
}
type Brand struct {
Id int
Name string
Logo string // image url
Header string // image url
Homepage string // company url
CatchPhrase string
Description string
}
Storage Bucket
Defining a type does not mean that it will be stored as-is in the database. Things are only stored when they are put in a bucket. A bucket uses a lookup key to retrieve a type of object
Examples:
bucket StoreItems(Id int, StoreItem)
bucket Brands(Id int, Brand)
bucket StoreItemSlugs(Slug string, Id int)
In a relational database, you may choose to implement a bucket in terms of a table, and the lookup key may be understood as the primary key for the table.
Lookup Index
A lookup index is also a mapping, but instead of being one to one, it's basically many to many, mapping a lookup term to a list of targets.
Examples:
index BrandItems(BrandId int, StoreItemId int)
index CurrencyItems(Currency string, StoreItemId int)
The BrandItems index allows us to iterate over all the store items that are from a certain brand.
The CurrencyItems index allows us to iterate over all the store items that define their price in a certain currency.
In a relational database, the index may be assumed to be some kind of optimization, since SQL allows you to use arbitrary queries with arbitrary lookup conditions.
However, when modelling data, it's important to be explicit about these lookup indices.
When using the lookup index, you provide a key and iterate on matches.
When setting the lookup index, you provide a match and a list of keys. It's the opposite.
Think of the index on the back of a book. If you edit a page and want to update the index, the operation requires that you provide the page number and a list of important terms that appear on the page. The system will then find each term on the index, and update it by adding the given page number. It will also need to find keys on the index that used to point to the given page number but no longer need to, and remove the page number from their matches.