Mark Dessain

Part 2 - Prototype and Proof of Concept

We want to prove that something works. As quickly as possible with as little effort as possible. We expect that every line of code will be deleted.

Lets get started

Given the preface that we will delete every line of code that is written should outline the level of effort and care we should be taking while developing the prototype. It is going to be held together with sticky tape and require lots of manual actions to be taken behind the scenes.

  • We are probably not going to have any tests apart from us clicking around in the user interface.
  • We are probably not going to have a database and for the application to reset on a restart.
  • We are probably not going to handle errors correctly causing the application to crash or show error messages.
  • We are probably going to put all the code into a single big file.

That is all fine, it will allow us to demonstrate some actions, how they work and what the user experience could be like. Let us just ignore all the good practices for now and focus on allowing us to make changes as quickly and easily as possible.

Having something real, albeit very basic and slow allow for a great deal more understanding and can really spark someones imagination.

Example

The below example provides a web application with buttons to increment or decrement a counter.

We write the code and run

go run main.go
// main.go

package main

import (
	"net/http"
	"strconv"
)

var counter int

func main() {
	http.HandleFunc("/", index)
	http.HandleFunc("/increment", increment)
	http.HandleFunc("/decrement", decrement)
	http.ListenAndServe(":8080", nil)
}

func index(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte(`
		<!DOCTYPE html>
		<html>
			<head>
				<title>Evolution</title>
				<script src="https://unpkg.com/[email protected]"></script>
				<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.classless.slate.min.css" />
			</head>
			<body>
				<main>
					<div role="group">
						<button hx-target="#counter" hx-get="/increment">Increment</button>
						<article>Counter: <span  id="counter">` + strconv.Itoa(counter) + `</span></article>
						<button hx-target="#counter" hx-get="/decrement">Decrement</button>
					</div>
				</main>
			</body>
		</html>
	`))
}

func increment(w http.ResponseWriter, r *http.Request) {
	counter += 1
	w.Write([]byte(strconv.Itoa(counter)))
}

func decrement(w http.ResponseWriter, r *http.Request) {
	counter -= 1
	w.Write([]byte(strconv.Itoa(counter)))
}

// ...

Deployment

We are able to build and run the above on our own computer. However what happens if other people want to be shown the application?

We can deploy this application and run it on a server with very little effort. We can build the binary for the server architecture, copy it onto the server and then run the application.

GOOS=linux GOARCH=amd64 go build -o evolution main.go
chmod +x ./evolution
scp ./evolution <USER>@<IP>:/evolution
ssh <USER>@<IP> /evolution

As long as the port is available for others your users will then be able to visit http://<IP>:8080 and be able to see it running. There is no domain name, there is no SSL certificate, no logging, no monitoring, no authentication but again that is fine.

We are just running it to demonstrate how it runs and once we are finished we can shut it down again.

The only precaution I would take at this stage is for if this is for internal only to ensure that your server is not open to the world wide web and has some form of firewall to restrict who can access it.

Dependencies

Right now we only have a handful of dependencies.

Limiting the dependencies will allow us flexibility in the future and ensure that we limit the surface area for things that can go wrong or need changing.

Code

Github: part-2-prototype