Stop arguing about functional programming and OOP

Stop arguing about functional programming and OOP

The post contains some amount of banana, the Ministry of Health strongly urges an unprepared reader to refrain from reading.

Articles on the topic “FP is better” or “OOP is better” remind a debate, which is better for lunch, a fork or a spoon. Traditionally, the junas began with a spoon, but someone very reputable once said that he eats only meat and uses a fork, so a new fashion was born - eating with a fork. She eats and porridge, and soups, and even manage to smooth up smoothies. The Internet is littered with articles that we did well, that we learned to eat a smoothie with a fork and overcame all the rakes. This is both funny and sad, on the one hand it gives a competitive advantage to seasoned guys who show over-results just ignoring this hyip, on the other hand they have to retrain colleagues and employees, wiping garbage from their heads. In this article I will try to tell my vision, which does not claim to be absolute truth, but works very well in practice.

As is customary in science, let's start with definitions. The classic definition of OOP includes following the principles of inheritance, encapsulation and polymorphism. But if we do not have one of these components, will it be OOP? And if not, what will it be? As long as the boring part of the audience hovered over this impractical and not giving us anything to ask, remember what happened before the PLO . And before it was procedural programming. And the main idea of ​​OOP at that time was in data communications and functions for processing them . The idea is simple, but quite revolutionary, it's hard to imagine how much, but more on that later.

Functional programming, in free interpretation, regards a program as a mathematical formula . Formulas are well formalized and with the same input data they return the same output. The entire program consists of subroutines that follow the same principles. How is this different from the same procedural programming? The OP actively uses pure functions , ideally the entire program should be a pure function. Pure functions do not have side effects , they can be easily memorized, easy to test, etc ... It can be said that in pure functions the main idea and the advantage of AF is.

And now two questions:
  - Can we use pure functions in OOP?
  - Can we bind functions to the data in the OP?
The answer to both of them is affirmative. Static class methods can be clean, even instance methods can be considered clean if they do not create side effects and we consider the properties of a class instance as parameters. The boundaries of classical definitions swell up and someone may disagree, but in practice it just works. And such methods are formalized and tested no worse than the classical pure functions written according to all canons. About binding data to methods is a bit more complicated; the language and libraries used are limited. Say, in JavaScript it is done elementary, not sure about Haskell and Erlang. Now the most interesting thing is that it gives, and why has the OOP already raised such a hyip about 20-30 years ago. If you write a small program - you can write as you wish, except for your sense of beauty, this does not affect anything. When you create a really big program, the problem of complexity arises. Not computational complexity, we believe that we are doing everything well here, but perceived complexity. Let's say you have 50,000 lines of code, and they all make sense. How to organize them so as not to go crazy (or not to leave work at 11 at night)? We cannot reduce the number of operations, but we can reduce the number of links between them (encapsulation helps us in this). We hide the complex implementation behind a simple interface and continue to work only with the interface. For example, the Internet is a terribly complicated thing, but most developers have enough knowledge of the HTTP protocol to do their job and leave the network, physical, and other sysadmin levels .The weaker the connectivity of our modules, the less complexity at the stage of their integration with each other. The less one module knows about the other, the less they are connected. Binding methods to the data inside the module helps us to get rid of this knowledge among consumers of the module. This is the main pragmatic advantage of the PLO. Above what? Above approach without data binding and methods. OP, as we found out, does not mean this. You can pass classes as arguments to pure functions, or you can use pure functions as class methods, one does not contradict the other, but only complements.

In practice, where does one approach mostly work, and where is another mainly? When I write a backend in NodeJS, it somehow happens in the functional paradigm. Why? Because a request to a server is by its nature a function, with a fixed input and output. The functional approach falls on server requests very naturally and the code is smaller and more flexible. When I create a frontend for the browser - OOP is usually better, because besides the input and the output, we have a stream of user events , as well as program events, such as the beginning and end of animations, requests to the server, etc. ... The functional approach would work if it were necessary to simply render a static page without interactive, using the FP in the frontend suffers either interactive or development time (according to our measurements , times in 3). Why?

Any programming paradigm is based on a certain model of reality, and a model is always a simplification. In the OP model imposes more restrictions on the world, so it is easier to formalize. For the same reason, when it becomes irrelevant to the conditions of the task - it begins to require more crutches. For example, the FP on the frontend solved the problem of user input by creating an array of events (actions, hello redux). But this is an irrelevant abstraction, which, in addition to hitting performance, greatly increases development time. With this approach, you can create a todo list, but on really big projects you have to break bricks with your forehead, and then write winning articles for the same unfortunate. For comparison, when we wrote the stock terminal (on vanilla js, of course) from canvas, svg and updating several times a second via websockets, in some frequently updated components we did not delete divs, but reused, since their re-creation is relatively expensive operation in the browser (and this is important if you have a really big app ). If you are programming on the FP at the front, you will not even have such a thought, since you have already come to terms with immunity (by the way, the wonderful thing to work with multithreading, which in JS does not happen ), that every action goes through every redusser and other junk. On the other hand, on the backend it is often possible to do without classes at all, because there, you can avoid the cost of creating them, since the conditions of the tasks are very relevant to the FP model. But, for the most part, Java and PHP developers are just not in a hurry to study the AF, in the front ranks the front-enders who really need it the least. As an exercise for the mind, it’s interesting, of course, only the programs are obtained by g ... but, and for someone to use them. Given that the frontend is a relatively young section of IT, and its unresolved tasks there for several generations. What, it would seem, is not an exercise for the mind?

Source text: Stop arguing about functional programming and OOP