Skip to main content

Stupid and robust

Roughly five years ago, I was pouring over the writings of designer and artist Adam Morse when I discovered a link that changed the way I viewed computer hardware and software design forever.

The UNIX Philosophy quickly and clearly outlines a basic set of best practices when building software and managing the hardware it runs on. While some of these principles are more UNIX focused, they can be broadly applied to any system.

That page covers a lot in a little space and all of the principles are worth discussion, but the principle that I'm thinking of now is:

Rule of Representation: Fold knowledge into data, so program logic can be stupid and robust

Broadly, I was aware of the concepts and have used aspects of them throughout my work. I've done a lot of work with databases, content management, and designing data-driven systems. Data was always there, but never at the forefront of my mind when thinking about building a website or application. I had sort of taken data for granted, but never thought much about the bigger role it can play when programming.

Is it really possible to represent every aspect of an application in a data structure and then write code that generates the entire application?

Better questions:

  • What happens when every concept of your application is available to your team as data?
  • What would it be like to "see" inside every level of your application?
  • How does data-driving the development of your application change the way you code, test, deploy and reason about it?
  • Can we lessen or completely eliminate the need for traditional frameworks and libraries with this approach?
  • What new types of tools can arise with this level of data at hand?
  • Just how stupid can our code really get?

Compilers

Compilers have been taking source code and constructing computer programs since Grace Hopper created the first one in 1952.

In the JavaScript world, Webpack, Rollup, and Parcel are compilers.

Entire ecosystems are built by them: Svelte, React, Vue, and Angular to name a few.

Build tools take source code, turn it into an abstract syntax tree (AST), and do all manners of transformations before spitting it back out as a string of clean JavaScript.

I began to think about how I could represent an entire application as JavaScript objects since properties can be easily accessed with dot notation:

{
  route: {
    path: '/',
    component: {
      name: 'Homepage',
      template: {
        element: 'article'
      }
    }
  }
}

route.path --> '/'
route.component.name --> 'Homepage'
route.component.template.element --> 'article'

This syntax is clear and easy-to-understand; the concepts are memorable.

Data can be traversed quickly and there's no friction to access it.

The "way-finding" of dot notation reminds me of subway stops, and the same recognizability and familiarity they bring. The more one travels the same paths, things become second-nature and automatic.

Today, this type of data lives in memory, client-side databases, server-side file systems, external databases, cloud providers, etc. The "source of truth" is difficult to define, if it ever was defined in the first place.

But with objects, every high-level concept in an application can be nicely represented where it is easier to visualize:

{
  cache: {}, // File cache used by server/service worker
  content: {}, // Localized dynamic content (CMS)
  controller: {}, // View controllers
  data: {}, // Application data
  layout: {}, // Page layouts
  route: {}, // Resource routes
  schema: {}, // JSON Schemas for data and application object validation
  template: {}, // Page templates
}

Each concept of the application has a place:

  • Routes/HTTP/Caching
  • Layouts/Templates
  • Data/Content management
  • Data Validation
  • Application Logic

As other concepts arise, they can be added to this structure.

The structure seems very list-like at first. In areas like templates, though (where HTML is represented), data is often deeply nested in a tree structure. And yet in other areas, we really need to reference other data, like a relational database.

Every concept in the application could be a document that had a specific type, for example:

{
  "name": "Homepage",
  "type": "template",
  "content: {
    "element": "article",
    "attributes": {
      "class": "pa3"
    },
    "content": "hey, world"
  }
}

This document's type is "template", therefore this document describes an HTML template for a page. Other types like image, schema, layout, color, and more could be used to describe everything.

Lessons learned

This post covers the last 5 years of my life working on and thinking about Hyperspaces.

Prior to this time, I had no clear notion of how an application like Hyperspaces could be built in total.

Eventually, I could envision pieces of it.

In time, I had definite thoughts about large parts of it.

Other areas have been like rooms at the end of a dark hallway; areas I can't bring myself to go into…

Our approach to this project is one of learning, questioning, building, questioning, re-building, stepping away, learning, starting over, rinse and repeat.

This journey has definitely not been a straight path. I've hit many walls before realizing that I could walk around them or dismiss them altogether. There are no "show stoppers" if you look at things from another point-of-view.

Different points-of-view got me thinking about representing things as data, which in turn changed the way I write code, which in turn is shaping how we are designing and developing Hyperspaces.

Remain open to possibilities. Question assumptions. Be flexible when it serves the project best.