Continuum | Unified Programming
Imagine if an architect’s blueprint automatically generated a building for free. I want that, for programmers.
Groundhog’s Day
At a sufficiently high level of abstraction, every piece of software ever crafted looks sufficiently identical. I believe in categorizing things into human-mind-sized chunks, and at my chosen level of abstraction, all software are tools for solving problems and all tools do just two things:
- Provide resources to the user, especially data
- Empower the user to manipulate the world
(and in the context of problems that software is good at solving, providing and manipulating information. Also, as a complete aside, go one level higher, and all problems become simply creating human value)
What this means is that at the core of every piece of software you, or your company, has written, you’re only doing two things. Just two. Regardless of the technology stack, problem domain, or budget behind a solution, the solution will always 1. provide resources, and 2. provide a tool for changing the world. Maybe you can look at these two things as providing inputs to a human, and amplifying their outputs.
I started realizing this early on in my programming career, as I was writing stuff in Python, JS, and eventually Clojure and Haskell. No matter who’s project I was working on, I was doing the same things! I felt like a plumber. Working in houses that superficially looked different, but ultimately I was making sure that the house had sufficent input of some things, and collecting their outputs, (and hopefully not mixing them up). People pay me to architect big beautiful complex weaves of pipes to solve some problem, and yet I spend most of my time joining PVC, and figuring out why the heck this pipe isn’t passing water where I’d intended it to.
Every day, and every line of code, felt somehow the same - like I was always repeating myself.
The Opportunity
A developer should not lay that piping/wiring herself, in the same way that a doctor isn’t needed to administer every shot.
- That developer’s time is expensive. (Do Not Repeat Yourself)
- Maintaining/growing ad hoc code is more expensive. (Code is a Liability)
- Hand-written code tends to have issues that weren’t obvious at development time, and Bugs Multiply.
Seeing this birds-eye view of what code really does allows a motivated individual to design a general solution to the problem; a solution which can hopefully make math-backed guarantees and obviate the risk of hand-written pieces, which frees developers up to design just the high level, value-generating pieces of the solution, and allows them to iterate on those designs faster.
Imagine if an architect’s blueprint automatically generated a building for free. I want that, for programmers.
What a Solution Needs
Plumbing the Truth
In software, if something is True I would like it to be true all over. If my database says a user’s name is “Pedro”, I want to make sure that Pedro’s account says the same thing. And if Pedro changes his name, I want to make sure that all devices he’s logged in through reflect it. Managing just this simple feature is actually a developer-intensive process. And changing the solution to fit new requirements is equally intensive.
To solve this, I am looking to CRDTs as a way of saying that Truth exists, even if it hasn’t propogated to the database, or the client yet.
Do Not Repeat Yourself
In order for the truth to propogate through your service, plumbing needs to exist between a database, possibly a server, and then all clients that need a given piece of data. The following examples of the requisite glue code are meant to bore you into craving a solution. Feel free to skip over them, but perhaps notice that each block of code is a different way of expressing “here’s how you get my name”, and “here’s how you change it”.
Manipulating a database looks like this:
SELECT name FROM user
UPDATE user SET name=...
Working with the database on the server might look like (YeSQL):
(fn select-user [user-id db] (sql-user-select {:id user-id} db))
(fn update-user [user-id new-user db] (sql-user-update ... db))
Offering an API endpoint from the server would be (Compojure):
(defroutes app
(GET "/user/:id" ...)
(PUT "/user/:id" ...)
Consuming an API endpoint from the browser (clj-http):
(client/get ".../user")
(client/put ".../user")
Then you’d store that data in, say, a clojure map:
(assoc db-atom ...)
(update db-atom ...)
And when you were ready to display it, you could use re-frame:
(fn []
(let [name (subscribe [:user-name])]
[:div
[:p (str "Your Name Is: " @name)]
[:button {:click (fn [] (dispatch ...))}
"Update your name"]]))
Gah! That’s a lot of plumbing. And now imagine you want to add a piece of data, or change this bit of plumbing. Nightmares ensue.
Conclusion
Leaving at the bleeding edge of computer science and mathematics are some ideas that I think will evolve into the solution for this problem.
I’m commited to solving it! And if you have any awesome ideas, or know of anyone else working on something else similar, please let me know!