Design By Contract, Immutability, Side Effects and Gulag
Tags: nim, dbc, contracts, tdd
Published: 2019-07-11 18:44:01

---
title: Design By Contract, Immutability, Side Effects and Gulag
published: true
description: Design By Contract on 2019 with more KISS & less Bugs
tags: nim, dbc, contracts, tdd
cover_image: https://raw.githubusercontent.com/juancarlospaco/nim-contra/master/contra.jpg
---

# World Of Bugs

> There are 1.4 billion insects for every human, most of them on your code

*The concepts on this post are useful for any language, examples are from [Nim](https://nim-lang.org).*

[Defensive Programming](https://en.wikipedia.org/wiki/Defensive_programming) usually takes the form of a Unittest, 
Unittest checks a "unit" of code, validates using assertions on special test runs,
runs a code block and asserts that the result equals a predefined "sample" result.

This is good, but is has some limitations, 
the input, data and context is very often faked (mocked),
the input is usually not asserted because is kinda fixed,
the output is result of the inputs so neither is completely real world,
it runs on "dedicated" automated tests runs.

- How can tests be more integrated and close to the code where the bug lives?


# Side Effects

![](https://image.slidesharecdn.com/getfunctionalprogrammingwithclojure-cebit-160315080400/95/get-into-functional-programming-with-clojure-6-638.jpg)

> Bugs is the entropy of the universe trying to reverse engineer your code while you are still writing it

Side Effect Free programming is focused on eliminating side effects on the code,
and monitoring or controlling them where you can not eliminate them.

[Functional programming](https://en.wikipedia.org/wiki/Functional_programming) tries to reduce Side Effects,
without Side Effects the Bugs can not spread on the code, helps reducing Bugs.

Side Effects examples:

- Writing to terminal or files, reading from terminal, files or user input.
- Mutating in-place of variables, globals, objects, types, data structures.
- Date/time functions, Win32 API/Registry, Databases, HTTP, GUI, exceptions. 

[Nim](https://nim-lang.org) has [Side Effects Tracking](https://nim-lang.github.io/Nim/manual.html#procedures-func), Functional advantages while still using OOP.
Simply changing `proc` to `func` will check for side effects on your functions!.


# Immutability

> Immutability changes everything!

[Immutability of variables](https://en.wikipedia.org/wiki/Immutable_object) helps to fight Bugs by not allowing unwanted mutations,
using Immutability whenever possible is very encouraged.

Nim is immutable by default and has 3 kinds of variables:

- `let` its a runtime **immutable** variable.
- `const` its compile-time **immutable** variable.
- `var` its runtime mutable variable.


# Contracts

![](https://upload.wikimedia.org/wikipedia/commons/thumb/e/ea/Design_by_contract.svg/512px-Design_by_contract.svg.png)

> TDD is Poor-Man's Contracts

Some programming languages use a different way of dealing with all this,
languages like [Ada](https://en.wikipedia.org/wiki/Ada_(programming_language)) or [Eiffel](https://en.wikipedia.org/wiki/Eiffel_(programming_language)), use [Design by Contract](https://en.wikipedia.org/wiki/Design_by_contract). Applied [Hoare logic](https://en.wikipedia.org/wiki/Hoare_logic#Hoare_triple).

Contracts can assert on input, data and context on the beginning of a code block,
and can also assert on the result at the end of a code block,
it lives in the code block as close as possible to it, it runs an actual real run,
everything is real inputs, data, context and whatnot,
on programming languages that support compile-time code execution all this can happen at compile time if desired.


# Contra

{% youtube DRVoh5XiAZo %}

> The night is dark and full of errors

[Contra](https://github.com/juancarlospaco/nim-contra#contra) reimagines Design By Contract in a modern [KISS](https://en.wikipedia.org/wiki/KISS_principle) way, 
all the benefits of [Assertive Programming](http://stackoverflow.com/questions/787643/benefits-of-assertive-programming) on statically typed compiled language,
like everything on [Nim](https://nim-lang.org) it takes a lot of care about performance,
it allows fast contracts with zero cost at runtime with a comfy API,
requires minimal modifications on existing code, just 2 lines to add a Contract.

Lets take a buggy example code and add a Contract to it:

```nim
proc myFunction(mustBePositive: int): int =
  result = mustBePositive - 1
```

Remember that `mustBePositive` must be Positive, lets use the function:

```nim
proc myFunction(mustBePositive: int): int =
  result = mustBePositive - 1

echo myFunction(0)
```

This is a Bug, `mustBePositive` is not Positive (`0 - 1` is `-1`), lets add Contra, 
and ensure that there are [no Side Effects](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) [using `func`](https://nim-lang.github.io/Nim/manual.html#procedures-func): 

```nim
import contra

func myFunction(mustBePositive: int): int =
  preconditions mustBePositive > 0 # Require 
  postconditions result > 0        # Ensure
  result = mustBePositive - 1

echo myFunction(0)
```

The Contract shields our code from the Bug, wont allow the Bug to spread.

- `preconditions` takes preconditions separated by commas, asserts on arguments or local variables.
- `postconditions` takes postconditions separated by commas, must assert on `result`, can assert on local variables.

To keep things simple, no `body` nor `invariants` blocks are required, 
you can pass invariants mixed on the `postconditions` but is optional,
it can be used on [JavaScript](https://nim-lang.github.io/Nim/backends.html#backends-the-javascript-target), interpreted [NimScript](https://nim-lang.github.io/Nim/nims.html), runtime and compile-time.
Your CI service can compile and run a binary with all assertions enabled.


Contra adds `0` lines of code to Release build and `9` lines of code to Debug build.


# Gulag Driven Development

> Make your users work for you

You can now delegate the bug hunting on collaborators and trusted users,
encouraging them to try development binaries compiled with all assertions enabled.

But the same code can also produce a binary with all assertions disabled,
Contra produces no code when build for release, then you pwn on all Benchmarks.

Nim has [automatic Dead Code Elimination](https://en.wikipedia.org/wiki/Dead_code_elimination).

- **Convert your users into being your Gulag CI!.**


# Install

```console
nimble install contra
```

Assuming you already have [Nim installed](https://nim-lang.org/install.html). 
[Try Nim now](http://play.nim-lang.org), you are missing a ton of cool stuff.


# Thank you for playing

![](https://raw.githubusercontent.com/juancarlospaco/nim-presentation-slides/master/nim-bad-cat.jpg)

- [Star Contra on GitHub!](https://github.com/juancarlospaco/nim-contra#contra)
- [Learn Nim today.](https://nim-lang.org/learn.html)
- [Contra on Nimble.](https://nimble.directory/pkg/contra)
- [Nim Telegram Group](https://t.me/nim_lang)
- [Nim Sticker Pack.](https://t.me/addstickers/nimlang)
- [Grupo de Telegram en Español.](https://t.me/NimArgentina)
- Say *Hi* on the bridged [Gitter](https://gitter.im/nim-lang/Nim), [Matrix](https://matrix.to/#/#freenode_#nim:matrix.org), [Telegram](https://t.me/nim_lang), [IRC](irc://freenode.net/nim), [Discord](https://discord.gg/ezDFDw2).

👑