Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update CONTRIBUTING.md #1297

Merged
merged 6 commits into from
Apr 3, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ This section illustrates how our design principles translate into actual code. W

#### Design by logical entity instead of product/feature

> “The most fundamental problem in computer science is problem decomposition: how to take a complex problem and divide it up into pieces that can be solved independently.”
>
> — John Ousterhout in "A Philosophy of Software Design"
This is probably our oldest and most important design principle. When designing a module or a FAST stage we look at its domain from a functional point of view: **what is the subset of resources (or modules for FAST) that fully describes one entity and allows encapsulating its full configuration?**

It's a radically different approach from designing by product or feature, where boundaries are drawn around a single GCP functionality.
Expand Down Expand Up @@ -200,6 +204,12 @@ We have several such interfaces defined for IAM, log sinks, organizational polic

#### Design interfaces to support actual usage

> “When developing a module, look for opportunities to take a little bit of extra suffering upon yourself in order to reduce the suffering of your users.”
>
> “Providing choice is good, but interfaces should be designed to make the common case as simple as possible”
>
> — John Ousterhout in "A Philosophy of Software Design"
Variables should not simply map to the underlying resource attributes, but their **interfaces should be designed to match common use cases** to reduce friction and offer the highest possible degree of legibility.

This translates into different practical approaches:
Expand Down Expand Up @@ -286,6 +296,11 @@ module "project" {

#### Design compact variable spaces

> "The best modules are those whose interfaces are much simpler than their implementations"
>
> — John Ousterhout in "A Philosophy of Software Design"

Designing variable spaces is one of the most complex aspects to get right, as they are the main entry point through which users consume modules, examples and FAST stages. We always strive to **design small variable spaces by leveraging objects and implementing defaults** so that users can quickly produce highly readable code.

One of many examples of this approach comes from disk support in the `compute-vm` module, where preset defaults allow quick VM management with very few lines of code, and optional variables allow progressively expanding the code when more control is needed.
Expand Down Expand Up @@ -413,6 +428,10 @@ Each FAST stage should be designed so that it can optionally be used in isolatio

#### Stage interfaces

> “The best modules are those that provide powerful functionality yet have simple interfaces.”
>
> — John Ousterhout in "A Philosophy of Software Design"
Stages are designed based on the concept of ["contracts" or interfaces](./fast/README.md#contracts-and-stages), which define what information is produced by one stage via outputs, which is then consumed by subsequent stages via variables.

Interfaces are compact in size (few variables) but broad in scope (variables typically leverage maps), so that consumers can declare in variable types only the bits of information they are interested in.
Expand Down