Learning Scala at SoundCloud

I’m a backend developer who worked extensively writing code in Golang before joining SoundCloud. SoundCloud mostly uses Scala for its microservices, so when I joined, it was important to learn it. As I was new to the language, I faced some challenges going from knowing nothing to becoming skilled at writing code in Scala.

This blog post will cover how I kickstarted the learning process, what resources I made use of, how the Scala community at SoundCloud helped me learn and grow, how I was able to keep going when things got challenging, and how I set achievable objectives to monitor my progress.

Learning a New Language

Learning a new language of any kind requires rewiring one’s way of thinking and seeing things. Personally, I had anxiety about not being able to do simple things, like fixing a compilation error that felt straightforward, converting one type to another, or debugging the existing code that had imports that provide implicit functions. However, I found that both being consistent in studying and using a language daily and getting help from people are key to learning a new language.

To give you more insight into this, I’ll share how I started learning with the help of Scala developers at SoundCloud. More specifically, I’ll talk about how I:

  • Enrolled in and completed a Coursera program
  • Ordered a book, Scala for the Impatient
  • Mixed up my learning methods
  • Eagerly dove into the work and sought help along the way
  • Took advantage of learning and development
  • Set personal objectives and key results

Without further ado, keep reading!

Coursera

Coursera is an online learning platform for taking courses on a variety of topics via its partnership with universities and companies around the world. It also provides certification for these courses. I began by enrolling in Functional Programming Principles in Scala, which is taught by Martin Odersky, one of the designers of Scala. I followed the course to first set up my environment, and then I started with my first “Hello, World!” program. I then began learning the concepts, and I worked on a few exercises.

It wasn’t as easy as I thought it would be, and a lot of that had to do with coming from Golang. More specifically, here are a few things I found different:

  • Go and Scala have different approaches to concurrency and parallelism. Go has goroutines and channels, while Scala has Futures and Promises. As a result, concurrent code written in Go and Scala looks quite different. (Here are examples of my code for running a task concurrently in Go and Scala.)
  • Scala takes more time to compile compared to Go. The compile time for the code linked above was 3 seconds in Scala and .16 seconds in Go. The slowness of the compiler is thoroughly described here by Odersky.
  • Go is a procedural and imperative compiled language, and its syntax is similar to that of the C family of languages. Meanwhile, Scala is a hybrid language that combines object-oriented and functional approaches.
  • Unlike Go, Scala is very concise and requires less boilerplate code.
  • Each language has a different approach to tooling. Common tasks — like compiling code, running tests, and building an application — are built into Go. Scala, on the other hand, has a separate tool to do these things, sbt.

To understand why applications should use Scala, it was especially helpful to watch videos and read blogs. They demonstrated both why Scala supports both functional and object-oriented programming, and its uses in different applications. There’s a suggested video on Coursera called Working Hard to Keep It Simple (also from Martin Odersky), and it was a great introduction to understanding Scala in a nutshell. I also recommend the blog post, Strategic Scala Style: Principle of Least Power, which aims to provide style guidelines at the “strategic” level. Scala provides various ways to solve a problem, and that post outlines how to choose one from the range of possible solutions.

Scala for the Impatient

I started reading Scala for the Impatient, which was ideal for a Scala beginner like myself. It doesn’t just introduce concepts; it also compares them to other languages like Java and C++, which was one of the things I really liked, because it helped me better understand and made me curious about how things are done in Scala. It also helped me visualize the comparison and provided a sense of familiarity when learning a new language. It has simple examples for learning Scala and an extensive list of exercises at the end of each chapter. The book began with the basics — like types and arrays — and it progressed to concepts like inheritance, objects, operator overloading, tuples, and lists.

One fun fact I learned is that usually, other languages (such as C, Java, or Golang) use [] to access an element. Scala, however, uses () to access an element. For example, to create an array and to access an element, respectively, in Golang, you’d do the following:

var z [Size]String
var i=z[0]

Meanwhile, to create an array and to access an element, respectively, in Scala, you’d do this:

val z = new Array[String] (Size)
val i= z(0)

As you can see, both the above statements create an array and access an element; however, Scala uses parentheses to access an element, while other languages — such as Go, C, C++, and Java — use square brackets to access an element. Apart from this being unusual in other languages, using parentheses means that collections are considered functions, and this can be useful to include functionalities like map andfilter, which expect their arguments to behave syntactically as functions, and not just semantically. To understand more of the history of using square brackets and the importance of switching to parentheses, please refer to the Syntax for Indexing blog post.

Switching Patterns

All that said, most of the exercises weren’t easy, in the sense that I needed to focus on the problem to solve, and not just the language to express the solution. This is something I felt could’ve been different in the course. Giving problems like Huffman coding, Anagrams, LinkedList, and sorting to Scala beginners is like asking a person who just started learning how to skateboard to do it for 30 kilometers: At this point, the person isn’t really great at skateboarding, much less for that distance.

Since it takes time to learn and solve the problems, I learned not to rush or feel like I had to finish the course quickly. And to keep things interesting and to reinforce my learning, I regularly changed how I learned by switching between watching videos and reading.

I had started reading Scala for the Impatient while still taking the Coursera course, as I found the exercises from Coursera were difficult, and I hoped the book would provide more context. Once I finished reading the basic concepts of Scala and doing exercises from the book, I wanted to try a different learning pattern, so I resumed the Coursera course. This time, I felt like it was easier to listen to and digest the video lectures, as I had just learned these same concepts from the book and the videos served to reinforce those learnings. This is because the simple exercises that I tried from the book provided me with more practical and hands-on exposure to functions and libraries in Scala, which in turn helped me complete Coursera exercises that I wasn’t able to finish before.

Diving In and Seeking Help

Even though exercises and courses helped me code in Scala, the one thing as a beginner that really helped accelerate my learning was to actually work on the projects. I started working on a pull request approximately two weeks after I started learning Scala to update a Scala version in a SoundCloud repository. It used a library called Scalaz, but it started failing after the update. I could understand the compilation error, but I had no idea how to fix it. As a note, this repository was written years ago, and most of the methods or concepts had been deprecated or replaced in the new version of Scala. These things can be learned only by working on them.

When I felt like it was really difficult for me to understand and to fix these errors, I asked questions and sought help from the #scala channel on the SoundCloud Slack, and I also did pair programming with colleagues. In doing so, I found that one of the more effective ways to learn a language, beyond just diving in and doing it, is to actually be part of the community and have discussions. It made me realize that it’s OK to make mistakes and ask questions, as this knowledge sharing helps us learn from each other.

Taking Advantage of L&D

SoundCloud has great employee policies for learning and development (L&D). It provides self-allocated time (SAT) for employees, a budget for learning that allows us to buy books and take courses, and extensive documentation for resources that help us learn and grow as developers. Additionally, SoundCloud has great internal documentation for Scala that covers the best practices, test styles, patterns, and libraries used here to provide guidelines for developers to write idiomatic “SoundCloudy” Scala. This provides sufficient resources for beginners.

Setting Objectives

Learning is a process, and especially considering that Scala is both an object-oriented and functional language — meaning it has many ways of expressing things — it might take a long time for people to master this language. As such, it’s helpful to set objectives to track learning and stay on course, which is where Objectives and Key Results (OKRs) come into play. This is a goal-setting methodology used to set goals with measurable results.

In my opinion, learning is a neverending process, but being able to track things on an individual and company level is crucial to know that the learning is indeed happening. OKRs helped with this. Together with my manager, I came up with my own OKRs using a performance management toolkit at SoundCloud called Small Improvements. These OKRs were to:

  • Finish the Scala course from Coursera
  • Create a small personal project using Scala
  • Get my hands dirty by implementing as many pull requests as possible
  • Perform code reviews on my colleagues’ pull requests
  • Record this process in a blog post to help others who are new to Scala

Key Results

After setting and working toward the objectives outlined above, here are my key results:

  • I am certified in the Coursera Functional Programming in Scala course.
  • I wrote a web service to create/retrieve a playlist that uses the following libraries:

    • Http4s — for the HTTP layer, this library uses cats-effect to manage I/O
    • Flyway for database migrations
    • PostgreSQL for the database server
    • quill for expressing SQL as a Scala class
    • circe for JSON encoding and decoding

Doing this helped me start a project from scratch, incorporate concepts I had learned, and explore various libraries in Scala. You can see the end result, playlists, on GitHub.

Additionally:

  • I implemented features by raising 64 pull requests and code reviewed 44 pull requests in Scala at SoundCloud in the past few months.
  • I finished writing this blog post.

Takeaway

In addition to all I did and learned, I had a few additional takeaways from this process:

  • One of Scala’s goals is to make programmers focus on high-level application logic, so it provides extensive built-in methods. This means I can do many manipulations of any type with less effort and time than in Go. One of the best examples of this is the .map method. With the help of this method, I don’t have to worry about writing code to iterate an array or list. Rather, I can spend my efforts on writing the logic of what manipulations need to be done on these elements.
  • As a developer, I think one of the essential tasks of my job is to write effective test code that’s both readable and easy to write in order to cover simple and complex test cases. One of the simple and yet more efficient testing frameworks that I used in the project is MUnit, in combination with the integration library munit-cats-effect. This made it easy to test the stream response for HTTP testing. Meanwhile, there are other simple and more important testing frameworks, like ScalaTest, with different testing styles.
  • Because I was a Golang developer for almost four years, I nearly forgot about object-oriented programming concepts like inheritance, encapsulation, and polymorphism. The whole process of learning Scala made me recall and refresh these concepts.

Conclusion

Learning is a continuous process, and the longer I’m here at SoundCloud, the more I’m learning. It’s a great opportunity to be able to grow my skills and learn a new language, and if you’re considering doing the same, I hope this post can help you kickstart your learning.

Additional References