Ceremony vs. Essence Revisited
Tags: apprun, react, vue, svelte
Published: 2020-03-18 15:32:01

---
title: Ceremony vs. Essence Revisited
published: true
description: This post review the 'Ceremony vs. Essence' idea against some modern front end technologies
tags: #apprun #react #vue #svelte
---

## Introduction

Recently I found a [Youtube video about AppRun](https://www.youtube.com/watch?v=TB2Qv2KAMkc), in which the author built and compared the character counts between two similar apps using [AppRun](https://apprun.js.org) and [Svelte](https://svelte.dev).

The comparison reminded me of the 'Ceremony vs. Essence' discussion happened about ten years ago. At that time, Ruby was on the rise. People compared [Ruby with C#](https://davesquared.net/2010/07/essence-and-ceremony-ruby-and-c.html).

> The fundamental idea of the Ceremony vs. Essence idea appears to be that, all other things being equal, programming languages should attempt to allow programmers to clearly express the essence of their programs without being caught up in excessive ceremony provided by the programming language. -- From this [post](http://bryanpendleton.blogspot.com/2010/02/ceremony-vs-essence.html).

Let's take a look at some of today's frontend technologies from the Ceremony vs. Essence point of view. We will use a simple button click counting application as an example. 

![Svelte](https://dev-to-uploads.s3.amazonaws.com/i/7mo21xx84dlho7j9tybp.png)

## The Essence

The essence of the application is to display a button which adds the count by one and shows the count. Also, it will log some messages in the console to mimic effects after the rendering cycle.

The concept is as simple as below.

```javascript
<button onclick="count+1">
  Clicks: {count}
</button>

console.log(count); // upon very click
console.log('mounted!'); // upon mounted
```

We will use the 95-character essence code above with a few frontend frameworks, such as AppRun, Svelte, React Hooks, and the Vue Composition API.

> A framework defines a skeleton where the application defines its features to fill out the skeleton. -- you can find this quote from googling.

When using the frontend frameworks, we need to write some code to plugin the essence code into the frameworks. The code required to plugin into the framework is the ceremony. We don't want them. Less of them is better.

## The Ceremony

### AppRun

Application logic is broken down into three separate parts in the AppRun architecture.

* State (a.k.a. Model) — the state of your application
* View — a function to display the state
* Update — a collection of event handlers to update the state 

```javascript
import app from 'apprun';

const add = count => count + 1;

const view = count => <button $onclick={add}>
  Clicks: {count}
</button>;

const rendered = count => console.log(count);

app.start(document.body, 0, view, null, { rendered }); 
console.log('mounted!');
```

In the example above, the application state is a number that has a default value to be 0; the _add_ function is the event handler to update the state. The _view_ function displays the state. The _rendered_ function runs after the DOM is rendered. The _app.start_ function ties them all together to the _document.body_ element.

Now, we identify and cross out the ceremonies.

![AppRun](https://dev-to-uploads.s3.amazonaws.com/i/7eypk2z64h5azepxnlbc.png)

AppRun code ceremony is mainly required by the JavaScript syntax, like the module import and the arrow functions. The only thing needed from AppRun is the _app.start_ function. 

Overall, it has 226 characters, which means 58% of code are ceremonies. 

### Svelte

Svelte uses a single file for a component. The file consists of a script section for code and the UI template. It requires a compiler to turn it into the runnable JavaScript code. 

```javascript
<script>
  import { onMount } from 'svelte'
  
  let count = 0;    
  const add = () => count + 1;
	
  $: console.log(count)
  
  onMount(() => console.log('mounted!')
</script>

<button on:click={add}>
  Clicks: {count}
</button>

```

Behind the scene, the svelte compiler creates the component class boilerplate. Then, the compiler extracts the _script_ block, wires up the [reactivity](https://svelte.dev/tutorial/reactive-assignments) ($:), and adds the rendering template into the boilerplate. The boilerplate does not exist in our codebase. Therefore, the svelte application has very little ceremonies.

![Svelte](https://dev-to-uploads.s3.amazonaws.com/i/o5j864n6r89tvqzqbcev.png)

Svelte code ceremony is also mainly the JavaScript syntax requirements. Only the _script_ tags are required by the Svelte compiler, which is worth of trading with what the compiler saves. 

It has 217 characters, which means 56% of code is ceremony.

## React Hooks

The React code is a slightly modified version from the [React Hooks Docs](https://reactjs.org/docs/hooks-overview.html).

```javascript
import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  const add = () => setCount(count + 1)

  useEffect(() => {
    console.log(count);
  });

  return (
    <button onClick={add}>
      Clicks: {count}
    </button>
  );
}
```

The React code has more ceremonies than the AppRun code and Svelte code above. It has 272 characters and a 65% ceremony.

![React](https://dev-to-uploads.s3.amazonaws.com/i/qtmjinxl7zqpoyz0og41.png)

The _setCount, _useState_, and _useEffect_ functions are the code the deal with the React framework itself. They don't help us to express the essence of the application. They are framework ceremonies. 

### Vue Composition API

The Vue code is a slightly modified version of the [Vue Composition API Docs](https://vue-composition-api-rfc.netlify.com/#type-issues-with-class-api).

```javascript
<template>
  <button @click="add">
    Clicks: {{ count }}
  </button>
</template>

import { ref, watchEffect, onMounted } from 'vue'

export default {
  setup() {
    const count = ref(0)
    function add() {
      count.value++
    }

    watchEffect(() => console.log(count.value))

    onMounted(() => console.log('mounted!'))

    return {
      count,
      add
    }
  }
}

```
The Vue code has 355 characters and a 73% ceremony.

![Vue](https://dev-to-uploads.s3.amazonaws.com/i/v44mpss7ysv5wwx4p45j.png)

The _ref_, _watchEffect_, _onMounted_, _setup, _count.value_, and returning an object of _count_, and _add_ are all required by the Vue framework. Sometimes, they may make writing code more difficult.


## Expression Comparison

We are not stopping at only comparing the character counts. What is more important is how do you express the business logic. How many extra boilerplates are forced to you by the frameworks?

Let's see how do we _increase the counter_ as an example again.

```javascript
// AppRun
const add = counter => counter + 1;

//Svelte
let count = 0;
const add = () => counter + 1;

// React
const [count, setCount] = useState(0);
const add = () => setCount(count + 1);

// Vue
const count = ref(0);
const add = () => count.value++;
```

You can see AppRun uses a _pure function_, which can easily be [strong typed](https://medium.com/@yiyisun/strong-typing-in-apprun-78520be329c1) if you wish. Svelte is also easy to understand. React and Vue are more difficult.

## Conclusion

Both the AppRun code and the Svelte code express the essence well and have less ceremony. I am biased toward AppRun because I am the author. But, I like the Svelte compiler. 

React Hooks and Vue Composition API are cool. However, they both add a lot more ceremonies to our codebase. Remember, the ceremony has no business values but more challenging to understand and, therefore, more costly to maintain.