I've only been developing for the web for two years. When I started I was still deeply in the land of bad C# code with all of it's InvoiceListDataManager
inheriting from ListManipulatorAbstract
. I would start new projects with some UML drawing tool just like they taught us at university. I wanted to take this with me to Javascript and I spent most of my energy trying to make object oriented classes work - but I was never happy with it.
When I found Underscore.js I fell in love. I remember reading the documentation, then pitching it to my boss. Grudgingly he accepted the extra 5kb and later that day I used _.chain
to form a pipeline for calculating some invoice totals in our app. It felt good; I liked that I was writing less code and using only the abstractions I needed.
It wasn't perfect. I wanted to use _.chain
with other things, but the only way to do that was to _.mixin
new functions. Mixins modify underscore globally, I wanted to avoid doing that though because modifying what's not yours is a quick way to end up in a total maintenance disaster. I played around with _.compose
for a bit. That let me put functions in my own modules which seemed to be what I wanted, but _.compose
actually doesn't work well with the standard underscore functions due to the order of their arguments.
I found this super uncomfortable; I started looking for other options. Briefly I went back to the ListHelperManagerSpelunker
nonsense, but it was awful. I liked chaining functions together. At this point I came to the conclusion that object oriented programming was all about distributing state over encapsulated, decoupled objects. That might be good for some things but I wanted to get closer to the data I was working with. I wanted everything to be about transforming what you had into a finished product through some sort of pipeline of function calls. In developing a web applications I found myself asking, how do I get from this starting state - a url - into this finished state - a rendered page. I wanted to write as little code as I could because that meant using generic abstractions. If you build everything out of weak generic abstractions like map and reduce then you've got code that is easier to reason about because there's a limited scope to what each function can do.
My experiments here were imperative and honestly not very good. I found _.compose
useful for joining some bits of functionality together but I couldn't get away from big nested if-blocks which forked off in different directions. It seemed easy enough to write a command line utility in this style, but a web-page, with event handing and two way data binding? Yeah - I couldn't figure that out.
After watching some great presentations by Brian Lonsdorf and doing a little bit of further reading I found out that other people are into this stuff too. They call it functional programming. I'd heard that term before but tried to avoid using it. It sounds like a stupid name, akin to "Intelligent Dance Music" or something. It also seemed like a problem that any language that has "map" or "reduce" gets to say that it is "functional". The things that Brian was talking about were so much more than "map" or "reduce"; what he was talking about was fantastical. It looked like a completely new and radical way to structure a Javascript application without all of this imperative plumbing crap that I had been writing. I don't think there has been a time in my life where I was more intrigued by a concept - well, maybe there was, but I'm not sure when.
From there it's been a crazy and mind-warping road. It is a road fraught with terms like "monad" and "applicative functor". People say things like "referential transparency" and "side effects". You can look up those terms if you want, but I promise you that the definitions fail to capture the weight to which these people use them. I've had to relearn recursion - which is a terrifying experience. Just coming out of learning recursion is like what I imagine what coming out of the brain-surgery theatre feels like - and I've still got so much more to learn.
All the while, I've been trying to connect the dots back to my own work in developing web applications. Can monads and applicative functors help you write Javascript code that is easier to reason about than the object oriented stuff?
Does fantasy land really exist? I don't know but I'm going to find out.