Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

Rhizz is a systems modeling language, built for architects who want to go beyond design documents and diagrams sketched on whiteboards (or their digital equivalents). Rhizz allows you to create a model of your system, either via an interactive model editor (think Drawio/Excalidraw but with with validation across multiple diagrams) or by implementing your systems models as code. Those approaches are interchangeable. Your LLM of choice will likely appreciate a text-based interface, while you will probably prefer a graphical representation.

Diagramming in Rhizz goes beyond drawing shapes on a canvas. Each thing you draw is added to your system model, made out of:

  • Systems (possible realisations of your product)
  • Components (nodes, boxes)
  • Connections (arrows/lines between components)
  • Interfaces (specification of interaction)

Once defined, Rhizz will not allow you to draw the same component with a different set of connections, a different parent, or a different interface. You can show & hide parts of the model for brevity, showing the model of your system from diferent perspectives, but the Rhizz compiler will always verify that all your diagrams are consistent.

Gradual Compilation

Rhizz is built on top of the idea that your system is constantly changing, rarely (if ever) finished. Therefore, the compiler was built with gradual specification of your system in mind. You don’t have to create a full model of your system upfront. You can leave missing pieces for later, you can stay on a high level of abstraction. The Rhizz compiler can be tuned into various level of strictness, accepting super high-level non-technical specifications or requiring full breakdowns of all components and their connections.

TODO: link to strictness settings page.

Target Audience

Engineers

The core audience for Rhizz are engineers in general. All the people who want to understand the things their working on. Rhizz attempts to deepen their understanding by letting engineers explore a system model, which also serves as a knowledge base.

Product Owners

High-level assumptions about the project can be defined in Rhizz, even by non-technical PO’s. What’s important is that there’s no knowledge/system gap between high-level Product Owners and lower-level engineers. The product spec and the model of how its implemented both live in the same place, allowing for effective collaboration and deeper understanding between team members with different backgrounds.

Architects

Warning: ramblings of the author ahead! After I stopped working as a software engineer and became an architect (though I’ve also been a team lead and a product owner), I felt like the way that we communicate in large engineering projects is not very effective.

Every time I meet with other teams, I explain the same interfaces all over again. Everyone has some level of understanding, but it’s usually only their side of the equation. You could blame bad documentation (or lack of it), but I don’t believe that’s the case. It’s mostly about availability of the right documentation when you need it. While the things which everyone should know are usually written down somewhere, it’s hard to quickly find and read through what’s relevant to the issue at hand.

I believe that the single system model which can be projected into a diagram, a view of a specific part of the system, is what we need to quickly find our way through complex multidisciplinary projects.

Programmers

Rhizz aims to bring static analysis capabilities to your system design. If you’re a software person, think about it as a linter or a compiler for a system design. You can have your diagrams checked for correctness, as you check your code!

Philosophy

The name “Rhizz” is a portmanteau of:

  • Rizz, a slang term for charisma/style/charm
  • Philosophical term rhizome:

Rhizome is a concept (…) describing an assemblage that allows connections between any of its constituent elements, regardless of any predefined ordering, structure, or entry point.

Rhizz’s philosophy opposes the typical top-down architect-to-engineer structure, where architects define “the high level view” and engineers are supposed to make their designs work in the limitations of the real world. Such approach causes architects to become more and more detached from the reality of the system, unaware of the growing gap between the model and the real world. See: Ivory Tower Architect. Rhizz aims to let engineers of different specializations and different positions in the organization contribute to the system model. The gradual compiler provides an easy learning curve. Each small piece of information added to the model improves the coherence validation capabilites of the compiler. Information no longer flows in one direction. Instead, constraints and details emerge from multiple sides.

Non-goals

Features which are not not planned for implementation. If you need them, you need a different tool.

Simulations

Rhizz does not simulate the behavior of your system. It cannot stress-test your model. If you need something for simulations, consider TLA+.

Fancy animations of your system model

Rhizz’s primary output format is a 2D diagram. While I’m dedicated to make them look as good as possible, I won’t create a tool for fancy visualisations.

Basics of Rhizz syntax

The smallest possible thing you could write in Rhizz looks like this:

While this does not really model any useful system, we can use it to describe the basics of the tool we’ll be working with.

HCL syntax

Rhizz uses HCL - HashiCorp configuration language to define system models. HCL is easy to write by hand, is much less verbose than JSON and is more predictable than YAML. It’s already used to define cloud-based systems, so it was a natural fit.

Rhizz Compiler Output

Output of the compiler will be frequently mentioned in this book. All code blocks in this book containing Rhizz code are run through the Rhizz compiler, which emits the compilation results - completion metrics for the system model. You can see them in the green box in the example above. This way of displaying the results of examples will be used across this whole book.

Systems

A system is one possible realisation of whatever it is you’re building. Think about a following example: you’re building a plane. But you can’t build just a plane, such system is always surrounded by the instrastructure related to its manufacturing and utilization:

  1. Your plane probably needs an end-to-end testing harness.
  2. Components of your plane need their own dedicated harnesses.
    • e.g. a dedicated harness for the engine.
  3. You could picture the same plane in various usage contexts.
  4. You want to re-use components and have Rhizz validate all defined configurations.

That’s precisely what systems are for! You can define separate systems for different use-cases:

  • system plane-in-hangar
  • system plane-in-air
  • system engine-testing-harness
  • system hydraulics-testing-harness

Those systems will re-use various parts of your overall model. When you have to change your design, Rhizz will give you hollistic feedback, not only about the final use-case (plane-in-air), but also how the design change will affect the rest of your product’s infrastructure.

TODO: is system really a good name for it? Ask fellow SE people.

Components

The keyword component defines a new reusable component. It’s not the same thing as placing the component somewhere in your system model! This is a reusable definition. Each definition has a unique name, you will soon learn how to “place” (instantiate) your component definitions in your systems.

You can already see that the Rhizz compiler started warning you about some issues with that definition. More on those issues in the Components in Detail page!

TODO: add component details page

Instances

You now know about systems and about components, lets put this together and place a component in a system:

We instantiated the wheel 2 times to create a bicycle! For the sake of brevity, I marked wheel with leaf = true, so that the compiler won’t complain about the battery not being fully defined. We’ll come back to this later, you can ignore this fact for now.

Nesting

A component can have children (and those children can have their own children). Let’s add a tire to our wheel:

Important

A crucial concept to understand in this example is that adding the tire as the child component of wheel causes this change to be propagated along all instances of wheel. front-wheel and rear-wheel both have a tire child component now, as we’ve changed the definition of what wheel means.

Connections

The warnings “component ‘NAME’ is not referenced by any connection” appear multiple times, let’s fix some of them by building a bike with:

  • A bicycle frame
  • A bicycle fork
  • Wheels attached

TODO: why W003 still appears for standalone components…?

We now have a simple (and incomplete) bicycle model. This model is small enough to be visualised with just a single diagram, so Rhizz’s diagramming capabilities won’t shine for such a trivial example.

In the upcoming chapters, you’ll see how Rhizz can model complex, nested and multi-dimentional systems, which cannot be grasped without looking at them from multiple different angles.

Full projects

All examples in this book are actual Rhizz projects. So far we’ve been only working with single-file examples, here you can see a project with a system model and a view.

Introduction to Views

Views allow you to visualise your system model from different perspectives. Think about the following:

  • High-level overview of the system
  • Detailed view of a specific component
  • View focusing on interaction between two important components

All of those are valid ideas for a view into your system. Take a look at a simple model of a computer setup. This model has 2 views:

  • system.hcl - Overview of the system
  • pc-build.hcl - Internals of the computer

Both of those views utilize the same model underneath. Components are imported to the view using their full path, which uniquely identifies the specific instance of a component inside a specific system.

View correctness

All views are checked for correctness. The example below demonstrates what happens when you use a non-existing component in a system view. As you can see, the view fails to render and the warning explains why:

Visibility of connections

Note

This behavior might change in the future, Rhizz is at MVP stage!

Rhizz decides what connections are visible in the view based on the components that are visible in the view. If selected components have connections, they will be displayed. This behavior ensures that you don’t accidentally miss any connections.

View syntax

Important

This section explains the view syntax, but remember that you’re not expected to write views by hand. Rhizz Web App allows you to create views in the diagram editor.

Connections & Ports

This chapter focuses on how to model connections between the components of your system. You’ve already seen the basic component-to-component connection schema:

This is fine, but high-level. We just know that two components talk to each other and that’s it. What if we wanted to dig deeper, how about:

  • What kind of protocol is used to talk between those components?
  • Is client even supporting that protocol?
  • Does server has any port for the client to connect to?

Note

Programmers reading this probably think about ports in terms of networking. In the case of this book, think about a more broad/generic definition of “something to connect to”.

While this model compiles without any errors, the model completion score points us towards things to specify further:

  • There are 0 ports defined
  • There are 0 messages defined

TODO: what the hell is “Connections 0/1”? Some bug prolly…

Defining & connecting ports

TODO: 0/4 ports, marked as unused or what? Why isn’t completion score up? Same issue with connections as before.

The work-computer system defines 2 usb-c ports on the component level. Now we have more details about what exactly we’re connecting to. The component states what port it exposes and the compiler will raise an error if you try to connecting to a non-existing port. Consider having an inventory of components from some iteration of your product, while designing a new version of that product. Having ports specified inside components allows you to quickly see what parts can be easily re-used and which ones will require changes at interface level, or even need a complete rework.

Warnings & Errors

The Rhizz compiler produces 2 types of diagnostic messages:

  • Warnings, which inform you about a non-critical issue
  • Errors, which prevent the compiler from building the system model

Warnings do not stop the build. Example below reuses a top-level component via source = "sensor-hat", but its protocol defines no messages yet and two entities are missing full names. The model still compiles and scores — the warnings point at exactly what to finish.

The completion score is still produced: source reuse works, connections resolve, diagrams are drawn (just not in this example), the compiler just outlines what is incomplete.

Warning Levels

The Rhizz compiler can run at different strictness levels, each of them filtering out different warnings. Currently, 3 levels are defined:

Business spec

Business spec is super high-level, allowing almost anyone to get a warning-free build. This strictness level can be compared to a typical diagramming application experience, like DrawIO or Excalidraw. It’s great for first sketches, preliminary designs, talking to business people.

Architectural spec

Architectural requires more details, full names and documentation, focusing on interfaces between large segments of the system.

Component-level spec

The most strict mode is the component-level spec - it requires modeling all the way down to leaf-level components, with all possible warnings enabled.

Per-example strictness in this book

Every live example below carries a Strictness badge showing the level it was compiled at — the same verdict the compiler produced when this page was built. Tutorial snippets often run at architectural so you are not nagged about leaf-level detail (like missing docs/ files) before the concepts are introduced; warning demos run at component so nothing is hidden.

Authors pick the level per fence: append ,level=architectural to a rhizz code fence, or level="architectural" to a full-project embed directive. An unknown level fails the book build loudly, so a typo can never silently change a verdict.

Documentation System

Reusing Components

Protocols, Ports & Messages

Completion Scoring

CLI Reference