There's more to the picture, �then meets the eye. �Hey hey, my my.
Neil Young
The idea behind the MarbleDesignSystem
Diagrams have the unique ability to express complex things simply.��Never had reactive programming been made so visual��Diagrams is transforming information into compelling images���Marble diagrams serve a method for us to visualize processes over time.
This helps programmers and engineers to understand and design reactive processes.��The overall goal of the MarbleDesignSystem is to provide a unified way of reading and creating stream based diagrams,
in particular one specific type of it, the marble diagrams.
This guide explains all building blocks of the design system step by step and in detail.
In general we have some main rules that system follows:
Consistency
Intuitive
There are several things to follow if you try to create a standard. One of them is more critical for a positive outcome than everything else, consistency.
By working with a standardized, reproducible approach we managed to create a consistent way of drawing marble diagrams. �A set of rules developed over many many iterations, adopted and simplified to serve as a guideline and blueprint for creating and using these diagrams.
As programming with Rx is hard we made sure to keep it intuitive. �By including a lot of people into the process of the creation of this guide we collected a lot of personal feedback to improve the system.�To make sure we consider a common way interpretation we created several public polls we were collected and evaluated the general understanding. �This helped us to make our system intuitive to understand.
Easy
Detailed
As mindset behind the system are several principles. One of them is “Easy to adopt and create”, which means we want to provide a way for everybody to read and create marble diagrams.
To achieve this we create all diagrams in either googleSlides oder Powerpoint. We believe this two options enable a big group of people to edit and draw these diagrams.
Marble diagrams exist since a long time now. As there was no well thought standard out there and not all edge cases considered, people started to create their own solutions to visualize processes. These let to a variety of different ways of drawing these diagrams. Some of the better approaches were able to visualize more complex prozesses, but there is one essential thing which nobody considered yet, but which is most critical to understand processes based on Rx. The internal behavior of operators.
This system is not only providing a consistent, standardized way of drawing marble diagrams, but also offers a way to visualize the internals of operators. Of course based on the systems rules it selfe.
Technically Correct
All diagrams should be able to mirror the source code as accurate as possible, therefore the
Index
DESIGN TOKENS
UNIT
BLOCK
Base Unit:Block
The unit for width and height in marble diagrams is called a block. �A block is a rectangle with equal width and height.��Positioning of objects and text is also measured in blocks.
To have a convenient unit we use em with the base of 1 blok.
Sometimes time matters. The smallest unit of time is called frame.
A frame is a unit for time and expressed in width. 1 frame equals to the width of 2 blocks.
15
10
5
20
1
5
1
10
BLOCK
BLOCK
FRAME
BLOCK
FRAME
1 Block = 1em
1 Frame = 2 Blocks
Block Grid
FONT
Text is used to name things or give more information to a specific part of a diagram like observables, operators and events like subscribe or unsubscribe. �It is furthermore used in notifications to give more detailed information about their content.
FONT-FACE
ABCDEFGHIJ
stuvwxyz01
ABCDEFGHIJ
stuvwxyz01
ABCDEFGHIJ
stuvwxyz01
ABCDEFGHIJ
stuvwxyz01
The design guide doesn’t limit the choice of font.��Only a few limitations are suggested.
�Serif font-face and mono-space letter.
Serif Font-Face
Serif font-face has compared to the serif font-faces less visual noise.
�Mono-space
Mono-space font has to be used in the description of observables, operators or in the text of notifications.
This ensures that the with of text is directly proportional to the number of characters and therefore simplifies the positioning and alignment of text in diagrams.
Monospace�Font-Face
Proportional�Font-Face
Sans-Serif Font-Face
Serif �Font-Face
FONT-SIZE
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890()[]{}
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890!Ҥ$%&/()=?
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890!Ҥ$%&/()=?
1em (Big)
0.67em (Medium)
0.5em (Small)
The font-size is measured in em, a scalable unit for text. In this design system 1em is equal to 1 block, the unit for width and height.
�There are 3 different sizes defined to describe marble diagrams. We will elaborate more on this later.
FONT-STYLE
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890()[]{}
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890!Ҥ$%&/()=?
Normal
Bold
The font-styles are limited to�2 different styles, normal and bold.�We will elaborate more on this later.
COLOR
All colors are are barrier free and used for specific things in the diagram.��There are 3 fixed colors and 4 to n colors that are free to choose.
For Text, lines, and arrows the “line” color is used.
The “background” color is not only used for the background but also for text to get an acceptable color ratio.
For “notification” colors you can use the defined colors 1 - 4 or any other color of your choice. All notification colors have the same meaning. There is no “danger” or “success” color.
You can check your pallet here.
The “inactive” color is used for anything that should be recognized as inactive.
Name: notification 1
Usage: �notification color 1
Name: notification 4�Usage: �notification color 4
Name: Line
Usage: �Line, border and text color
Line
Background
Notification 1
Notification 4
Notification 3
Notification 2
Name: Notification 3
Usage: �notification color 3
Name: Notification 2
Usage: �notification color 2
Name: Background�Usage: �Background of operators or text
Inactive
Name: Inactive�Usage: �Inactive lines, shapes and text
COLOR
#FFCB21
#6734BA
Notification 1
Notification 4
Notification 3
Notification 2
#F77C00
#89C540
Colors serve the purpose to distinguish between notifications or observables.��Try to use as less colors as possible to keep the visual noise of a marble diagram low. ��If you create your own color patterns keep in mind that you can use text inside shapes.��Also always check your palette including text with a color contrast tool like accessible-color-matrix
Example Palettes:�Palette 1
Links:
#D01C8B
#4DAC26
Notification 1
Notification 4
Notification 3
Notification 2
#B8E186
#F1B6DA
#36175E
#9768D1
Notification 1
Notification 4
Notification 3
Notification 2
#7B52AB
#553285
LINE
Lines are here to symbolize time.�Time without a measurement as line or area as shown with [1] and [5], a specific time period is shown under [4] or an interaction at a specific point in time ilke in [2] and [3].
The interaction can be initialized from the consumer [2] to the producer [3,6].
Lines from the consumer side [2] have in some cases description in form of the letters S, U and C.
Some lines from the producer side [6] can be angled. This is possible to the right side only. [7] [8]
Style: Dashed
Weight: 0.06em
Start: none
End: none
5
2ms
6
Style: Solid
Weight: 0.06em
Start: none
End: none
opr
Style: Solid
Weight: 0.06em
Start: none
End: Filled Arrow
1
Style: Dashed
Weight: 0.06em
Start: Filled Arrow
End: none
2
Style: Dashed
Weight: 0.06em
Start: none
End: Filled Arrow
3
Style: Dashed
Weight: 0.06em
Start: none
End: Filled Arrow
4
Style: Solid
Weight: 0.06em
Start: none
End: none
7
Style: Dashed
Weight: 0.06em
Start: none
End: Filled Arrow
8
Update to latest version of components
S
U
opr
1
3
2
2
6
42ms
5
2
4
7
1
SHAPE
Shapes, same as colors help to distinguish between notifications. �You can use the suggested set or create your own set of shapes.
Try to use as less different shapes as possible to keep the visual noise of a marble diagram low. ��If you create your own shapes keep in mind that evers shape should be same height and width to keep the sizing and spacing as easy as possible.��Also consider that every shape should be able to have dynamic with. (dynamic in number of blocks)
��
Rectangle
Circle
Diamond
Cross
1
2
3
4
1
3
2
4
SIZE
Time
1
Notifications
2
Error
4
Completion
3
There are 2 different sizes, normal (2em) and small (1em).��Small size is only possible for this subset:�[1] Time
[2] Notification
[3] Completion
[4] Error
��Small size is rarely used but can serve in some cases as a useful detail information.�For example to sketch higher order observables or operators.
Usage only outside of operators sope?
COMPONENTS
COMPONENTS
Components are the smallest entities in marble diagrams.�The different design tokens are applied on components. Diagrams are a composition of components.
11
Task Stacks
fn
T
A
I
S
1
Timeline
2
Observable
3
42ms
Time Span
4
Event In Time
5
Notification
6
Error
7
Completion
8
Operation
9
Operator Internals
10
Operator Scope
12
Consumer Event
OBSERVABLE
Time
1
Time in marble diagrams is represented as an arrow going from left to right.
The arrow at the same time is also a representation of an observable it selfe.
Time is measured in frames, a superset of blocks.�1 frame is 2 blocks
��
7
8
2
3
6
4
9
4
2
3
1
10
5
1
5
Frame:
Block:
TIME SPAN
2
Object:
Shape: Rectangle
1F
Time Span is here to specify a certain duration of time.��The smallest possible size is 1 turn in the event loop��The description of the time span is placed inside the box and consists out of an amount directly followed by a unit.�No space inbetween.�
The amount is a number.�The unit, as singular, can be any known unit of time as well as the unit frame, which is equal to one block.
�For time units you can use shortcuts as ms for milliseconds or s for seconds as well as full name i.e. month or year.��Of course you can also use any other imaginary unit of time like a moment ;-)
����
��
42frame
42ms
42month
42moment
...
EVENT IN TIME
INFOS HERE!
����
��
3
Object:
Shape: Circle
t2
fn
t2
OPERATION
Operation is an event triggered from the consumer of an observable.
Operation symbolizes the interaction with the notifications and operators.
�The operator start from notifications ��Examples for inactive operations (stop at operator stop at output)�
9
Operation
CONSUMER EVENT
Consumer events are directed bottom up. It starts from the result observable and ends at the operator context, or the observable it selfe.� �Use [S] If you subscribe�
And [U] If you unsubscribe��The position of the box is 0.15em above the observable. ��If the box has to be placed next to it on the left side and 0.15em inside the start of the observable.��Other components in the same frame are queued in the next free block to the right.��
3
Consumer Events
S
S
S
S
S
U
NOTIFICATIONS
Notifications are the possible content of observables.
They ocurre over time and are a representation of any particular thing. ��
Notifications can have:�- Color
- Shape
- Content (proper contrast to fill color)
- With (in full blocks)
Color and content combination should always have a proper contrast. Find a onlinetool here: Contrast checker�The value color can be only black or white.
With is here to provide enough space for more content than just 1 chars. Every shape can have a dynamic width.
�
��
4
Notification
Color
Width
Shape
Content
Contrast
R
4
$
x
2
&
COMPLETION
Completion symbolizes one possible end of an observable.
��
5
Completion
ERROR
Error symbolizes one possible end of an observable.
��
6
Error
OPERATOR
The operator symbolizes the logic which interacts with observables and their notifications. ��Operators can contain any other component in small as well as normal. Also text.
In case the content contains components they can have a description on their left side.
7
Operator
opr
opr(v => !v)
opr( [] => )
opr
a
Remove text in operator. All description is on the left side.
Cosider get rid of the mini icons inside the opr.
TASK STACKS
Task Stacks
��
8
Task Stacks
opr
DIAGRAMS
SECTIONS
A diagram consists at least of the diagram section.��Description, legend as well as flow description are optional.
FLOW DESCRIPTION
DIAGRAM
LEGEND
DESCRIPTION
12 - n �blocks�height
? blocks�width
DESCRIPTION
The description section is the first section possible in a diagram. It can have variable height.
This section is optional as most of the time we want to have our textual description as text, not as image but it’s completely fine to include the description in the diagram.
FLOW�DESCRIPTION
DIAGRAM
LEGEND
DESCRIPTION
0 - n �blocks�height
LEGEND
The legend section is the second possible section in a diagram. It can have variable height.��This section is optional too, but compared the the description section it is always part of the diagrams as we want to have the legend as part of the diagram it selfe.
Use small font size for the legend. For font weight use normal for description and bold for indexes, operator params, or content references.
The legend can give information about:�- Time per frame�- Name and color�- Data type and shape�- Content�- Indexe�- Operator params:��
FLOW�DESCRIPTION
DIAGRAM
LEGEND
DESCRIPTION
0 - n �blocks�height
LEGEND
Description can be anything text as well as any multimedia is allowed. �This is the only section without any restrictions. �Therefor it allows a variety of opportunities to describe the content of the following diagram.
LEGEND
Time per frame:�If important you can specify the time per frame.
Name and color:�Information related variable name of input or output observables. �Also color is included and used to distinguish observables.��Data type and shape:�If needed you can also distinguish data types from each other. �This is done by shapes.
Content:�The content can be used to directly place the notification inside i.e. “1” or “a”.�If you want to be more specific use the content as reference to describe complex objects. I.e. “x: {name: ‘Eric’}“ ��Indexe:�Index chars can be letters used to reference consumer events or numbers for everything else.��Operator params:�Details for operator params like functions or notifications.
ADD OBSERVABLES TOO HERE�
�
(name and or color)
o1$: button clicks
o1$:
o1$:
x
o1$:
map(fn1)
(shape or data type)
circle: Array<string>
(content)
x: [‘a’, ‘b’, ‘c’]
(operator params)
fn1: (n) => !n
o1$:
1
(index)
[1]: notification F12
F1
2
3
4
5
(time per frame)
1F = 250ms
F
o1$:
(observable)
o$:
FLOW DESCRIPTION
TODO
FLOW�DESCRIPTION
DIAGRAM
LEGEND
DESCRIPTION
equal to diagram�height
0 or 10�blocks
width
of(true)
delay(500)
combineLatest(input$, (h, _) => h)
input$
output$
delayAtLeast(500)
500ms
1100ms
1100ms
FLOW DESCRIPTION
click$
Bold+Big (Observable)
scan(a => ++a,0)
scan(fn,s)
Normal+Big (Operator)
1
Bold+Small(Index + Legend)
42ms
[a]
[1,2,3]
Normal+Medium (Notification, Timespan)
[a]
[1,2,3]
42ms
DIAGRAM CANVAS
Diagram:�- Grid� - Padding� - Frame scale� - Block scale� - Min-With�- Positioning� - Lanes� - Horizontal� - Vertical�- Notifications� - Content� - Shape� - Color� - Multiple notifications� - Dynamic with� - Inner components� - Inner state => scan, buffer� - Multiple Operations�- Operator� - Padding� - Operations and lines� - Operator grouping�- Multiple components �- Inactive components�- Order of involved observables
FLOW�DESCRIPTION
DIAGRAM
LEGEND
DESCRIPTION
12-n
blocks height
38
blocks
width
GRID
The diagram is drawn in a grid which is made out of blocks. It’s optional to display.��The grid has a padding of 1 block.��Also optional are the blocks and frames scales.
The block scale is mainly here to position components. It is very rarely used.��The frame scale is here to measure the exact time in diagrams.
For a consistent appearance we suggest a minimal with of 38 blocks.
Fix min width!
15
10
5
25
30
20
B1
F1
2
3
4
5
6
8
9
10
11
12
13
7
14
15
16
38 blocks width
POSITIONING
For every component you have to provide a space of 2 by 2 blocks. �This is important in combination with the frame scale. ��The components are arranged in lanes.��The minimum vertical space is 1 block.��Lines are placed either horizontally or vertically on the edges of a block.��Horizontal lines can only be placed in the center of a frame.
�Between lanes there has to be a horizontal space of 1 block.
Mention vertical separation of observables if needed �KUDOS @ncjamieson��Include @CedricSoulas solution for complete and start in the same frame
opr
F1
2
3
4
5
6
8
9
10
11
12
7
opr
3F
5 frame
NOTIFICATION AND CONTENT
In marble diagrams the emissions of observables are called notifications.
They are displayed as shapes with color.
To give more information about the data of a notification you can use content. ��Content is any set of characters placed centered in the shapes area.
Content can also be represented as symbol of any kind.
In special szenarios the content can also be a producer event
0
1
2
3
z
o
r
r
NOTIFICATION AND CONTENT
Content can be directly representing the notification or serving as a reference for the legend with details.�
�You can use the prime symbol [`] to show relations in derived notifications. A => A` => A``
Include examples for types, and all the new stuff!
a
b
c
d
a`
b`
c`
d`
a: ['a', 'b', 'c', 'd', 'e']
b: ['e', 'f', 'g', 'h', 'i']
c: ['i', 'k']
a`: 'abcde'
b`: 'efghi'
c`: 'ik'
NOTIFICATION AND SHAPE
0
‘1’
2
‘3’
0
1
2
3
Notifications have shape. Shape is closely connected to content and serves an abstraction for the data type. �I.e. number or complex objects��In some cases it helps the readability of a diagram.
�Especially when you have data type transformations or observables that emit different data types.
42
43
44
45
‘*’
‘+’
‘,’
‘-’
map(v => parseInt(v))
map(v => v+42)
map(v => String.fromCharCode(v))
NOTIFICATION AND COLOR
Color in diagrams is used to distinguish notifications from different observables.��Colors are applied to input observables.�
The output observable can be drawn in 2 versions.��a) It has a different color.�b) It has no own color, but is a result of all colors from the input.
The output observable has no own color, but is a result of all colors from the input.��In more complex diagrams you have to decide when to switch back to a single color or not.
MULTIPLE NOTIFICATIONS IN ONE FRAME
15
5
20
1
2
3
4
5
1
FRAME
BLOCK
5
In several diagrams there is the situation where we have to display multiple components like notifications and or error or complete. ��In the following we describe the actual set of all explored options ��Duration:�
TIME
NOTIFICATION AND DYNAMIC WIDTH
NOTIFICATION AND INNER COMPONENTS
If you want to display higher order observables you can use small components size for it. ��Small size is rarely used and
only serve as a symbol.��As normal as well as small components take a 2 by 2 blocks space all positioning and spacing rules apply also for small components.���It does not reflect the real behaviour of the inner observable.��The real behavior is displayed in the operator which takes these notifications.
Inner State
OPERATOR Padding
200ms
Name
barFo
barFo(v => v * 2)
Name and param( psudo )
Name and param( marble )
barFo( => )
Internals
1
2
2000ms
2000ms
OPERATOR AND LINE
1
2
4
2
map(v => v * 2)
a
b
b
c
a
b
b
c
Operators perform operations which happen at a certain point in time and are displayed as vertical dashed lines with and arrow at the lower end.
Form simple operations the lines are behind the operator box. This helps to have no overlappings with the operator content.��For operators where the internal visible the lines are on top of the operator and end in another component.
��Add curved lines example (scan)��Show diagonal line
Multiple Operations in one frame
OPERATOR NESTING
of(true)
delay(500)
combineLatest(input$, (h, _) => h)
input$
output$
delayAtLeast(500)
500ms
1100ms
1100ms
Find better solution��Can we avoid the gray nested box?���SHOW Vertical Separation!!!!!!!�Ref window operator
INACTIVE COMPONENTS
1
0
0
1
a
a
�Sometimes it serves helpful information to show notifications and operations as well as
complete and error, in inactive color if they don’t occur.
Inactive operations can also end on the operator context. This could be on the in and outside.
Include rules for i.e. filter operator. Where does the black line stop where does the gray line start���CONSIDER REMOVE FROM STANDARD
b
a
c
A
B
A
B
1
1
filter(v => !!v)
NUMBER OF EXAMPLES PER OPERATOR
In general:�Less complexity and more different diagrams/examples �with more notification distance
EXAMPLES PER OPERATOR
Lowercase character
BEYOND THE STANDARD
ALTERNATIVE SHAPE
3
1
Also possible to use Images, emoticons and so on���
Cloud
Bottle
emoji
Rounded Rect.
1
2
3
4
4
2
ALTERNATIVE UNITS
2
1F
Time Span is here to specify a certain duration of time.��Of course you can also use any other imaginary unit of time like a moment ;-)
����
��
42moment
TODOS
?
Overlapping shapes���
���
��
42moment
?
?
Vertical Layout
a
A
input$
output$
A
w$:
b
A
A
B
B
B
B
w1$
w2$
switchMap(fn)
fn:
(n) => ws$
Contributors
END HERE
Open Issues
Operations and their end
fnName(a) {
}
fnName()
fnName(a) {
}
fnName()
fnName(a) { return a; }
fnName(a) { }
output$:
race([slow$,fast$])
slow$:
fast$:
output$:
race([slow$,fast$])
slow$:
fast$:
Closed Issues
EXAMPLES