Vala reactive programming: part 3
Tags: vala, glib
Published: 2022-01-02 21:01:34

The last article showed how we could create a Window with two different forms with clear separation between application logic and GUI code. Most of our work consisted of binding properties and using signals to send information out of components. Although this seems to work well with our little example, our application didn't have any global state. One could argue that global state is a code smell (and a lot of people do), but the fact is that lot's of applications use it to some degree. 

One of the problems of global state is that it increases **coupling**. Essentially, **coupling** represents the amount of interdependency between two or more modules. Frequently, in situations with large **coupling** a change in one module snowballs into lots changes in the related modules as well. This is why **coupling** is seen as bad: there's the possibility of a butterfly effect in which a small change in one module produces a large change overall. 

We could simply add properties to our `Application` class pass them along to our components. This could be done either through bindings, via constructor parameters or by referencing the parent component using `(Application) this.parent.property_name`. All these options are fine, in the sense that they work but might cause **coupling** problems. 

The first two may require passing a reference to or binding `Application` to basically every class you write. Not only this is annoying but it also makes testing harder. We might need to mock `Application` for basically every class we test, since we are introducing a hard dependency on `Application` existing even in functions where it's not used.

We could circunvent this by using `parent` references. However, we can easily get to a point where code like this is written: `parent.parent.property_name = ...`. Not only this type creates highly coupled components, it's also very brittle. A component might break because of a change in the hierarchy of an apparently unrelated set of components. It might also be a nightmare to test, since we might need to reconstruct whole hierarchies of objects

#### It's possible to avoid this problems by being extra careful. The issue here is that it's easy to shoot yourself in the foot when using these approaches. So we'll try something different.

In this post we'll explore using a *Singleton* to store shared data and logic. A *Singleton* is a class that only has one instance which is shared. Although *Singleton*s look like classes with all `static` properties and methods, some key differences exist:

1. *Singleton*s can implement interfaces
2. *Singleton*s can lazy load resources 
3. A *Singleton* instance can be passed a argument to other functions or methods

Building a singleton in Vala is easy:

```c#
class SingletonExample {
    private SingletonExample () {
        // TODO: initialize all resources here
    }

    private static SingletonExample? _instance;

    public static SingletonExample getInstance () {
        if (_instance == null) {
            _instance = new SingletonExample ();
        }
        return _instance;
    }

    // shared data is created using public properties

    // shared logic is created using public methods 
}
```

Using it is even easier:

```c#
SingletonExample.getInstance ().method_here ();
SingletonExample.getInstance ().property_name = XXX;
```

Make no mistake, if we need shared data we are going to have to deal with *coupling*. 

#### By using a *Singleton* **all components depend on the *Singleton* **, which helps us to **avoid components depending on other components**.

The advantage of using a *Singleton* is that it concentrates the dependencies into a single class. Instead of using `parent` or passing references deep into our component hierarchies, we can access `SingletonExample.getInstance ()` anywhere in our code. We can also bind to `SingletonExample`'s properties and connect to signals it emits. Thus, our reactive components can now react to local as well as global state changes. 

Some situations where using *Singleton*s may bring advantages include

1. sharing a list of opened folders/files in a text editor
2. saving/retrieving user settings from dot files and making them available to the rest of the application
3. storing a list media folders in a music/videos application

Global state should be minimized and good design helps both decreasing *coupling* and creating testable and quality code. However, sometimes using shared state leads to simpler design and less code. If this is the case, you might want to consider using Singleton in your next project.