Functional Programming and OOP
April 20th, 2014
If you are learning programming, you probably have more or less heard about the programming schools of thought for Functional vs. Object Oriented styles.
Functional programming is a coding style that emphasizes functions to produce results that depend only on their inputs and not on the program state (i.e. think calculator math). True functional programming does not change program 'state', or in other words makes the output mutable when run multiple times, although the input may remain the same. Because of this, it is much easier to understand and predict the behavior of a program. Functional programming is a form of declarative programming.
In contrast, object-oriented programming (OOP) was designed to support imperative (procedural) programming. Typical OOP tends to emphasize change of state in objects, imposes coupling between layers hindering modularization, and mixes the concepts of identity and state. What this means is that OOP code can tend to be less reusable than FP code.
Programming languages out there have differences in supporting one style more than the other, but in general it can be assumed that both style paradigms can be supported. For example, although Ruby is generally used as an OOP language, one can still take a functional approach when using it.
Functional Programming Benefits:
- Cleaner code - variables are not modified after defined, making code easier to follow
- Referential transparency - if a function is called with the same parameters, it is certain that the output will always be the same (there is no state that would change it).
- Modularization - the program is more modular, thus promoting bottom-up programming.
- Ease of test/debugging - Functions are isolated with transparency of input vs output, so it is easier to test and debug.
Here are some best practices for functional programming with examples. This is by no means an exhaustive list of best practices. However, a common theme/rule of thumb that I have find useful to remember is that it's better to NOT be destructive and NOT reuse existing variables.
- Don't update variables, just create new ones
- Don't append to arrays or strings or update hashes
- Avoid destructive bang(!) methods
- Don't reuse variables Bad:
Instead of doing this:
array.push(4)
# array = [1,2,3,4] as a result
n_array = array + [4]
OR in the scenario of altering a hash, instead of doing this:
hash[:c] = 3
# hash = {:a => 1, b => 2, :c => 3}
new_hash = hash.merge(:c => 3)
celsius = celsius.to_i
To sum up, the functional programming approach provides quite a few benefits. You can express more with less compact code, the code is more reusable due from being able to abstract and reduce complexity of generic patterns, and it is more declarative and easier to follow than OOP. When coding in Ruby, it's good to be aware of these benefits and wisely choose when to take an FP approach versus a classic OOP approach.