Why is it important to share our personal learning experiences?
One of my passions within the tech community is to break down the barrier to technology and open up the space for people who don’t just “get it”. I was lucky enough to stumble into the technology industry and stubborn enough to stay, but I hold my hands up and say this does not come naturally to me. The longer I have stuck around the more I have realised that most scary sounding jargon is unnecessary, most tutorials start with problems too daunting, and ‘blue sky’ Scala still has a barrier of intimidation for many people.
How did I continue with Scala and Functional Programming?
If you’re striving towards ‘pure’ code, we want to start small and push the state to the edge (this is a great talk for reference by Rhys Sharrem). I think it’s important to prioritise a few principles of functional programming and focus your attention on understanding these first before moving on to more complex ideas. The last thing we want to do is intimidate people moving towards functional programming and scare them away for good. I focused on the following three principles:
Immutability means “unable to be changed” and this is favoured in functional programming. One of the benefits of immutability is that it makes the code simpler to reason about and reduces side-effects in your application.
Throwing exceptions within your codebase is generally avoided in functional programming as this also contributes towards side-effects. It means you can’t predict what your function will return or how to deal with that simply. This was the first thing that I worked on reducing when getting serious about functional code as it is provided me with small slices of the codebase I could analyse and improve.
A commonality I have noticed when seeking advice from mentors, is that they all write their function signatures first. The benefits they see is that you end up writing a lot of your code, and decide the direction of your solution, without even trying too hard to solve the crux of the problem. It helps break down the problem in to bitesize chunks whilst forcing you to answer the important questions first. What do I need to pass in to this function? What do I need to return from this function? How do I want to handle success and failure? How does this function fit into the wider codebase?
How to apply these principles?
The first problem I solved with these principles in mind was returning failures without losing messages. If several things fail in a function, we wanted to be able to retain all of the errors so the user can analyse a complete list. The function I was working on was currently throwing exceptions at failure. We all agreed that returning one message and exiting the function, rather than a continuing and compiling a list of messages, meant we were losing vital information. This is where one of my mentors first introduced me to Validated, and the first time I had used a helper library like Cats. We both talked through what we wanted the function to do and how we wanted to handle failure, this helped us compose the function signature. This gave us clear direction for how the function would look. Through this example I learnt about why throwing exceptions wasn’t ideal, the benefits of writing the function signature before jumping straight into the code, and ensured immutability is maintained.
However, you don’t have to tackle these too. Use your current work and roadmap to decide what will be approached organically. Extra context around the problem will help everyone understand why a solution may or may not be suitable. It’s also helpful to get it wrong, allow people to explore a flawed solution as this is the best way to understand and remember why it doesn’t work.
How am I learning?
Since joining my current job nearly one year ago, pair programming has been my default way of developing software. It’s always seemed a controversial topic when I’ve talked about this in the past. From what I’ve experienced, the more your team does it, the better it works. Our team has become very good at it, and in return, we are all happy developers; sharing knowledge, ideas and feedback.
When I started, I hadn’t used a library for functional programming and I still threw an exception or two where I couldn’t think of an appropriate way to bubble up the information I needed. Having someone there to guide me through the bombardment of information and new concepts was exactly what I needed to get started.
However, I noticed a couple of months down the line that I needed space to explore and make mistakes that pair programming just doesn’t create the right environment for. It’s important that people are allowed to recognise what’s best for their learning and exercise that.
The best thing I ever did for my independent learning and confidence was to do kata exercises at home. I started with this list of exercises and began working from the top to write the best solution I could. Then I looked up other peoples solutions, took note of concepts I liked most, and tried to apply it to the next kata on the list.
Throw yourself in: Katas, Red book, Coursera.
I started the Functional Programming Principles in Scala Coursera course about 6 months into learning Scala and felt it was too advanced for me at that time. Approaching it a year later when I had more confidence, I found that one of the first exercises was nearly enough to frighten me off once again. However, this time I persisted and I realised that this barrier to the course wasn’t reflective to the remainder and I hope this will convince anyone else that may have been scared off to try again. I wrote about my experience with the course here.
I’m having the same kind of journey with Functional Programming in Scala, exercise 3 is a real challenge and I have to really motivate myself to keep plugging away with it. This time I know that just because I can’t figure out X, doesn’t mean I can’t tackle Y. I try to move on and continue to learn new things, and come back to it when I feeling more confident, ready to attack the problem in a new way.
Here are some other resources I can recommend:
I touched on this when I wrote about pair programming, but it’s worth mentioning in more context. Giving and allowing yourself more space to make mistakes is so beneficial to your learning, mindset and self-confidence. I try to see it as a necessary step, however hard that may be sometimes. Learning what’s not quite right is just as important as knowing what works.
What are the challenges?
Introducing a helper library for functional programming
Before my current team, I had never used a library for functional programming and I found the learning curve was intimidating. It almost changed the language for me and it felt like I needed to learn all these new tricks in order to get it “right”. Thankfully we practised pair-programming, and my mentor was able introduce concepts one at a time. As said above, we used validation as a great place to start and I continued to pick up new features as and when I touched them in day-to-day development.
Strip a problem back until it’s at its most basic form. You will be able to understand it more generally and be able to apply it to more than just the immediate problem. Get the function signature right even with ???
Another approach we took was to strip the problem back to a very simple example, and build up to the real world example slowly; this ensured each new piece of information was digestible. We stepped away from the desk and focused on a very basic example of validation. We then made it slightly more complex and more like the real-world problem and this gave me a chance to ask plenty of questions without any underlying assumptions.
Getting feedback about your strategy that adapts to your progress
This journey into functional programming means that there is incremental progress from “Java-like” Scala to FP. That means the first few steps won’t be perfect and getting feedback on your strategy in this time-frame will be an ongoing challenge. Ideally we would all have friendly mentors or patient colleagues, but for anyone brave enough to be doing this in their spare time, this is not possible. The only thing I can encourage and push myself to do is get out into the community to help those who want to learn. Although not all of these are specific to functional programming, a few great initiatives are:
From zero to ‘Red Book’
The difference between “Hello World” and the first few chapters of Functional Programming in Scala is huge. Please don’t let that put you or others off. From experience, these courses and books don’t follow a steady diagonal line upwards, there’s a good chance you will find the next topic suitable and you can revisit when you have more confidence with key concepts.
One step at time. Functional Programming Principles in Scala course on Coursera is a perfect example of how some resources can be scary, but that’s not the whole story. Leave that problem and continue on, but don’t forget to go back and smash it when you feel more confident.
While struggling with exercises or problems I often write something, anything, just to get it from running around in my mind. I then work on making sense of it. This stops me from becoming confused with all of the “what about…”s and I can see my solution a little more objectively. Then I tweak and replace some parts of the code until it passes a test (manual or written). Very rarely can I write a solution straight away without changing something, which I think is what I expected to happen at some point.
It doesn’t have to have a ‘click’ moment
Most importantly, there is NO PRESSURE. Everyone is different and will have prior habits or assumptions they may need to shed before a change of mindset.