One-pager: Grokking Simplicity by Eric Normand
A gentle yet effective introduction to practical functional programming.
As a software engineer by trade, I highly recommend Grokking Simplicity (non-affiliate link) as a gentle introduction to practical functional programming.
Here were my favourite takeaways (in actual fact, I think #6 is the most important):
Embrace simplicity in programming: Understand that simpler code is more maintainable, less prone to bugs, and easier to reason about. Be aware that unnecessary complexity can lead to errors and confusion. Prioritize simplicity in all your programming endeavors.
Prioritise functional programming: Leverage the benefits of functional programming. Learn to separate data and behavior, avoid state mutation, and minimize side effects. Understand that functions are first-class citizens that can be passed around like any other value.
Master pure functions: Write pure functions whenever possible. These are functions that always produce the same output for the same input and have no side effects. They are easier to test, more predictable, and simpler to understand.
Avoid state mutation: Strive to avoid changing state. This approach reduces the likelihood of bugs caused by unexpected state changes. Instead, use immutable data structures and create new values rather than changing existing ones.
Limit side effects: Limit the scope of side effects in your code. Understand the implications of side effects and work to isolate them, ideally confining them to the boundaries of your system.
Understand data in, data out: Embrace the concept of “data in, data out.” Functions should take in data, transform it, and return new data. This makes your code more predictable, easier to test, and simpler to reason about.
Use higher-order functions: Utilise the power of higher-order functions. These are functions that can take other functions as arguments, or return them as results. They can greatly increase the expressiveness and reusability of your code.
Learn recursion: Master the concept of recursion, a powerful tool for solving problems in a simple and elegant way. Understand that recursive solutions often have less state and are more declarative than their iterative counterparts.
Leverage composition and abstraction: Use function composition and abstraction to build complex functionality from simpler parts. These techniques can help you manage complexity and make your code easier to understand and maintain.
Apply functional programming in real-world scenarios: Don’t just learn functional programming concepts in isolation. Apply them in real-world scenarios, solving complex problems with simplicity and elegance. Understand how these concepts can make your code more resilient, easier to reason about, and simpler to maintain.
Grokking Simplicity is not about memorising a list of rules or techniques. It’s about developing a mindset that prioritizes simplicity and clarity, using functional programming as a tool to achieve this. Adopt this mindset, and you'll become a better, more effective programmer.