“OO patterns are codified workarounds for missing language features, namely higher-order functions, sum types, and higher-kinded polymorphism (that allows for the expression of recursion schemes).”
— Chris D'Aloisio (@chrisdaloisio) December 26, 2018
Great post! Much of it resonated with my own journey 👏 https://t.co/6onMTBc3eh
I really like this post - it highlights principled ways in which OOP falls down where trying to think about and manage code.
After re-reading the post again, there was another quote that stood out to me that I’d like to explore a little further.
For example, in his discussion of the Single Responsibility Principle, he takes a messy Employee class with three methods, calculatePay, reportHours, save, required by three separate entities, and refactors it into a pure Employee data type and three object-functions, PayCalculator, HourReporter, EmployeeSaver, that take the Employee data structure and performs the specific function8. (With functional programming, this separation is automatic.) Then he bundles the things together again with an EmployeeFacade (a module signature). But, I ask, if you’re going to write OO code like this, why not just use Haskell?
Well, I’d like to think that most people who have been introduced to Haskell would like to answer “I can’t think of a compelling argument not to use it”. However, I think there are a number of reasons that make the majority of seasoned, professional software engineers answer “no” to that question.
Some answers that I routinely come across include:
- “Because it’s too difficult to learn”
- “Because I can’t see how it be that different”
- “Because it’s not useful when I need to write dynamic programs”
- “Because I can’t use any of my existing knowledge about OOP to write code”
- “Because I won’t be able to get work done as fast as I do in my current language”
- “Because I have no idea about the ecosystem. What is testing like? What are deploys like?”
There were three areas that I felt helped me the most over the past few months with these questions.
- Learning curves
- Feeling intimidated
- Support networks
Whoa! That’s a steep learning curve you’ve got there!
Haskell is notorious for being difficult to learn. And there is a lot to learn. There is a great resource by Steven Diehl titled “What I Wish I Knew When Learning Haskell” that covers many topics at a high level. Just getting the basics down is a difficult task because there isn’t really a definitive source on what the “basics” are.
And really, I don’t think there is enough context even at that point because you need to ask, “basics” for what exactly?
- Writing a simple script that you don’t have to run anywhere except for inside GHCi?
- Having a command line app that will run on multiple platforms?
- Writing a desktop app with a complex GUI?
In such an expressive language that has been evolving and growing over the better part of the last three decades, then combining that with the amount of choice that the language and it’s libraries give you in terms of abstractions and implementations, I think the mistake that I’ve made in the past, is that you go in thinking that you need to learn everything in order to write anything. This couldn’t be further from the truth.
Pick a small project, one that you commit to releasing and/or having in production, bite the bullet and dive in. Working with functional programming principles on an actual project that has code running in the wild, will solidify abstract concepts in your mind so that you can start seeing how they might be useful in other contexts.
The learning curve will only increase as more concepts and ideas make their way into the language. There is no avoiding the steepness of the curve. But by reducing your scope, you don’t have to climb at such a high angle for an extended period of time which would have otherwise most certainly led to burnout.
Overcoming Intimidation
Taking the first step is hard. Seeing and reading through libraries and their implementations, written by experienced Haskellers is a sobering experience simply because of the amount of code that is unfamiliar to you. There needs to be a reset button on your expectations before jumping in.
Being a self-taught software engineer and dabbling in a variety of languages over the past 10 years, I never really had that much trouble grasping any of them after a short amount of time, say a couple of months, and was able to be relatively productive as a result.
Haskell is not like that at all. Mathematical concepts, new ways of thinking about abstraction and generalisation, a syntax that isn’t intuitive if you don’t have an understanding of mathematical notation, etc.
You simply can’t place the same amount of pressure on yourself to learn all that Haskell has to offer in comparison to when you tried to go from PHP to Ruby for the first time (if you ever did that 😉). Instead, you need to give up on this idea that you’re going to be productive in a short amount of time if you try to learn everything upfront.
Thoughts and feelings
It’s important when attempting to learn something new that you share your thoughts (and more importantly, feelings) outside of the enclosed and safe quarters of your mind.
Having an outlet in which you can interact with your thoughts, outside of your mind really helps disperse any feelings of worry, doubt, skepticism, etc, that you may have about whatever it is that is creating a negative learning environment for you.
The Haskell community has come a long way in recent years with respect to absolute beginners. Taking a look at the State of Haskell 2018 survey results, there are more people than ever before wanting to use Haskell in production at work and in personal projects.
I’ve personally found that the sheer volume of learning materials and overall friendly people wanting to help you (on places like Slack) has absolutely skyrocketed in the last year and I look forward to seeing more and more people who, regardless of where they are in their journey, feel compelled to join in on the conversation.
Having the support of others around you is crucial to supercharging your journey. When you begin, you will start to feel more engaged and motivated to continue with your learning and applying your newly acquired knowledge to real-world projects, especially when the going gets tough.
It’s a long road, it’s a hard road. When starting, choose one, not both.
I’ve covered some of the things that prevented me (and might prevent you) from answering in favour of using Haskell.
I’ve found that with some re-framing of perspective and expectations, I have been able to finally become productive using Haskell. I wish I had these bits of information internalised a few years ago - it would have helped enormously.
This is not a new story. It’s just my version of it. And finding more posts about these experiences helps to normalise it, help others feel safe to ask questions when they are stuck, and/or to give them inspiration and courage to proceed.
If there are obstacles preventing you from reaching your goal that are what I’ve mentioned, or if you have others, I’d love to hear about them so feel free to reach out via Twitter.
I’ve purposely avoided technical topics arising from “just using Haskell” - but I’m definitely interested in exploring some problems solved using Clean Architecture in an OO paradigm and how that compares with the FP implementation.
Thanks for reading!