Hi, Habr! I present to your attention the translation of the article by
Roman Prozaznik -
Why FP matters even for OOP developer?Once I was very interested in functional programming, I began to study it and tell all my friends about how wonderful it is. Later I came across an article on functional programming from the OOP point of view of a programmer and decided to translate it for you. Do not judge strictly, this is my first translation.
I was asked to express my personal opinion on functional programming from an objective-oriented point of view. I was even forced to create an account on Medium. As an ex-OOP developer, and at the moment sometime — I — become — a real-OP programmer, I think I have something to say:
Welcome traveler
If you have not spent the last 60 years on another planet (if so, welcome back, traveler), you must have heard about functional programming. If you follow modern trends in the software industry, you hear terms like “functional programming”, “immutability”, “pure functions” and “composition” every day. It all sounds cool, delightful and understandable until you think: “Hey, I’m an OOP programmer and I can’t (or don’t want) to change the paradigm. What can functional programming give me? Why should I bother? ”As an FP programmer / enthusiast who came from the world of the PLO, I want to share what I myself would like to know many years ago. We can talk about this for hours, so we’ll choose the three most important things.
Immutability
The traditional advantage of FP is the word, which usually takes at least two slides of each presentation on functional programming. Silver Bullet OP, right? Not really. Despite the fact that this word is most often used mainly by functional programmers, it is not exclusive to AF. As an OOP developer, you can achieve (almost) the same level of immutability as an OP developer. In fact, it is quite easy, just need to look a little differently at your objects and collections. Imagine that you do not change the original, but create a new version. Added item to collection? Fine! You did not change the original collection, instead you just have a new collection containing the added item. Changed the property of the object? Great! Now you have a new object with a changed property.
I know, I know - it sounds weird. But this small switch of consciousness will allow you to sleep more easily. As soon as you realize that your objects cannot be changed (only copied), you will be sure that no one in the team can reassign them to any other place. It's like borrowing your favorite, ancient Pink Floyd audiotape without fear of getting it back dubbed with Justin Bieber. And as a bonus, your code will have fully tracked methods in which real changes occur (where new objects are created based on the original ones). And, I almost forgot, if you are a C # or Java developer, you already use them by calling "ToLower ()", "Trim ()" on strings that are initially immutable. That is essentially nothing new.
Pure functions
Another fashionable phrase, mistakenly considered exclusively AF. What is a “pure function”? Simply put, a pure function is a function that returns the same result with the same input value, without being connected to the “outside world” (I / O operations, general condition, etc.), also known as “side effects”. A typical example of this type of function might be getting the length of a string (you won’t connect to the database to count the number of characters in a string?), Calculate the sine, and so on. What is the benefit of this for OOP? Same as for FP. If you work with pure functions (or methods), you know exactly what result you will get for each input value. And if your code does not depend on some hidden state, it is very easy to test it, and it will not bother you to write a unit test. We all know that without interaction with the outside world, our software would be useless, but there is a tangible difference between pure code (written in pure functions / methods) with input-output only at the system boundaries and a system in which each method depends on the internal state, updated by other methods.
Once again, a small rethinking of the approach to input-output gives all the advantages of AF, plus testing becomes how simple that will finally bring pleasure.
Declarative VS Imperative
We have already changed the point of view on our code - we can write more secure (immutable) and tested (clean) code. Now it is time to go a little further and change the approach to determining what our software should do. What else makes OOP different from FP? In the functional world, we define “what” should occur instead of “how” should occur. Of course, there remains a part of the program that performs that particular operation, but here it is important to concentrate on expressions instead of statements. And this is what you can do in your favorite OOP language.
For example, if you are familiar with such things as LINQ (from C #), you already know the advantages of query expressions, when you can read your code like “Aha, here I take 10 elements from the collection, sort them alphabetically and use as a parameter for the following method. " You must have read thousands of LINQ-like expressions without having to wonder what is actually going on behind the scenes. And the most important thing is to concentrate on what really matters.
Summary
I think this is enough for now. I do not want to eventually sell the OP as a silver bullet. The world is not only black and white. The truth is, for me, OP is incredibly difficult. Almost as difficult as proper OOP. But it is definitely worth a try. From my point of view, OOP vs OP is by and large how I think about the code and its structure. As I think about dependencies, side effects, the whole world of I / O and testing. To sum up with a single thought, “The functional approach will help, regardless of language, subject area and platform.”