|
1 | 1 | # Desirable Properties |
2 | 2 |
|
3 | | -<h2>Values</h2> |
| 3 | +<h2 id=deterministic>Deterministic operations</h2> |
4 | 4 |
|
5 | | -<h3 id=deterministic>Deterministic</h3> |
6 | | - |
7 | | -- A given input always produces the same output |
8 | | -- Easily Cacheable |
| 5 | +- A given input will always produce the same output |
| 6 | +- Easily cacheable |
9 | 7 | - Verifiable by multiple actors |
10 | | -- *e.g. Multiply or adding two integers* |
11 | | -- *e.g. Converting to lowercase or uppercase* |
12 | | -- *e.g. Concatenating strings* |
13 | | -- *e.g. Substring of another strings* |
14 | | -- *e.g. Removing duplicates from a list of items* |
15 | | -- *e.g. SHA256 hash digest (RFC 6234)* |
16 | | -- *e.g. Base64 encoding/decoding (RFC 4648)* |
17 | | -- *e.g. Gzip decoding (RFC 1952)* |
18 | | - |
19 | | -```console |
| 8 | +- Integers |
| 9 | + - *e.g. Multiply two integers* |
| 10 | + - *e.g. Adding two integers* |
| 11 | + - *e.g. Finding the maximum of two integers* |
| 12 | +- Strings |
| 13 | + - *e.g. Converting strings to lowercase or uppercase* |
| 14 | + - *e.g. Concatenating strings* |
| 15 | + - *e.g. Substring of another string* |
| 16 | +- List |
| 17 | + - *e.g. Sorting a list of items* |
| 18 | + - *e.g. Removing duplicates from a list of items* |
| 19 | +- Binary data |
| 20 | + - *e.g. SHA256 hash digest (RFC 6234)* |
| 21 | + - *e.g. Base64 decoding (RFC 4648)* |
| 22 | + - *e.g. Gzip decoding (RFC 1952)* |
| 23 | + |
| 24 | +```bash |
20 | 25 | # Converting to lowercase |
21 | 26 | > echo "AbC" | tr "[:upper:]" "[:lower:]" |
22 | 27 | abc |
|
38 | 43 | abc |
39 | 44 | ``` |
40 | 45 |
|
41 | | -<h3 id=unique>Unique</h3> |
| 46 | +---- |
| 47 | + |
| 48 | +<h2 id=unique>Unique values</h2> |
42 | 49 |
|
43 | | -- Unique within a context or globally unique? |
44 | | -- Won’t clash with existing values |
| 50 | +- Will never clash with existing values. |
| 51 | +- Choice: Unique within a context or globally unique? |
| 52 | +- Warning: just because a value is unique does not mean that it is unpredictable. |
| 53 | +- *e.g. Auto-incrementing SQL primary key* |
| 54 | + - Con: might be predictable as it is _deterministic_. |
45 | 55 | - *e.g. UUID (RFC 4122)* |
46 | 56 | - *e.g. SHA256 hash digest (RFC 6234)* |
47 | | -- Warning: could still be [guessable](#guessable): *e.g. Auto increment SQL primary key* |
48 | 57 |
|
49 | | -```console |
| 58 | +```bash |
50 | 59 | # UUID |
51 | 60 | > uuidgen |
52 | 61 | 5F36D0E2-F524-46B8-870B-9AA70128F8AF |
53 | | -``` |
54 | | - |
55 | | -<h3 id=random>Random</h3> |
56 | 62 |
|
57 | | -- Not [Guessable](#guessable) |
58 | | -- Should never clash with existing values |
59 | | -- *e.g. UUID v4* |
60 | | -- *e.g. Cryptographically Random source* |
61 | | - |
62 | | -```console |
63 | | -> head -c16 /dev/urandom | base64 |
64 | | -4mQ9EA== |
65 | | -``` |
66 | | - |
67 | | -<h3 id=guessable>Undesirable: Guessable</h3> |
68 | | - |
69 | | -- Not Secure |
70 | | -- Not [Random](#random) |
71 | | -- *e.g. Auto incrementing SQL primary key* |
72 | | -- *e.g. The current time* |
73 | | - |
74 | | -```console |
75 | | -> date -u '+%Y-%m-%dT%H:%M:%SZ' |
76 | | -2021-02-07T22:51:21Z |
| 63 | +# Cryptographically random source |
| 64 | +> openssl rand -base64 20 |
| 65 | +lrtijvqi3Dz4YrHZMQpcdfqTkJ4= |
| 66 | + |
| 67 | +# Auto-incrementing SQL primary key |
| 68 | +> sqlite3 |
| 69 | +sqlite> create table items (id integer primary key); |
| 70 | +sqlite> insert into items values (?); |
| 71 | +sqlite> insert into items values (?); |
| 72 | +sqlite> insert into items values (?); |
| 73 | +sqlite> select id from items; |
| 74 | +1 |
| 75 | +2 |
| 76 | +3 |
| 77 | +sqlite> |
77 | 78 | ``` |
78 | 79 |
|
79 | 80 | ---- |
80 | 81 |
|
81 | | -<h2>Acts</h2> |
82 | | - |
83 | | -<h3 id=immutable>Immutable</h3> |
| 82 | +<h2 id=immutable>Immutable values</h2> |
84 | 83 |
|
85 | | -- Changes to data work on a copy, preserving the original |
86 | | -- Benefits caching: *given I have an object’s ID, the contents will always be the same* |
87 | | -- Benefits syncing: *retrieve only the parts I do not yet have* |
88 | | -- *e.g. Twitter tweets cannot be edited, only deleted* |
89 | | -- *e.g. YouTube video media cannot be edited, only deleted* |
90 | | -- *e.g. Git object from a committed file* |
| 84 | +- Can never be modified. |
| 85 | +- Changes to a data structure work on a copy, preserving the original. |
| 86 | +- Can help with caching: *given I have an resource’s ID, the contents will always be the same.* |
| 87 | + - *e.g. Tweets on Twitter cannot be edited, only deleted.* |
| 88 | + - *e.g. Uploaded videos on YouTube cannot be edited, only deleted.* |
| 89 | +- Can help with syncing: *retrieve only the values I do not yet have.* |
| 90 | + - *e.g. Committed files in Git become immutable objects stored in `.git/objects/`.* |
91 | 91 |
|
92 | | -<h3 id=stateless>Stateless</h3> |
93 | | - |
94 | | -- Is [Deterministic](#deterministic) |
95 | | -- *e.g. Restful HTTP GET request* |
| 92 | +---- |
96 | 93 |
|
97 | | -<h3 id=idempotent>Idempotent</h3> |
| 94 | +<h2 id=idempotent>Idempotent operations</h2> |
98 | 95 |
|
99 | 96 | - The same effect is produced if run once, twice, or a thousand times |
| 97 | +- *e.g. Adding an item to a set* |
| 98 | +- *e.g. Removing an item from a set* |
| 99 | +- *e.g. Sorting a list of items repeatedly* |
| 100 | +- *e.g. HTTP `PUT` request* |
100 | 101 | - *e.g. Consumer of an at-least-once event delivery system* |
101 | 102 | - *e.g. [Stripe charges](https://stripe.com/docs/api/idempotent_requests)* |
102 | | -- Hint: Could generate a [random](#random) identifier for each request, which allows recording which commands have already been processed. |
| 103 | +- **Tip:** To get idempotent behavior, you could generate a [random](#random) identifier for each request, and have the receiver record which requests have been processed, and then skip whenever one is repeated. |
| 104 | +- See also: [Distributed Systems Shibboleths](https://jolynch.github.io/posts/distsys_shibboleths/) |
| 105 | +
|
| 106 | +---- |
103 | 107 |
|
104 | | -<h3 id=versioned>Versioned</h3> |
| 108 | +<h2 id=versioned>Versioned operations</h2> |
105 | 109 |
|
106 | | -- Won't break previous usages |
| 110 | +- Will allow a previously valid request to still work. |
| 111 | +- No breaking changes without the user opting into them. |
| 112 | +- This often relies on a **unique** version number. |
| 113 | +- *e.g. [Semantic Versioning](https://semver.org)* |
107 | 114 | - *e.g. [Stripe’s API Versioning](https://stripe.com/blog/api-versioning)* |
0 commit comments