Disadvantages of OOP, DDD (Domain-driven design) and patterns. OOP Alternative

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).

  1. Everything is an object .
  2. 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.
  3. Each object has an independent memory, which consists of other objects.
  4. Each object is a representative of a class that expresses the general properties of objects (such as integers or lists).
  5. The class defines the behavior (functionality) of the object. Thus, all objects that are instances of the same class can perform the same actions.
  6. 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.

Data is more important than code

If you were the owner of the project, how would you rank (arrange) such concepts for your project?

  • a) the maximum compliance of the functional (features) specified in the specification (technical specifications) and the expectations of marketers
  • b) maximum reliability and minimum bugs
  • c) deceit; good extensibility of the application in the future, but with damage in terms of time in development (deceiving - because constant refactoring is required)
  • d) maximum atomization of code into classes, interfaces, domain methods
  • e) maximum academic literacy when applying various design techniques (OOP, functional, DDD), the use of patterns

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.

Disadvantages of OOP, DDD (Domain-driven design) and patterns. OOP Alternative

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.

Disadvantages of OOP, DDD (Domain-driven design) and patterns. OOP Alternative

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:

  • It was shown that there is no significant difference in the productivity of software development between the OOP and the procedural approach [ Thomas E. Potok, Mladen Vouk, Andy Rindos. Productivity Analysis of Object-Oriented Software Developed in a Commercial Environment // Software - Practice and Experience. - 1999. - Vol. 29, no. 10. - P. 833-847.].
  • Christopher Date points to the impossibility of comparing OOP and other technologies, largely due to the lack of a rigorous and universally accepted definition of OOP [CJ Date, Introduction to Database Systems, 6th-ed., Page 650].
  • Alexander Stepanov in one of his interviews pointed out that OOP is “methodologically wrong” and that “... OOP is almost the same hoax as artificial intelligence ...” [STLport: An Interview with A. Stepanov].
  • Frederick Brooks points out that the most difficult part of creating software is “... the specification, design and testing of conceptual designs, and not the job of expressing these conceptual designs ...”. OOP (along with technologies such as artificial intelligence, program verification, automatic programming, graphical programming, expert systems, etc.), in his opinion, is not a “silver bullet”, which could reduce the complexity of developing software systems by an order of magnitude. According to Brooks, “... OOP only reduces the added complexity of design expression. Design remains intricate in nature ... ”
  • Edsger Dijkstra pointed out: “... what society asks for in most cases is an elixir for all diseases. Naturally, elixir has very impressive names, otherwise it will be very difficult to sell something: Structural Analysis and Design, Software Engineering, Maturity Models, Management Information Systems, Integrated Environments project support "," Object Orientation "," Business Process Reengineering "...".
  • Niklaus Wirth believes that OOP is nothing more than a trivial superstructure over structural programming, and an exaggeration of its significance, expressed, inter alia, in including more and more fashionable “object-oriented” tools in programming languages, harms the quality of the software being developed.
  • Patrick Killelia in his book “Web Server Tuning” wrote: “... OOP provides you with many ways to slow down your programs ...”.
  • A well-known overview article of problems of modern OOP programming lists some typical problems of OOP
  • In programmer folklore, criticism of the object-oriented approach has become widespread in comparison with the functional approach using the metaphor of the “ Kingdom of Nouns ” from Steve Yeggi's essay.

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:

  • The speed of translation is reduced, since the linker has to upload descriptions of all classes of the hierarchy.
  • The performance of the program in a system with page memory is reduced - since the methods of one class are physically located in different places in the code, far from each other, when fragments of the program are actively accessing inherited methods, the system is forced to make frequent page switching.

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.

Disadvantages of Object Oriented Design and Programming

  1. Documenting classes is a resource-intensive task.

  2. Dramatically increases the time to analyze and design systems

  3. Increased lead time.

  4. Inefficiency at runtime.
  5. Code size increases

  6. Ineffective in terms of memory (dead code is one that is not used)

  7. The complexity of the distribution of work at the initial stage and when changing the architecture and functionality

  8. In complex class hierarchies, fields and methods are usually inherited from different levels. And it is not always easy to determine which fields and methods actually belong to this class. To obtain this information, special tools are needed, such as class navigators.
  9. Methods are usually shorter than procedures, but there are many more. Short methods are easier to understand, but they are inconvenient in that the code for processing a message is sometimes “spread out” by many small methods
  10. You need to understand basic concepts such as classes, inheritance, and dynamic binding.
  11. Reusable use requires a programmer to become familiar with large class libraries.
  12. Designing classes is a much more complicated task than using them. It is very difficult to study classes without being able to "touch" them.
  13. OOP generates huge class hierarchies, which leads to the fact that the functionality spreads or, as they say, is blurred by the base and derived members of the class, and it becomes difficult to track the logic of one or another method.
  14. In some languages, all data is an object, including elementary types, and this cannot but lead to additional costs of memory and processor time.
  15. Also, the implementation speed of polymorphism, which is based on the mechanisms of late binding of a method call to its specific implementation in one of the derived classes, can adversely affect the speed of program execution.
  16. The psychological aspect. Many people consider OOP to be cool and start using its approaches always and everywhere and indiscriminately. All this leads to a decrease in the productivity of programs in particular and the discrediting of OOP as a whole.
  17. Documenting classes is a more difficult task than it was with procedures and modules. Since any method can be overridden, the documentation should not only talk about what the method does, but also in what context it is called.
  18. In complex class hierarchies, fields and methods are usually inherited from different levels. It is not always easy to determine which fields and methods actually belong to a given class. If a class expands, then each method is usually abbreviated before passing the message to the base class. The implementation of the operation, therefore, is scattered across several classes, and to understand how it works, you have to carefully review the entire code.
  19. Methods, as a rule, are shorter than procedures, since they carry out only one operation on the data, but there are much more of them. Short methods are easier to understand, but they are inconvenient in that the code for processing a message is sometimes “spread out” by many small methods.
  20. Encapsulating data should not be abused. The more logic and data hidden in the bowels of a class, the more difficult it is to extend it. The starting point here should not be that clients are not allowed to know about any data, but that clients do not need to know this class to work with the data.
  21. Decreased program performance associated with the use of virtual methods;
  22. OOP ideas are not easy to understand and especially for practical use;
  23. Effective use of existing OO systems requires a large amount of initial knowledge and skills.
  24. Data encapsulation abuse. The more logic and data hidden in the bowels of a class, the more difficult it is to extend it.
  25. Inefficiency at runtime, incl. data encapsulation.
  26. Inefficiency in the sense of memory allocation. Excessive versatility
  27. Significant impact of limitations and conventions of programming languages ​​(primarily C ++ and Java)
  28. Orientation of OOD (object-oriented design) to the simplest implementation of the object model
  29. Inability in many cases to comply with one’s own principles
  30. As a result, the need to use a large number of point solutions, such as GOF-patterns
  31. 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.

  32. Lots of code . Programmers are so used to OOP that they write all the tasks on it. Take the same user registration we know. To do this, they write a class, in it properties, a constructor, a function that contains the code for processing the form and writing user data to the database. Then an instance of the class is created, and a function is called through it. Below we show the solutions to this problem on OOP, and the track is the hands of a programmer.
  33. A lot of action . No matter how you try to write a cleaner script using OOP, Patterns, Fremvorki, the interpreter has to perform a lot of unnecessary operations, while overheads increase significantly.
  34. The interpretation time of a project on OOP using a pattern and frameworks is hundreds of times more than a project on pure code, but of course, clean code must also be used reasonably. The more actions - the more time is needed to complete and process them. This is affected by the volume of scripts, and the number of actions, because the server will spend time loading a heavy OOP file into RAM, parsing and execution. All the latest versions of ready-made CMS and frameworks use PDO to connect to the database. If you go deeper, you can find out that in time one connection to a third-party database is equal to the processing time of the project in pure code.
  35. Ineffective in terms of server RAM. RAM on the OOP server “eats up” hundreds (the simplest project on OOP), or even thousands of times more (the framework, and the more CMS) compared to the project on pure code. Yes, this is exactly what all hosting companies profit from, and those who provide cloud services such as Amazon AWZ, etc.
  36. Unused unnecessary code . Any project written in OOP has partially and by messenger code. I’ll give an example of the OOP class of the sales repository, in which there are such functions: get all sellers, get a specific seller, get sellers by filter ... If you need to show a specific seller, the method responsible for this will work, while other methods will be inactive, which is very bad.
  37. The OOP approach makes code confusing . Any CMS-system, framework, design template is so confused and has great connectivity and engagement that you can grow like a monkey, trying to parse every line of code that it is responsible for.
  38. OOP is unsafe because 95% of programmers use ready-made patterns, vendors, frameworks, and even more so CMS, and they are all widely distributed on the open Internet. then it will not be difficult for a hacker to find a “hole” in the code and hack.

Projects that lose in competition or go out of business or close after using OOP

  1. Windows Internet Explorer (application of proprietary standards, slow work compared to commonly used assembler in Webkit) using C ++
  2. Windows versus linux
  3. Large social. networks such as Facebook - a decrease in runtime performance despite the tictonic efforts to optimize the code.
  4. Any projects abusing pure OOP, and not using other methods and paradigms

Motivation for difficulty


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.

Counts are everywhere


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.

B a true OOP

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.

Cross Cut Tasks


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.

You can look at the same data in different ways.


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.

Low performance


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 -

Disadvantages of OOP, DDD (Domain-driven design) and patterns. OOP Alternative

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?

Disadvantages of OOP, DDD (Domain-driven design) and patterns. OOP Alternative

Figure 4 Illustration of the geocentric system of the world from the atlas of Andrei Zellarius Harmonia Macrocosmica (1708 g)

What are the solutions to OOP problems?

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.

Criticism of DDD advertising, its shortcomings and other heresies

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,

  • GOF patterns (Design Patterns: Elements of Reusable Object-Oriented Software, 10 - $ 100 for Amazon
  • antipatterns
  • Patterns of Enterprise Application Architecture (Martin Fowler) $ 200 Amazon
  • SOLID ( Single . Open, Liskov, Interface, Dependency ), Martin, Robert (Uncle Bob). Getting a SOLID start. Principles Of OOD
  • “Over” -SOLID, OverSOLID (Anti-SRP • Anti-OCP • Anti-LCP • Anti-ISP • Anti-DIP)
  • KISS ( keep it simple, stupid ),
  • DRY (Don't repeat yourself),
  • YAGNI ( You Aren't Going to Need It )
  • GRASP (General Responsibility Assignment Software Patterns),
  • DDD ( Domain Driven Development ), Eric Evans $ 170 Amazon
  • TDD - Test Driven Development
  • TDD - Type Driven Development
  • BDD - Behavior Driven Development
  • FDD - Features Driven Development
  • MDD - Model Driven Development
  • MDA -Model Driven Architecture
  • PDD - Panic Driven Development

and pleasing methodologies

  • YKDM (Yaiken-Kruten Driven Development),
  • ZDM (Zeitnot Driven Development), that is, “now we spit on all the paradigms and finish it faster, until the bosses hang by the balls”,
  • ADD (Asshole Driven Development)
  • Cognitive Dissonance development - Development of cognitive dissonance (CDD),
  • Cover Your Ass Engineering (CYAE, Cover Your Ass with Engineering),
  • Development By Denial - Development by Denial (DBD),
  • Get Me Promoted Methodology - Advance Me Methodology (GMPM)

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.

1. Critique of the OOP paradigm


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:

  • a large amount of code is added that your class does not even need (a problem with the banana and the jungle);
  • defining parts of your class elsewhere makes code analysis more difficult, especially with multiple levels of inheritance;
  • in most languages, multiple inheritance is not even possible; this basically makes inheritance useless as a mechanism for code sharing.

The diamond problem in class inheritance

Sooner or later, the next problem generates an ugly and, depending on the language, unsolvable puzzle.

Disadvantages of OOP, DDD (Domain-driven design) and patterns. OOP Alternative

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:

Disadvantages of OOP, DDD (Domain-driven design) and patterns. OOP Alternative

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) .

Disadvantages of OOP, DDD (Domain-driven design) and patterns. OOP Alternative

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

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).

Encapsulation

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.

Abstraction

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.”

2. Criticism of object-oriented programming languages


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

avatar
24.5.2020 19:56

Да если Рисунок 3 повернуть на 80 градусов против часовой стрелки то реально)) внизу грешные люди, пользователи, а вверху божества и ангелы, сверхвозможностями


Comments


To leave a comment
If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
To reply

Object oriented programming

Terms: Object oriented programming