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() {
:= thing1.New()
t1 := thing2.New()
t2
.BindThing2(t2)
t1}
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() {
:= thing2.New()
t2 := thing1.New(thing2)
t1 }
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 Foo
s, and a
group of services which mutate Bar
s. 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?