Lecture
Object-oriented programming is an extremely bad idea that could only come up in California.
- Edsger Wee Dijkstra
Object-oriented programs are offered as an alternative to the right ones.
Edsger W. Dijkstra , computer science pioneer
Object-oriented programming was created for one purpose - to manage the complexity of procedural code bases. In other words, this approach was supposed to improve the organization of the code. There is no objective and open evidence that OOP is better than simple procedural programming or functional or logical programming.
Object-oriented programming seems to be the standard, most common software design paradigm. It is he who is usually taught to students, explained in online tutorials and, for some reason, spontaneously applied even when they were not going to do it.
I know how attractive she is and how wonderful this idea seems to be on the surface. It took me many years to destroy her spell, and now I understand how terrible she is and why. Thanks to this point of view, I have a clear belief that people should be aware of the fallacy of OOP and know the solutions that can be used instead.
Recall what OOP is that is over 50 years old.
Timothy Budd writes:
Roger King argued insistently that his cat is object oriented. In addition to its other advantages, the cat demonstrates characteristic behavior, responds to messages, is endowed with inherited reactions, and controls its completely independent, internal state.
According to Alan Kay, the creator of the Smalltalk language, who is considered one of the "founding fathers" of the OOP, the object-oriented approach consists in the following set of basic principles (cited from the above-mentioned book by T. Budd).
- Everything is an object .
- Calculations are carried out by means of interaction (data exchange) between objects, in which one object requires that another object perform some action. Objects interact by sending and receiving messages. A message is a request to perform an action, supplemented by a set of arguments that may be needed when performing the action.
- Each object has an independent memory, which consists of other objects.
- Each object is a representative of a class that expresses the general properties of objects (such as integers or lists).
- The class defines the behavior (functionality) of the object. Thus, all objects that are instances of the same class can perform the same actions.
- Classes are organized into a single tree structure with a common root, called the inheritance hierarchy. The memory and behavior associated with instances of a particular class are automatically available to any class located below in the hierarchical tree.
Thus, a program is a collection of objects that have state and behavior . Objects interact through messages .
Many people have discussed OOP issues before, and at the end of this post I will list my favorite articles and videos. But first, I want to share my own view.
If you were the owner of the project, how would you rank (arrange) such concepts for your project?
For classic OOP there will be something like this sequence and importance
1st place e)
2nd place d)
3rd place c)
4th place b)
5th place a)
Take a look at this hierarchy (note, you can’t put a few concepts in one place), did you notice that when you blindly use OOP, you just spit on the very idea of the application and the customer? Now think about whether you need to blindly use OOP and is everything good with him?
We should not forget that all imperative programming languages and paradigms (including OOP) are more primitive compared to declarative programming (including Language-oriented programming, DSL-Based Development, domain-specific languages) Examples of languages and paradigms with a higher level and more modern are functional programming languages, SQL, a logical programming language, and even HTML and many times where the programmer does not forget how he will do it but orders what he wants and receives. Moreover, these paradigms should not be confused with the programming styles of the same name.
Figure 1 Comparison of imperative and declarative programming
At its core, all software is designed to manipulate data in order to achieve a certain result. The result determines how the data is structured, and the data structure determines the necessary code. But not the other way around. That is, it makes no sense to construct an infinite number of lines of code, an infinite number of classes. The more classes, the more complicated is the understanding of the entire architecture of an application, the decrease in its reliability, the complexity of testing, the appearance of more bows and the significant increase in the development time and execution time of such programs, since more resources are required to execute them.
Figure 2 Classification of programming paradigms
This point is very important, so I repeat: goal -> data architecture -> code. Here the order can not be changed in any case! When designing a program, you should always start by clarifying the goal that you want to achieve, and then at least roughly imagine the data architecture: the data structures and infrastructure necessary to achieve it effectively. And only after that you need to write code to work with such an architecture. If the goal changes over time, then you must first change the data architecture, and then the code.
In my experience, the most serious problem of OOP is that it motivates to ignore the architecture of the data model and apply the stupid pattern of saving everything to objectspromising some vague benefits. If this is suitable for the class, then it is sent to the class. Do I have a Customer? He goes to class Customer. Do I have a rendering context? It is sent to class RenderingContext.
Instead of building a good data architecture, the developer’s attention is shifted towards the invention of “good” classes, the relationships between them, taxonomies, inheritance hierarchies and so on. This is not just a futile exercise. In its depths, it is very harmful.
Table 1 Comparison of procedural, OOP and functional programming.
Basis For comparison | Pop | Oop | Functional programming |
---|---|---|---|
main | The procedure / structure is oriented. | Object oriented. | Functors and Monads |
An approach | Downward. | Bottom up. | denotational expression semantics and the use of graph reduction |
the basis | The main attention is paid to “how to complete the task”, that is, the task is divided into sub-tasks into functions, procedures. conditional statements can be used as if-else statements and a switch statement | Objects, methods, classes. The focus is on “data security”. Therefore, only objects are allowed access to class objects., Using loops for iterable data, the object is the basic unit of manipulation. conditional statements can be used as if-else statements and a switch statement |
variable, High-order functions, referential transparency , f (a) == f (b) if a == b. , pure functions, recursion for iterable data, function is the primary unit of manipulation. does not support conditional statements. |
separation | A large program is divided into blocks called functions. | The whole program is divided into objects. | instead of objects combining data with behavior, everything is separated separately into the data itself and its processors. Each handler is a function that accepts raw data and returns a result. |
performance | statements must be executed in a specific order. | statements must be executed in a specific order. | statements can be executed in any order. |
Object Access Mode | Access specifier is not observed. | Access specifiers: “open”, “closed”, “protected”. | no procedures |
Overload / Polymorphism | Neither overloads functions, nor operators. | It overloads functions, constructors, and operators. inversion of source code and runtime dependencies. | |
abstraction | basically supports data abstraction only | supports data abstraction and behavior abstraction | |
inheritance | no inheritance. | Inheritance is achieved in three public and protected regimes. | |
Data Hiding and Security | There is no right way to hide data, so data is not safe | Data is hidden in three modes: public, private and protected. hence data security is increased. however, object methods can have side effects | functions have no side effects |
Data exchange | Global data is distributed between functions in the program. | Data is distributed between objects through member functions. stateful programming model. condition exists. | no assignment operator, functions use immutable data, programming model without saving state, state does not exist
data → function1 → data → function2 → data → function3 → result, |
Friends Functions / Classes | There is no concept of a friend’s function. | Classes or functions can become friends of another class with the keyword “friend”. Note: the keyword "friend" is used only in C ++ |
There is no concept of a friend’s function. |
Virtual classes / functions | There is no concept of virtual classes. | The concept of a virtual function appears during inheritance. | There is no concept of virtual classes. |
Speed of execution, and resource consumption | very high | execution speed is very low, consuming large resources of memory and communication channels, not suitable for processing large data | high performance when processing big data |
Development speed | very low | high | low |
native support for parallel programming | not | there is | |
purpose, use and use | used to perform several operations that have common behavior and various options. | used to perform many different operations for which data is fixed. | |
example | C, VB, Fortran, Pascal, Assembler | C ++, JAVA, VB.NET, C # .NET. | F #, XSLT and XQuer, Haskell, Erlang, Lisp, R |
Of course, it is desirable to expand Table 1 by adding logical programming, SQL, and programming based on neural networks, programming based on qubits.
Despite some criticisms of the PLO, it is precisely this paradigm that is currently used in the vast majority of industrial projects. However, it cannot be considered that OOP is the best of programming techniques in all cases.
Criticism of the PLO:
Grady Butch points out the following reasons that lead to a decrease in program performance due to the use of object-oriented tools:
Dynamic method binding
Ensuring the polymorphic behavior of objects leads to the need to bind the methods called by the program (that is, determine which particular method will be called) not at the compilation stage, but in the program execution process, which takes extra time. At the same time, real dynamic linking is required for no more than 20% of calls, but some OOP languages use it constantly.
Significant depth of abstraction
OOP development often leads to the creation of “multilayer” applications, where the execution of the required action by an object is reduced to a lot of calls to lower-level objects. In such an application, there are a lot of method calls and method returns, which, of course, affects performance.
Inheritance Blurs Code
The code relating to the “final” classes of the inheritance hierarchy, which are usually used directly by the program, is found not only in these classes themselves, but also in their ancestor classes. Methods that belong to the same class are actually described in different classes. This leads to two unpleasant moments:
Encapsulation reduces data access speed
The ban on direct access to the fields of the class from the outside leads to the need to create and use access methods. Both writing, compiling, and executing access methods incur additional costs.
Dynamic creation and destruction of objects
Dynamically created objects, as a rule, are placed on the heap, which is less efficient than placing them on the stack and, especially, static allocation of memory for them at the compilation stage.
If you try to classify criticisms of OOP, you can highlight several aspects of criticism of this approach to programming.
OOP Advertising Criticism
The idea of object programming as a kind of omnipotent approach that magically eliminates the complexity of programming is criticized for explicitly expressed or implied in the works of some OOP propagandists, as well as in advertising materials of "object-oriented" development tools. As many noted, including the Brooks and Dijkstra mentioned above, “there is no silver bullet” - no matter what programming paradigm a developer adheres to, creating a non-trivial complex software system always involves a significant expenditure of intellectual resources and time. Of the most qualified specialists in the field of OOP, as a rule, no one denies the validity of criticism of this type.
Challenging development effectiveness using OOP methods
Critics dispute the thesis that the development of object-oriented programs requires less resources or leads to the creation of better software. The development costs are compared by different methods, on the basis of which it is concluded that OOP does not have advantages in this direction. Given the extreme complexity of objectively comparing different designs, such comparisons are at least controversial. On the other hand, it turns out that statements about the effectiveness of OOP are equally controversial.
Object Oriented Program Performance
It is indicated that a number of “innate features” of OOP technology make programs built on its basis technically less effective than similar non-objective programs. Without denying the really existing additional overhead costs for organizing the work of OOP programs (see the "Performance" section above), however, the significance of reduced productivity is often exaggerated by critics. In modern conditions, when the technical capabilities of computers are extremely large and constantly growing, for most applications, technical efficiency is less significant than functionality, development speed and maintainability. Only for a certain, very limited class of programs (embedded system software, device drivers, low-level part of system software,scientific software) performance remains a critical factor.
Criticism of individual technological solutions in OOP languages and libraries
This criticism is numerous, but it does not concern the OOP as such, but the acceptability and applicability in specific cases of certain implementations of its mechanisms. One of the favorite objects of criticism is the C ++ language, which is one of the most common industrial OOP languages.
Documenting classes is a resource-intensive task.
Dramatically increases the time to analyze and design systems
Increased lead time.
Code size increases
Ineffective in terms of memory (dead code is one that is not used)
The complexity of the distribution of work at the initial stage and when changing the architecture and functionality
Concurrency Issues The messy sharing of mutable state in OOP makes parallelizing such code virtually impossible. To solve this problem, complex mechanisms were invented: blocking threads, mutex, and many others. Such complex approaches have their drawbacks - deadlocks, lack of composability, plus debugging multi-threaded code is very complicated and time-consuming. We are not even talking about the increase in complexity caused by the use of such parallelism mechanisms.
When designing the data architecture explicitly, the result is usually the minimum required set of data structures that serve the purpose of our software. If you think in terms of abstract classes and objects , then the grandeur and complexity of abstractions from above is not limited to anything. Just take a look at FizzBuzz Enterprise Edition - such a simple task can be implemented in so many lines of code just because there is always room for new abstractions in OOP.
OOP advocates say abstraction testing is a matter of developer skill level. Maybe. But in practice, OOP programs always grow and never decrease, because OOP stimulates this.
Since OOP requires scattering information on many small encapsulated objects, the number of links to these objects is also growing explosively. OOP requires passing everywhere long lists of arguments or directly storing references to related objects for quick access to them.
Your class Customer has a link to class Order, and vice versa. class OrderManager contains links to all Order, and therefore indirectly to Customer. Everything tends to refer to everything else, because gradually more and more places appear in the code that refer to a related object.
You needed a banana, but you got a gorilla holding a banana and the whole jungle.
OOP projects usually do not look like well-designed data warehouses, but like huge spaghetti-graphs of objects pointing to each other, and methods that receive huge lists of arguments. When you start designing Context objects just to reduce the number of arguments passed back and forth, you realize that you are writing real OOP code at the Enterprise level.
Erlang is OOP in its purest form. Unlike most mainstream languages, it focuses on the main idea of OOP - messaging. In Erlang, objects interact by passing immutable messages to each other.
Is there any evidence that immutable messages are superior to method calls?
Sure! Erlang is arguably the most reliable language in the world. It supports the bulk of the global telecom infrastructure (hence, the Internet). Some systems written in Erlang are 99.9999999% reliable.
The vast majority of essential code does not work with just one object, but actually implements the tasks of cross sections. Example: when class Player hits using the hits () method of class Monster, where do you really need to change the data? The hp value of the Monster object should decrease by attackPower of the Player object; Player's xp should increase by Monster if Monster is killed. Should this happen in Player.hits (Monster m) or in Monster.isHitBy (Player p)? What if class Weapon needs to be considered here? Are we passing the argument to isHitBy or does Player have a getWater currentWeapon () getter?
This simplified example with just three interacting classes is already becoming a typical OOP nightmare. Simple data transformation turns into a bunch of clumsy intertwined methods that call each other, and the reason for this is only in the OOP dogma - encapsulation. If we add a bit of inheritance to this mixture, we get a good example of what stereotyped Enterprise-level software looks like.
OOP requires ordering data in an inflexible way: divide it into many logical objects, which determines the data architecture - a graph of objects with related behavior (methods). However, it is often useful to have different logical expressions for manipulating data.
If the program data, for example, is stored in a tabular, data-oriented form, then two or more modules can be created, each of which works with the same data structure, but in a different way. If the data is divided into objects with methods, then this is no longer possible.
This is also the main reason for the object-relational gap. Although the relational data structure is not always the best, it is usually flexible enough to work with it in various ways, using different paradigms. However, the rigidity of data organization in OOP causes incompatibility with any other data architecture.
The combination of data scattering over many small objects, the active use of indirection and pointers, and the lack of a proper data architecture lead to low execution speed. This justification is more than enough.
Often they simply created a universal system capable of solving supposedly any problem exclusively through DDD such as this -
Figure 3 One of the masterpieces of printing for the Bible on DDD
People, wake up! such a system can be drawn with any methodology, practice and concept in the center !!!
this is just a color picture with the letters DDD in the center!
Does this remind you of delusions with beautiful speeches and pictures with a geocentric system during the Middle Ages?
Figure 4 Illustration of the geocentric system of the world from the atlas of Andrei Zellarius Harmonia Macrocosmica (1708 g)
answering this question, you climb into an even bigger swamp in which some problems are replaced by others. Let's consider them in more detail.
If you read the books of Jimmy Nilsson. Applying Domain-Driven Design and Patterns: With Examples in C # and .NET.
then we can conclude that it was composed by a rather average programmer. Everything is basically such that even without this book it should be clear to the gopher's loving one, unless of course this gopher thinks about it. Not a single significant thought, or anything new, not a single original, or at least old, but rethought reasoning and inference.
In fact, in DDD books it comes down to developing not on the basis of a subject domain, but on the basis of a domain model. That is, they replaced the subject area with a model, or rather, not even with a model, but with cubes and arrows, and went according to the old scheme: we draw properties, methods, write code. Where is the subject area? Oh well, her, just a buzzword, you need to raise the circulation and the number of webiranas.
As for the concept of DDD itself, it actually comes down to a rather banal statement:
DDD - you need to develop programs based on the subject area.
Hello, come!
It turns out that there are still those (and there are many of them!) Who develop programs, games, systems without taking into account, or not based on the subject area?
And then what? On your ideas about how to program? Database-based, as the book says? (The author of it for a long time appears to have done so!). For a normal developer, this is absurd. Yes, and just do it, it sounds wildly for any specialist.
The funny thing is that this banal concept has seriously and for a fairly long time become “fashionable” in the programming world. Is this not a sign of stagnation? It turns out that programmers can be bullshit, there would be money. Recall how one man came up with the idea. The main thing is to gow and write well)
What do you think for whose services, books and in 45 minutes of simple verbal chatter you have to pay from $ 50 to $ 250 (nevertheless, every seventh in America is fond of this, every fifth in Europe)? AND?. The person who came up with such an income, his name is Sigmund Freud, and so, all the scribes trying to find solutions to the problems of the PLO, in the form of the holy grail,
and pleasing methodologies
It seems that advertising, unnecessary books, seminars and webinars for which there is not, has become the most powerful tool in the software.
But the main thing is not even that. The main thing is that the criticism, normal, sound, is practically invisible.
Do not be serious about any methodology - unfortunately there is often more self-promotion than content.
do not forget the two main principles of analysis - one of the rules of dialectics -
everything has advantages and disadvantages, that is, it cannot be ideal, and used alone.
and second
another 10th century Pierre Abelard said that
The starting point of any research is doubt , and the scientist's (rational person's) business is to, following the path of reason, go from doubt to truth. This is possible only with the consistent and correct application of dialectics (logic). The dialectical mind is the questioning mind, constantly searching, questioning even the statements of the Holy Scripture, but with the goal of a deeper understanding of it. The dialectical mind, rising above the ordinary human mind, seeks to approach the Divine Logos
the third
Remember that mathematical formulas are an analog of a code, and they are not patented. since there are multiple isomorphs because it makes no sense to inflate them, and therefore the amount of program code should be minimal to solve the whole logic. This can speed up the development time and increase the reliability and quality of the software and make it possible to earn more money for your client. If you are doing your project
Let's get married to our driven development and Nielson’s book. It should be viewed in much the same way as Fowler's “Patterns of Enterprise Application” (naturally, with a lower class, a thinner text, thicker delusions). If you read Fowler, then some of the patterns are not that outdated, but cause a feeling of secondary nature - "this is already in [substitute your favorite platform], why smear it?" There are awesome chances that the platform’s feature is secondary, but you’ve studied it before.
If you read Evans, you can see it is a great PR and popularizer, but with its own oddities.
As you wrote, the idea of a domain model for Evans is slightly secondary - back in seventies, the DBTG ANSI / SPARC shag was a conceptual level - the same “general model of everything”. True, then it was about the DBMS architecture, and not about the sacred cow of DDD business logic - it was not yet fashionable. Ehhh, what topic disappears - to trace the share of research where business logic is mentioned.))
In the same Evans book about DDD, he schizophrenically mixes 2 models:
- Domain as a model of a customer’s subject area
- and Domain as an OO model of a program’s domain
What is the difference? In the first version, we get a very interesting thing - a relatively formal description of the rules by which business logic is built. Secondly - BL is already on board with whores, blackjack and agile players - Evans passes them a couple of times in the spirit of "with some efforts DDD can still be used in agile-driven projects."
He clearly didn’t talk to code-as-model fans.
The first option is prettier for me precisely because of its simplicity - we have a common thing, loaded just enough to be supported and useful. And most importantly - this thing is absolutely independent of the wishes of the developer / customer. With sufficient adequacy, of course.
DDD shot (and even then not immediately - in which year DDD: Tackling complexity came out?) As the idea that Aguil is still alive and can generate new ideas - because "follow the commandments and find peace if not a project, then peace of mind" fed up. In this sense, yes, DDD is entirely conjuncture and does not carry anything of value in itself.
In general, expressions ending in “driven development” are already such programmer folklore.
Many who attend such DDD webinars or buy books do not have a computer science education, but they can beautifully speak and prove.
For example, they don’t know that there are many models for the database, for example, you can start designing with the conceptual form of the database, together with CRUD matrix + USe case and very active communication with the customer. In our world, it all starts with entities that are perfectly stored in relational or non-redirection tables, and in clear rules (simple and superpositional), and for this it makes no sense to create methods like -> getAllCategoriesByHousesAndCityesInCoutry () ...
Can you imagine how tough your code becomes, how much is superfluous and not flexible and not ugly in your system, do you imagine what will happen if the customer wants to do the same without logic in the logic?
But back to the OOP, what's wrong with him? In this spirit, I prepared a modest list of several things that I can not stand in the PLO.
What is the paradigm of object-oriented programming? Is there a direct answer to this? I have heard so many different versions that I myself don’t know now.
If we look at Smalltalk's ideas, we will come across the mantra: “Everything is an object.” In addition to variables. And packages. And primitives. Numbers and classes are also not entirely objects, and so on. Obviously, “everything is an object” cannot be the basis of a paradigm.
What is fundamental for OOP? Peter Wegner once suggested that object-oriented programming is based on objects, classes, and inheritance . However, each programming language supports them differently, or does not even support some of them by default. Clearly, this is not the OOP paradigm either.
Others assure that OOP isEncapsulation, Abstraction and Data Hiding . True, different sources will tell you that these are just different words to describe the same idea. And others will say that these are three fundamentally different concepts.
Since the mid-80s, several myths have been circulating about the PLO. One of them, the Reuse Myth , says that OOP makes development more productive, so it allows you to inherit and extend the current code instead of writing it again every time. Another, the Myth of Design, which implies that analysis, design and implementation smoothly follow from each other, because they are all objects . Of course, none of these myths can be the OOP paradigm.
OOP tries to model everything as a hierarchy of objects. But this is not so. Objects in the real world interact with each other through messages, but they are basically independent of each other. OOP inheritance does not reflect real-world inheritance. The parent cannot change the behavior of child objects at runtime. Even if you inherit your DNA from your parents, they cannot make changes to your DNA as they see fit. You do not inherit behavior from your parents. You develop your behavior. And you cannot redefine the behavior of your parents.
It is often mentioned that encapsulation is one of the greatest benefits of OOP. It is supposed to protect the internal state of the object from external access. But there is a small problem. This does not work. Encapsulation is the OOP Trojan horse. He promotes the idea of a common mutable state, making it seemingly safe. Encapsulation allows unsafe code to penetrate the code base (and even encourages it), causing it to rot from the inside. It is often said that the global state is the root of all ills and should be avoided at all costs. Encapsulation is essentially a global state. To make the code more efficient, objects are passed not by value, but by reference. This is where the "addiction" falls into the dirt face. Let me explain. Whenever an object is created, references to its dependencies are passed to the constructor.These dependencies also have their own internal state. A newly created object stores links to these dependencies in its internal state, and then modifies them in any way convenient for it. It also passes these links to everything else that it can ultimately use. This creates a complex graph of heterogeneous common objects that change each other's state. This, in turn, causes enormous problems. It becomes almost impossible to see what caused the change in the state of the program. Days may be wasted trying to debug such changes. And you're lucky if you don't have to deal with concurrency (more on this later).It also passes these links to everything else that it can ultimately use. This creates a complex graph of heterogeneous common objects that change each other's state. This, in turn, causes enormous problems. It becomes almost impossible to see what caused the change in the state of the program. Days may be wasted trying to debug such changes. And you're lucky if you don't have to deal with concurrency (more on this later).It also passes these links to everything else that it can ultimately use. This creates a complex graph of heterogeneous common objects that change each other's state. This, in turn, causes enormous problems. It becomes almost impossible to see what caused the change in the state of the program. Days may be wasted trying to debug such changes. And you're lucky if you don't have to deal with concurrency (more on this later).if you don’t have to deal with concurrency (more on this later).if you don’t have to deal with concurrency (more on this later).
I think that the inability to reuse affects object-oriented rather than functional languages. Since the problem with OOP languages is that they have all this implicit environment that they carry with them. You wanted a banana, but you got a gorilla with a banana and the whole jungle to boot.
Joe Armstrong , creator of Erlang
Inheritance has nothing to do with the real world. It is the worst way to achieve code reuse. The gang of four explicitly recommended giving preference to composition over inheritance, and some modern programming languages generally avoid it.
There are several problems with inheritance:
The diamond problem in class inheritance
Sooner or later, the next problem generates an ugly and, depending on the language, unsolvable puzzle.
Figure 5 Diamond-brilliant problem of OOP in class inheritance
Most OO languages do not support this, although this seems logical. What is so difficult to support in OO languages?
Ok, imagine the following pseudo code:
Note that both the Scanner class and the Printer class implement a function called start .
So what startup function does the Copier class inherit ? Is the scanner alone? Is there one printer ? It cannot be both.
The solution to the diamond (brilliant) problem. The solution is simple. Do not do this. Yes that's right. Most OO languages do not allow you to do this.
But, but ... what if I need to model this? I want my reuse!
Then you should contain and delegate (Contain and Delegate) .
Note that the Copier class now contains an instance of Printer and Scanner . He delegates the function of starting the implementation of the Printer class . It can also be easily transferred to the scanner .
This problem is another crack in the Inheritance column.
Polymorphism is great, it allows you to change the behavior of the program at runtime. This is a very basic concept in computer programming. I'm not very sure why in the PLO they pay so much attention to him. He does his job, but once again leads to mental juggling. This makes the code base much more complex. Analyzing the specific method that is being called becomes very difficult.
Functional programming allows you to achieve the same polymorphism in a much more elegant way - simply by passing a function that defines the desired behavior at runtime. What could be easier than that? No need to define a bunch of overloaded abstract virtual methods in multiple files (and interface).
As discussed earlier, encapsulation is the OOP Trojan horse. This is actually a global mutable state that makes unsafe code look safe. Unsafe code writing practices are the foundation that OOP programmers rely on in their daily work.
Schizophrenic encapsulation of objects. Let's take a look at the definition of encapsulation:
Encapsulation is a concept of OOP that connects data and functions for manipulating this data, which helps protect them from external interference and misuse. Encapsulating data has led to the concept of data hiding, which is important for OOP.
The intention is good, but in practice, encapsulation with the fragmentation of an object or class often leads to the fact that the code tries to separate everything from everything else (from itself). This creates a huge amount of boilerplate: getters, setters, numerous designers, strange methods, and all of them are trying to protect us from errors that are too unlikely to occur on such a modest scale. You can use this metaphor: I hook a padlock on my left pocket so that my right hand cannot take anything from it.
Don't get me wrong - imposing restrictions, especially in the case of ADT, is usually a good idea. But in OOP with all these cross-references of objects, encapsulation often does not achieve anything useful, and it is quite difficult to take into account the limitations scattered across many classes.
In my opinion, classes and objects are too fractional, and in terms of isolation, API, etc. it is better to work within “modules” / “components” / “libraries”. And in my experience, it is in the OOP (Java / Scala) code bases that modules / libraries are not used. The developers are focused on building fences around each class, without really thinking about which groups of classes together form a separate, reusable, integrated logical unit.
OOP abstraction is trying to solve complexity by hiding unnecessary details from the programmer. Theoretically, this should allow the developer to analyze the code base without thinking about hidden complexity.
Fancy word for a simple concept. In procedural / functional languages, you can simply “hide” implementation details in a neighboring file. There is no need to call this basic act “abstraction”.
Let's look at other paradigms that allow you to solve programming problems in a certain way. Procedural programming is often described as programs = data + algorithms . Logical programming states: programs = facts + rules . Functional programming, most likely, programs = functions + functions . Which suggests that OOP means programs = objects + messages. Is it so? I think that the main thing is lost here. And most importantly, OOP is not a paradigm, such as procedural, logical, or functional programming. Instead, OOP says, “for each individual task, you must develop your own paradigm.” In other words, the paradigm of object-oriented design is: “Programming is modeling.”
I also don’t like the way everyone likes to dislike other languages. We love to divide the world into camps: braces versus square versus round.
Here are some of the things that have been said about our beloved NWFS:
“C makes it easy to shoot yourself in the leg; with C ++, it’s harder to do, but when you do this, you shoot your entire leg off. ”
This was said by Björn Straustrup, so everything is fine.
“I coined the term 'object oriented,' and here's what I tell you: I didn't mean C ++.” - Alan Kay.
I am very sorry that I coined the term “objects” a long time ago because they make many people focus on a less important idea. The main idea is messaging. Alan Kay
продолжение следует...
Часть 1 Disadvantages of OOP, DDD (Domain-driven design) and patterns. OOP Alternative
Часть 2 An alternative to OOP or what approach to use instead
Да если Рисунок 3 повернуть на 80 градусов против часовой стрелки то реально)) внизу грешные люди, пользователи, а вверху божества и ангелы, сверхвозможностями
Comments
To leave a comment
Object oriented programming
Terms: Object oriented programming