On Descartes and Microservices

published: 2016-05-06 | generated: 2024-06-04 | tagged: ,

And other annoying shit I’ve just made up.

This post is about dependency injection, a decoupling technique used by programmers often with wanton abandon.

I’m not going to apologize for the above non-sequitur, but rather to attempt to contextualize it. To begin, let’s talk about Descartes:

René Descartes

Descartes is responsible for what is probably the penultimate existential statement, eclipsed only by Shakespeare’s “to be or not to be”. Descartes’s goes like this:

Cogito ergo sum

Or

I think, therefore I am.

Descartes’s whole spiel was I can’t doubt that I exist, because there must be an “I” to doubt “I”. That is, doubting my existence is dependent on me existing and then doubting that I exist. An interesting strange loop indeed.

Computers

I recently found myself in an analogous existential argument about when a component in a program commenced to exist.

This component is dependent on another, and my coworker was of the school of thought that this component’s constructor should be decoupled from the injection of its dependency. Something like this:

func main() {
	t1 := thing1.New()
	t2 := thing2.New()

	t1.BindThing2(t2)
}

However, I believed that there was no reason for t1 to even be constructed if it there was not yet a t2 to meet its dependency. Like this:

func main() {
	t2 := thing2.New()
	t1 := thing1.New(thing2)
}

My coworker had a compelling argument. For us to reach optimal clarity on his argument, we first must be live. That is, consistent on our understanding of a few things, so I must digress.

—- Begin Digression —-

Microservices

A overloaded term which, to me, means Domain Driven Design, where each “domain” is composed of subdomains (read: microservices) of functionality.

For example, you have a group of services which mutate Foos, and a group of services which mutate Bars. Each of these “domains” have independent services which have discrete responsibilities such as paint-bar or flip-foo. A service in the Foo domain has no knowledge of a Bar whatsoever. Ideally not even through a dependency like an ORM with both Foo and Bar declarations within it. This complete, physical delineation protects each domain from the other’s faults.

The Go Programming Language

An interesting thing about the design of the Go programming language is that the language itself gently leads you down the path towards something microservice-like even though your software may exist completely in a single runtime. This is done through goroutines, channels, and long-running loops. With Go, you find yourself writing a distributed system, passing messages back and forth between disparate, long-running, reactive loops all within a single runtime. It’s important to consider this mindset when considering my coworker’s argument.

—- End Digression —-

So, given this context, when does a service commence existence? Is it at instantiation? Or, when it becomes useful, with all its subsystems in line and ready to take on the world?

What do you think?