What are the limitations of the object-oriented paradigm?

Asked

Viewed 1,710 times

14

My experience is more with the object-oriented paradigm. Ok, "if all you have is a hammer, all the problems look like nails".

And I say: it’s a complicated paradigm, full of good practices, S.O.L.I.D., design principles, design patterns, code Smells and a mental model that, if on the one hand reduces the representational gap between the problem and the solution, on the other, requires time, study and experience to learn how to model this solution according to what the paradigm asks for and in order to obtain the benefits it proposes. From "objects are a natural way of thinking" he has nothing. Not in the medium long term at least when problems of design begin to appear.

It is a powerful weapon with the risk of getting shot in the foot. It is used perhaps for lack of something better, but I understand when they say it is mainstream too much. Maybe because of marketing. But it was a highly researched paradigm and I don’t believe that so many people are wrong about it being beneficial for a large number of uses.

One can say that the problem lies in the developer who does not invest time in dominating the paradigm. I don’t know if other paradigms suffer from the same problem, or if the problem is the discipline of design itself that is complicated in general, or conflicts with the deadlines projects when evaluating a design, or both.

But the OO paradigm itself receives some criticism. In Wikipedia most come from proponents/creators of functional languages. I don’t know the arguments, but this suggests a sardine pull to this paradigm (I am not saying that there is a dichotomy there, only that the arguments run the risk of being biased and there is no advantage in defending a paradigm that has no prospect of supplanting another - is, at least in this aspect there is a dichotomy).

My question is: as if these criticisms (or perhaps should pay more attention to them) were not enough, are there others that the OO programmer needs to be aware of? What are the weaknesses of OO?

  • 1

    Computationally there is no limit. So is functional or even Turing machine-based. There is limitation on maintenance and readability, however

  • 1

    @Jeffersonquesado Being the languages underneath all Turing-complete, in fact there is not. But do you mean that other paradigms are easier to maintain and more readable? Can you elaborate?

  • 1

    I agree with most of you, I disagree mainly with Mas foi um paradigma muito pesquisado e não acredito que tanta gente se engane em ele ser benéfico para um grande número de usos.. People are using things the wrong way (the human being loves to deceive himself, he does it all the time, essentially everyone). It is useful some number of cases. And it has not been so studied, and where it has often shown that it is not all this wonder. If it were well studied people would agree on its definition. Neither do they know. So which OO are you talking about? :)

  • @Maniero I’m talking about the Java OO, but they all have complexity when it comes to designing, don’t they? Or an OO design principle does not apply to another particular OO?

  • Piovezan, unfortunately I cannot elaborate much = I have informal experience on the subject, very opinionated things or else I can’t even express my intuition on the subject in words

  • @Maniero e onde foi muitas vezes mostra que ele não é essa maravilha toda. Could you draw up that part?

  • @Maniero researched and saw that OO failed to reuse large-scale commercial components although I can’t tell if this was the original paradigm proposal. In addition there seems to be a lack of empirical evidence in its effectiveness, some say that yes, others who nay and nay. With these remarks I think it kills the subject.

  • @Piovezan I’m writing a reply.

  • 1

    @Jeffersonquesado I’m only going to give opinion :P, based on my experience.

  • @Piovezan This story that OO fails to reuse large-scale commercial components seems to me to stem more from social, administrative and organizational problems than from technical ones. There is difficulty in reuse mainly because many people program anyway to put out fire, whether for lack of competence, time, resource or whatever, and possibility of reuse ends up being in the background. Moreover, in many companies that develop software, departments and teams often turn into fiefdoms that share little code with others.

  • @Victorstafusa This is an idea that you would no longer need to write code, which would simply buy ready-made components made by third parties. I had until the time of J2EE, if I’m not mistaken I have an old Java magazine that quotes this. From hitting your eye at the idea I see that would not avenge, there is always something that needs to be customized, can not apply the general case at all. Library reuse works at best.

  • @Piovezan This reuse component market was a marketable idea propagated by EJB2 proponents and never came close to materializing. She’s overly optimistic and simplistic for forgetting the obvious factor that software is complex and undergoes changes and that business rules are highly specific and not at all generic, and that’s independent of the paradigm. Something that is slowly supplying this idea is the use of webservices/Apis either via SOAP, REST or whatever. However, starting something like this to say that OO failed to provide this reuse is a tremendous exaggeration.

Show 7 more comments

3 answers

14

It can produce useful information here, but our mechanism does not help people understand that this information is not canonical and universal, which reflects some bias

First let’s agree on who uses object orientation. Let’s not talk about that pseudo programmer who doesn’t understand anything about OO, maybe even programming in general and some even basic mathematics and can’t even calculate a percentage, much less know how to interpret a text or problem, they can’t put together the parts of what they’re doing, look for information in a structured way, analyze it and conclude something on their own. Because these people probably won’t even read this page, or know what to do with it.

Unfortunately I think by the 90% of the people who program fall into this category, because it’s broad and it takes from the guy who should be banned from selling hot dogs on the corner, to the one who manages to deliver projects that work and to some extent are right, but still understand only vaguely what they are doing.

I don’t think there are many people who understand what OOP is, probably not even who created the term (I explain below). And obviously I’m not saying that I understand. People who categorically state that her definition is the right one should suffer from the Dunning-Kruger effect, which is different from being assertive about what she believes is right.

I’m sorry if anyone feels offended, my intention was just to put a basis of what happens on the market to justify why we got to this point, I don’t want to offend anyone, and if you felt that way, think about if you can change something because you saw it fit you, or suffer from impostor syndrome or should take the opportunity to evolve and change category. I think that people actively participating here and almost everyone who passively participates are among the not offended, or unconsciously think they are "impostors".

I’m not talking about anyone specific!

Unfortunately these days we have to do all this Disclaimer.

I will say what I agree and disagree with Victor’s excellent answer and the question and adopt a different point of view, because the question is dubious about what kind of problems she is talking about.

was a very researched paradigm and I do not believe that so many people mistake it be beneficial for a large number of uses

It wasn’t much researched, seriously, and what happens most in the world is people make mistakes, they do this all the time, they love to cheat, everyone, some more than others, at one point or another. Why do you think politicians are so bad, but they still hold power? Why does the bulk of what we consume have something bad and yet nothing changes? Why do rich people spend their fortunes on things that have little or nothing added to it other than the fact that it’s expensive? And I’m gonna stop right here so I don’t get too rough :)

requires time, study and experience to learn to model

Yes, to model, to learn the mechanisms is not that complicated. But of course the guy who does not want to learn everything well will not achieve anything. But then the problem is another, he also does not know that can’t use double for money, cannot accept inputs without positively validating, one CPF is a description, can’t thresh or ask a question on the internet, anyway, the problem is below.

objects are a natural way of thinking

Yes, for those who think :P Okay, seriously now it is difficult to establish limits of the object and that has nothing to do with what Victor answered, thinking OOP is the hard part.

I’m talking about the Java OO, but they all have complexity when it comes to designing, don’t they? Or an OO design principle does not apply to another particular OO?

Java doesn’t have an OO, it has OO mechanisms, but the project can be done by following some schools. Java has static typing that forces certain mechanisms to function in a way. Victor covers most aspects well. Java uses a series of mechanisms that have nothing to do with OOP, and people don’t even notice.

Opacity of polymorphic abstractions

Corroborate the jsbueno that there seems to be scrutiny of the implementation of language and not of the object orientation paradigm. More specifically, at least in part, you are talking about the difficulty with typing.

Recalling that in dynamic typing languages the functions are naturally polymorphic (although not all are written like this, in static typing language also not).

To me this whole section is talking about the difficulty imposed on static typing when using polymorphism (not necessarily OOP).

The difficulty in using is a little bit if you are not using an IDE. But I don’t think the OOP problem is there, OOP precisely helps the IDE better inform the code structure.

What I always say is that people don’t understand what OOP is. She doesn’t have this difficulty because it’s common for her to neither use it, especially in the right way. Most create classes and think it’s OOP. But for the "real programmer" I agree that you have this difficulty cited.

I think that affects readability code. Everything you need context to know what will happen is less readable. I pointed out why it is common for proponents of OOP to defend legibility tooth and nail, which I even agree, I just disagree that OOP helps in this. Victor’s argument shows that it’s more complicated to know what that is.

Some may say that this affects even is intelligibility. Whatever. And in consequence the manutibility.

People who advocate OOP often sell the idea that programming gets easier and this is not true. It gives the impression that you abstract and encapsulate everything and it’s all simple. Hiding concreteness has its drawbacks. I love abstractions, but when used in excess only puts more cognitive load and hides relevant points. I know some people will defend that with philosophy. I love philosophy, but when it comes to doing the project it needs to be with rice and beans (I know you’ll get it wrong, but whatever).

People complicate too much what can and should be simple.

Simulating polymorphism in a structured language

With branches (if, switch, etc.) you do polymorphism, not just simulate it. Not in the way people usually refer to polymorphism, it’s true. The problem is the same.

There’s nothing wrong with doing that unless you have a reason not to. Maintenance can complicate if you need to add behaviors, this form leaves no cohesion. But it is not any project or any specific problem that needs this whole cohesion. Cohesion has harms as well. I am not advocating the use of this mechanism, just making it clear that it has utility and not use it where it should is as bad as using it where it should not. I see a lot of mistaken use because one only sees traditional polymorphism as correct.

The use of pointer to function has even more to do with functional programming.

These concepts are more concrete, which is always easier to understand.

OOP abstracts the mechanism and makes it more difficult to understand what is occurring. Even if the person says no, even for himself, it is common for the person to see it as magic.

É mágica

Double-Dispatch

I agree and find one of the biggest problems of the whole mechanism. Enough to disqualify the use where it should not.

It’s too abstract an example for me to say, but it’s very common for this problem to arise when you try to model something that doesn’t actually exist, when you try to use OOP where it doesn’t fit, maybe a relationship would be more appropriate.

Often it goes unnoticed

My perception is that this occurs too much in the use of OOP.

Here comes the problem I talk about, the person is so blind to using OOP for everything she can ignore that has easier ways to solve the problem. The relational model is usually easier for people to understand. I don’t know why, it needs to have a Pedagogy.SE para gente perguntar perguntar.

If I’m not mistaken fix this, but pay a price.

Multiple inheritance of implementation

I see this as an implementation problem, which is simpler in dynamic languages.

I’ve discussed this several times with a lot of people, a lot of the OOP complaint is actually about static typing.

There are several ways to have multiple inheritance. Some languages do this too generically (C++ cof cof), others may restrict too much, and it is rare, if any, languages that have everything you need to function (abstract classes, interfaces, traits, mixins, roles, protocols, delegations, extensions, attributes (I’m not talking about fields), etc..).

In fact people don’t quite understand what to inherit, when to put things together, what is a mechanism and what is a business rule, what is the business limit of that object, how it can or cannot be extended, why not extend what could because of optimization, Just to name a few things. People don’t understand ontology and taxonomy. Not that this is irrelevant in other paradigms, but in OO is quite important.

The project starts well, with time it begins to be a lot of gambiarra, because one did not classify and named things right. Ah, but there’s the miracle Refactoring. Um, it seems to me that these people have only worked on small, short-term projects or that they are very statically defined. I know who talks about these things and has worked on dozens of times more projects than me in a third of the time I have profession. I don’t know if they understand what it’s like to keep a big project long-term. There’s no time to take care of hundreds of projects when you have one this complicated. And to solve this there are people complicating the projects even more, but if you follow the standard recipe you’ve done before, everything is solved and it seems that the person works a lot, productivity measured in Klocs.

I’ve seen people have to change the system almost completely because of this. This is OOP?

The problem I see is that it is difficult to define what is what. Of course you need to understand the mechanism as well. The point is that if you know what you’re doing well, you can make good use of other paradigms like modular, which is simpler and more organized.

OOP doesn’t make people create good projects magically, OOP is just the tool. Just because you have water, a refrigerator and a saw doesn’t mean you can do this:

Escultura de gelo

Simple inheritance of implementation

I agree 100%, especially the last sentence of the first paragraph. And this is a relational and modular model and not OO.

Much of the problems we deal with today have been created because they have started to make inheritance where they should not, and in many cases should not. Unfortunately people don’t see it, they don’t understand what problems it will have in the future by having this coupling.

And guess why it’s often no problem? Because the problem was too simple and/or static, and OOP was not needed there.

Crosscutting-Concerns

It is a limitation of OOP and other paradigms. The functional handles it better with its own limitations, metaprogramming in its various forms as well, as the modular but less because it ends up being a middle ground, but it has a problem, it is worse defined than OOP.

aspect-oriented programming was not well accepted because it has a strong negative side as well: it causes the code to acquire in it behaviors that are not expressed there and that are encoded far from the point where they are executed, without there being any clear indication for such a fact

OOP too and was very well accepted.

But it is a fact that it does not deal well with the modeling of the real world. That is why some people nowadays deny that this was the goal of the paradigm, even being full of material from the past saying this. So what is the advantage of using OO? Reuse? There are those who deny too. And can only reuse well if you do not try to make objects that take care of everything.

This is the biggest limitation of the paradigm, taxonomy needs to be perfect to work well, but this is difficult or impossible.

Focus on objects and not on actions

There it says that the languages that said OO have surrendered to the functional. They are neither one thing nor the other, only allow something in this line. Essentially these languages are imperative.

People focus on actions and it seems hard to understand that this is not OO. OO is data structure.

Inextensibility of classes

There are several solutions to this. In fact I believe that this limitation is not OOP, as far as I know pure OOP requires that classes should be extended. But there must be controversy about this.

However, the mix-in still has a downside, which is to be a behavior assigned to an object that does not appear in the code of the class corresponding to that object, being located outside the class where it is applied (and possibly somewhere far away from it and quite difficult to be determined).

This is a criticism I make, proponents of OOP tend to destroy cohesion by wanting to put everything together that is separate. The procedural/modular/functional tends to allow these compositions in a much simpler way, greatly facilitating maintenance and simplifying creation. The error charges you much less when everything is more granular.

In dynamic languages this is often much simpler, even in OOP.

There was presented a limitation of Java. Although the existing solution in other languages is also not well oriented to object.

Dependency injection

I agree. And this complication is something that most people don’t quite understand, and they don’t know when to stop doing this. It’s very common to violate KISS and YAGNI to be "OOP".

There are some questions there that are very difficult to answer. In fact almost everything, when modeling objects is difficult. The worst is that people learn that the answers to this are wrong recipes. They teach in bad abstract examples and people fail to apply in the real context properly.

They often say do DI to facilitate the test. Then you will see the tests and are a heap of bad engineering, testing the obvious and leaving aside what matters because the person does not understand the difficulties that it will have with that object. That’s why TDD doesn’t work. And the unit test done afterwards only solves regressions... if the project remains firm in its initial philosophy of quality, which is rare in long projects that are not products for other developers to use (even these are not always so).

Greater complexity than other paradigms

I agree with everything before Bullets. Too bad people don’t understand that OOP is modeling.

Few people reach the level of using OOP well, and many think they have (I’m not talking about aloprados). I didn’t arrive after 30 years doing this because I don’t do the same project every time. Once again, you learn to do better when you’ve made a mistake on a number of projects. Whoever did several projects, due to their size, probably worked on things that OOP was not so useful. There are exceptions.

Making a form using the classes in your GUI is not object-oriented programming, it is using the object-oriented programmed. The same for MVC and others frameworks. And yes, the greatest utility of OOP is to build frameworks. My experience in business systems is that almost always it has less utility than people imagine.

Already looking for studies that indicate that OOP has these qualities that propalam and did not find. This proves nothing, unless you have no proof that OOP is so much better. It’s all perception. Mine is the one I just said above.

Done wrong, and this includes using OOP where it shouldn’t, no value delivery.

  • Some people complicate the code just so they don’t break the rule that says switch is the devil’s work.

  • I’ll wait to see if Victor can tell me what’s wrong with PessoaJuridica extends Pessoa. I think normal, almost all inheritance should be on top of abstract class, interface or something, there serves only as taxonomy and/ or reuse. I find it strange Cliente extends PessoaJuridica that triggers cohesion.

  • In fact "pure" OOP does not like primitives. That’s why I think OOP is bad, it’s academic and not engineer stuff that uses what is most suitable for the problem.

  • In OOP what I see most is the use of Copycat.

The fact is that OOP is taught all wrong, and it has become almost impossible to teach right, because "no one" agrees with what OOP is. This further diminishes its usefulness, making it difficult to communicate. And the biggest mistake is teaching that OOP solves everything very well and ignore other paradigms.

Extra complexity in the representation of abstract concepts

So it seems to be more of a critique of abstraction. It’s a problem when you say you can only do it in an abstract way. Modeling things that change is complicated. Not complicating what can be easily changed is more difficult to see, then one goes in the default and complicates everything.

Note that all products used by us devs uses OOP to some extent and goes into concrete where it is best.

Of course, everyone can have the opinion that this is not a valid criticism, I validate it, until the day they prove to me that it is not valid.

Object-oriented programming has inferior performance

The problem is not the mechanism, is the model. If you exaggerate you get problems yes. If you need the maximum performance is something else. Functional has problems too. When performance matters, other paradigms can be more useful. Metaprogramming can help in abstraction at no cost. It is common for OOP to end up hiding complexities that only turn slow too late. Sure, it’s design mistake, but OOP helps to have it.

The problem with Object-oriented Languages is they’ve got all this implicit Environment that they carry Around with them. You Wanted a banana but what you got was a Gorilla holding the banana and the entire Jungle.

-- Joe Armstrong

Over specification without generic types

Curious that a good OOP modeling is to make use of genericity and not OOP. It is an OOP problem in static typing. And OOP (not all definitions) preaches inheritance and not genericity.

Lack of a canonical definition of object-oriented

If each one understands in a way is a complicated paradigm to follow. It’s hard for people to understand each other in projects, first you have to learn what the team’s OOP is, and today the team can be the world.

If people don’t even know what OOP is, it’s hard to use and evolve in the paradigm. Every hour you are influenced by something different, you don’t know if what you are taught applies to the by-product you are using. This is one of the biggest problems of the paradigm. A lot of the mistakes made in it are because of this.

The described pillars is what I think, but the creator of the term does not think so, although he himself has already said (or almost so :) that should have called that message guidance or server-oriented and says that chose the term mistakenly.

I have been wondering about what encapsulation and abstraction is, I have the impression that I have always misunderstood, and a lot of people too, so they teach wrong and everyone learns wrong. I publish something the day I’m right (I started doing it).

Some people say almost the opposite of these things, so it’s a problem. It’s hard to know if you’re doing it right if there’s someone who tells you to put everything in class, and who tells each class to do just one thing.

Victor objected in comments on his answer that inheritance is something inherent in OO. I live doing these things, it’s complicated to deal with something ill-defined.

If it only has one of the three pillars, is it OOP? Some people say yes and say it’s encapsulation, and I think it might be, considering that this is just bringing it all together in class. The only one that is exclusive to OOP is the inheritance.

Interestingly, it has a dynamic typing language that has subtype inheritance, I’m not going to name names, but it starts and ends with P :P :D

Anemic model

It is a modular model that makes maintenance much easier. There are people who have no problem with cramming everything into one class, or don’t see it as a problem, even if it is, or make relatively static systems, as I said above.

It doesn’t matter if it’s anemic or not, sole responsibility matters. In other paradigms it’s easier to have it, some are automatic. Hitting the "size" of the class is very difficult. And is worth everything you said throughout the text.

100% OOP encourages rape DRY, and there’s a strong movement towards this lately. People are going crazy :)

Cohesiveness it’s not about putting it all together, it’s about putting together what needs to be together. Not even talking about classes. Being cohesive is important, being encapsulated to the extreme not.

Cohesion depends on context. How to model this in OO? Simple, making modular/functional or even procedural. A lot of people do, but think they are doing OO (remember, I’m not talking about noobs).

Since we don’t even know the definition of OOP, we don’t know the details of what is cohesive for OOP. What I know is that cohesion is fundamental, and this has existed in computing for over 50 years, before OOP and before the term software engineering existed. I’m talking about the term using in our area, in others it’s secular, or millennial, I don’t know, ask ptlang..

Spreading things without discretion and putting everything together without discretion are equally bad.

Difficulty writing a compiler

Yeah, it doesn’t matter.

It is only good to make clear that more modern languages (Rust, Go, Erlang, etc.) are not adopting OOP explicitly, do not encourage it, and the older ones are moving a little away from the paradigm, even if they deny it. This is true for Java, C# and mainly C++. The languages that bet everything on the paradigm were not successful. Alias Alan Kay thinks Lisp is the best language there is and she’s not OOP, she doesn’t have anything people say about OOP :)

Other problems

Has problems with competition. No room to detail.

The biggest problem is the difficulty in modeling, it’s not so much OOP. It’s that OOP requires doing right. When asked about learning OOP for Alan Kay, he replied with a book that does not teach programming. I always talk, the problem is that people can’t sort things out, and that’s fundamental in OOP. So it brings together different things. And we deal with problems we don’t know, or we’re repeating what we’ve done before, which is not a very noble task.

I just don’t like the book statement so much because almost nothing we program works like biology. It gets the wrong idea. Hence comes a lot of bad example of how to model OO.

If people are bad at ontology, something that makes them good at it is a invitation to disaster.

It is only easy to understand a code written well O if it was you who wrote or is in a language very well dominated by the team.

OO inhibits creativity, because it has to follow certain patterns to make everything work. OO works better to do recurring things. I won’t even talk about DDD that is OO in the worst form (the idea of DDD is good, the implementation adopted is one of the most terrible things I’ve seen in computing).

SOLID is an interesting case. Is he or is he not OOP? If you follow everything correctly you will be doing modular/functional programming and nothing in it is unique to OOP, in fact some OOP things are not in SOLID. The impression I have is that he’s opposed to OO. If this is true, and of course I think it is, it would be another case that needs to get out of the purity of the paradigm to get what it wants. And you need to know all this.

The Difference between people who like OOP Languages and These people are that These people are Pioneers who are Actually solving Huge problems in computing; whereas the designers, supporters, and implementers of OOP Languages Waste all their efforts on Aesthetics or trying to Prevent a strawman Idiot from Doing idiotic Things.

-- Joe Armstrong

Item 4 of the last objection is the most important.

If you search for OOP, OOD or word that indicates the same thing along with flaw, sucks, evil, bad, problem, misuse, and similar things will find a lot of stuff, most make sense.

Completion

I think there’s a lot of evaluation of implementations, of languages and not of the paradigm in Victor’s response. Apparently the answer indicates that it does not matter to be OOP, it is a language that is said OOP can do everything even through other paradigms. I may have misunderstood. But it is a fact that this indicates that pure OOP does not work.

OOP does not solve all problems and adds new ones. In its pure form it requires doing very impractical things and inefficient codes. It requires things that most people are not qualified to do and done wrong it causes more problems. Whoever created the term also thinks that problems are too complex and need an understanding that people do not have, and they cannot be solved in isolation how people want it. I understand that he knows that OOP is not all this, the problem is the people who think it is.

There are two groups of people: those who are distancing themselves* of OOP (or have already been distant) even if they do not realize it, and those who are sticking themselves in the paradigm hole more and more. The good news is that if you have this kind of attitude most of the problems we take care of don’t cause a lot of difficulty nowadays, because the problems are too small and too static to cause.

*Distancing isn’t abandoning, it’s using where you need it.

It’s the biggest problem we have in our area, and it’s getting worse: something very good is created and it serves 1% of the problems, maybe 10%, but people want to use it for 100% of them.

Phrases from excellent programmers (almost everyone) who do or have done important things by hitting OOP, at least the way people use it. They seem empty sentences, but if you look you will find the context where they were said and almost all have concrete arguments behind the phrase.

Read the comments of the question, AP found more interesting things.

I like the GRASP, not everything, but the basic idea, because if you do all those things, you run away from the central idea of O. At least it’s just a guide line and it says that you should do what needs to be done to achieve a general goal. It doesn’t mean much, but it’s better to have "rules" that need to follow purely because otherwise you’re a cunt.

If you follow all the rules you have invented and keep inventing (OO has new rules almost every day :) it can work. If you follow a series of rules in other paradigms you also have a great chance of working, often more, only these rules were not disseminated, perhaps because they were created before the computation "explode".

As a curious note is to see the irony of Rob Pike, the creator of UTF-8 and this part is important in this sentence, saying that OO is the same as Roman numbers.

Object-oriented Programming is popular in big Companies, because it Suits the way they write software. At big Companies, software tends to be Written by large (and Frequently Changing) Teams of mediocre programmers.

-- Paul Graham (the whole text is interesting)

It is not OOP that is Broken - we just Haven’t Figured out (after over 40 years) how best to develop with it

--Oscar Nierstrasz

  • I hit the 30000 characters for the first time. The other problems I’ll have to see how I’ll finish, I just started some ideas :)

  • 1

    The part about "refactoring the entire system" reminded me a response from the Programmer Master: https://answall.com/a/185404/64969

  • Another trick answer :) It is even difficult to know which answer to accept. In relation to the limit of 30K characters would not give a second answer? I’m just sorry I know so little about dynamic languages, part of the discussion is lost to me. I accept language suggestions to learn that help understand the problems raised.

  • 1

    As to the PessoaJuridica extends Pessoa it is because PessoaJuridica is a term that materializes in the real world usually as Empresa, which leads to Empresa extends Pessoa. At the very least, it’s a poor choice of nomenclature, but it’s almost always something far beyond, a very bad modeling. Outside Brazil and Portuguese-speaking countries, I’ve never seen or heard of anyone doing Company extends Person and PhysicalPerson extends Person. That is, it is a peculiarly curious term of the Tupiniquim juridiquês that ends up contaminating the modeling of the system.

  • In addition, it will take me a while to digest your reply and think of some kind of replica or what I can edit in my response to it.

  • 1

    @Victorstafusa I think an ontology problem, I prefer Personal juridical because that is what this entity is. Company is a subset of legal entity that can only be defined by an auxiliary information, not always available or relevant. That is, for me it is a rich choice, within my experience taking care of Erps. I don’t know everything how it works outside of Brazil, and my English is scarce to affirm something, but for me Company is Company and Organization is our Legal Person. The fact that people do so, wrong, is not a good justification to do the same.

  • 2

    The term is not our invention: https://en.wikipedia.org/wiki/Legal_person, but this is topic pro ptlang.SE.

  • @Maniero The problem is not having an entity PessoaJuridica, is to get PessoaJuridica and PessoaFisica have a superclass in common because they’re supposed to look alike. In general they are things so different that either the subclasses inherit a lot of things that should not or else you have a superclass so empty that serves little and in this case the best would be to use an interface (interface that is the type that denotes to whom you can send an invoice, for example), this assuming that you have static typing obviously and nothing like Duck Typing.

  • Anyway the question of nomenclature is the least here. Usually the problem is much greater when inducing the programmer to use inheritance where it should not only because of nomenclature.

  • The idea of the interface is good, even if it is not one, it has to be an abstract class. I see no problem in it being poor if it serves the purpose. I also don’t think it’s fundamental to have this, but it seems very useful in most cases (I’m always talking about general problems, there are specific cases that may be better to do otherwise). The question of the name and its classification that I speak is precisely because defined wrong induces to organize wrong and there is used inheritance where it should not, separates what is together and joins what is something else. Organize right and name wrong is reasonable.

  • Well, I personally can’t deny or reject the idea that there is a brasiless which is usually confused with orthodox (or not) patterns of development. Regardless of OO, or whatever the popular or academic paradoxism is fact that Brazil exists a system peculiarity (well) legacies that were made practically shaped in the processes that companies developed and evolved, that is to say, I don’t like to mix discussions about nomenclature of classes, functions, tables, etc, because otherwise I leave exact science to a holistic science ...

  • @Maniero How does C++ rank? Is it also a language with OO elements like Java? What would be object-oriented languages other than Smalltalk?

  • @Piovezan yes, and there are even those who question whether it is OO. Smaltalk is even, but not purely, as a secondary paradigm has no way of being only OO. There are some Smalltalk descendants, maybe Self and Cecil are the best examples of maintaining a similar philosophy. Alan Kay says that Lisp is very OO, but it’s because she can undergo a metamorphosis and it could be anything. C++ comes from Simula that tends to give more value to static typing and the low cost of abstraction, Smalltalk preaches flexibility, whatever it takes. It’s easier to OO on Smalltalk, but it’s hard to program right on it.

  • @Victorstafusa present for you: https://answall.com/q/279342/101 Besides thinking that OOP cures cancer, they think that Generics AIDS cure. I was responding he erased.

  • It seems to me to be just another elaborate question by someone who doesn’t quite know what he’s doing.

  • @Maniero "That has nothing to do with what Victor said, this is the hard part" - what’s the hard part? "Victor’s argument shows that it’s more complicated to know what that is" "that" would be the opaque code? "The people who defend OOP (...)" of this paragraph I could only take away that "abstractions should be used sparingly, the rest became very vague. "maybe a relationship would be more appropriate" as well as relationship? "The relational model" we are talking about database?

  • @Maniero "I agree 100%, especially the last sentence" which sentence? "And this is a relational and modular model and not object-oriented" refers to Car and Vehicle modeling? "People focus on actions and it seems hard to understand that this is not OOP." I don’t understand. "Ali has some questions (...)" vacant whole paragraph. Although I do not understand DI, who knows better understand when understand the magic.

  • @Maniero "Then you’ll see the tests (...)" I didn’t understand the phrase, I didn’t really understand the relationship between DI and test design. But also, I don’t master unit tests. "I agree with everything up to the Bullets" this includes or excludes Bullets? "Too bad people don’t understand that" What, modeling is hard? "Copycat" I meant copy/Paste? "Extra complexity in the representation of abstract concepts" vague section, I could only conclude that not always make the abstract form is better.

  • @Maniero "It is a problem of OOP in static typing" comment: genericity should be a "OOP pull" in static typing, recommending the application in the relevant cases :) "The people who have no problem" would be "There are people"? "Oo works best to do repetitive things" what kind of things? "In its pure form" What would be pure OO, "everything is objects"? "that kind of attitude" what attitude, use only where you need? (finished!)

  • @Piovezan Thinking OOP is different from thinking naturally, this is difficult. " That" is is the object, what it will do can have various forms, be different objects, it is still a little opacity. I don’t have room to be less vague. That is, the question is wide :) You understood what matters the rest is almost same rambling :D And we are talking about the relational model (more or less), but not the database, the model is not unique to DB.

  • @Maniero Missing number the doubts. By comment: 1 to 5; 6 to 9; 10 to 14; 15 to 19. Perhaps it is easier to answer by numbering them.

  • Ult phrase was left without context even:"It happens that even simple inheritance introduces problems". This, the modeling presented, and I don’t know if I agree with everything of the modeling, but it depends on the case, is what I said, it is not always easy to define the problem correctly. People care about the algorithm and not the data structure that is most important, OOP is data structure, zero algorithm. See all interrogations in the DI section of Victor. Fit a chapter of his book just to clarify this.

  • People say without DI it’s hard to test. And they preach tests as a solution to everything, but they do horrible tests just to say they did it (but they think they’re stifling). Excludes Bullets. They don’t understand that modeling is OOP and this is hard, they think class is OOP. Copycat is imitation, google it. Speaking of abstraction is almost a chapter as well. Remember opacity. It is good to some extent, bad when it passes the point. Your conclusion is right. Your doubt has become vague :P

  • It is virtually impossible to have effectively static typing without Generics, ñ has nothing to do with c/OOP. in dynamic typing OOP does not need Generics because it is a mechanism to solve typing. The "There" would be better there now, but I got lost in the middle and was going to finish the paragraph, then I reviewed it. OOP "is modeling", and you only model well what you have modeled before, you already know what mistakes, so it works better when you solve the same types of problems. Pure OOP is when it does not adopt other mechanisms to help what the paradigm is not good...

  • ... And this idea of everything having to be an object is one of the troublemakers, the languages can’t even make everything actually be an object. Bad attitude of getting into OOP with everything as if it solved everything. END. In fact it would have gotten better c/ a numbering, here it will be confused as well. This is why I thought the question should be closed. This works best on forum even though today I find that well done is useful anywhere.

  • @Maniero "100% OOP encourages DRY violation" what exactly are you talking about?

  • @Piovezan If you keep putting everything in the object as the paradigm (at least as some say) fatally you will have repetition of code. Who proposes OOP thinks that can not have anything outside the class, that can not have static class and those things are daring to make composition. Then violates the code DRY and violates the data DRY, because often the same real object happens to have more than one representation within the system when it assumes different roles, case type Pessoa that is Cliente and Fornecedor to the same. Who usually does OOP has 2 objects that are the same person.

Show 22 more comments

11

The object-oriented programming paradigm imposes some difficulties. They may or may not be overcome to a greater or lesser degree. The following list is by no means exhaustive, but should serve to answer this question.

Real criticisms that I consider valid

Here I list some things that I consider typical problems in object-oriented programming languages that can be disadvantages.

Opacity of polymorphic abstractions

The object-oriented programming paradigm is significantly more complex than the structural/procedural one because now functions and procedures are replaced by possibly polymorphic and even abstract methods. This polymorphism no longer allows the function/procedure invoked here to be determined precisely in advance, so that it will only become known at runtime. This can make the analysis and understanding of programs more complicated.

In a procedural/structured programme when a function xpto is invoked, it is known exactly in a static way where she is and you can then quickly look at her code. That is, in this case, abstraction is transparent, because you can easily locate and inspect its content. In object-oriented, no. The calls to methods in object-oriented programming can be abstract and polymorphic, being determined only at runtime, and therefore being opaque, i.e., not able to be quickly located and inspected.

This is something that tends to disturb OO beginners who get that thing of not knowing exactly what method they are calling, since there can be multiple implementations. It can complicate when you’re looking at the code, looking for some bug or trying to understand some code behavior and falls into an abstract method and you don’t know where to find its implementation or even which of the various implementations is the one that matters.

Simulating polymorphism in a structured language

Programs written in procedural programming languages do not usually attempt to explicitly use polymorphism. However, the need for polymorphism exists when we see that function salvar that has a type parameter int where 1 is a file, 2 is a socket, 3 is a pipe, etc. or where instead of just having a function salvar, we have the function salvarNoArquivo, salvarNoSocket, salvarNoPipe, etc..

It is possible to simulate polymorphism in procedural programming through the use of function pointers or through functions that have a if or switch gigantic within to choose the proper implementation. However, it should be noted that in doing this, one is actually doing a gambit in order to simulate a different paradigm than the one that language imposes.

In the case of a procedural language, the use of function pointer-based polymorphism, if done in a standardized and well-organized way ends up producing a design pattern capable of simulating the polymorphism of object-oriented languages (even, this is exactly how they are implemented in practice). But they use very atypical constructions and with structures very different from those that would be the natural ones for the language. That is, the gambiarra becomes a pattern of project promoting something that is not natural to be expressed in the language in question.

When doing this in a procedural language, the opacity of the object oriented arises and it is no longer possible to know statically which function will be called since what we have is a function pointer whose value is only known at runtime (or even if it is/was a value to be used a switchvery big). The structure of the resulting program has an extra complexity that only serves to simulate object orientation in the procedural program, a complexity that would disappear if the language were object oriented, but without the opacity of the corresponding abstractions disappearing. This demonstrates that this opacity is not in fact something that procedural programming is immune to, but something that arises when polymorphism is added to it.

Double-Dispatch

That from here is the opposite of the previous item, is insufficient abstraction. Polymorphic calls use the object they refer to as a context in which they perform in order to provide a polymorphic dimension. It happens that not always a single dimension is sufficient.

For example, imagine that we have several types of robots that inspect various types of cars and that each robot-car combination occurs in a different way:

  • In the structured paradigm, either we would have a function/procedure for each robot-car combination or we would have a single gigantic function/procedure with a zillion ifs and switches to separate these cases all.

  • In object-oriented programming, we can put the method visita(Carro) in class Robo and choose the type of car within each implementation or else put the method receberVisita(Robo) in class Carro and choose the type of robot within it. Neither of these two approaches is ideal because whichever one is chosen, you choose whether polymorphism is based on the Robo or in the Carro, but not both of us.

  • In the ideal paradigm, given a combination of Carro and Robo, when invoking the method visitar, the ideal polymorphic implementation would already be chosen.

The name of it is double-Dispatch, because the implementation to be executed depends on the type of two objects instead of just one (single-Dispatch).

There are some techniques to try to circumvent this problem in object-oriented languages, such as using the design pattern Visitor, introspection or Reflection techniques or use tables containing dozens of objects that represent each of the possible different implementations, these being defined by an interface. However, in this case you are already trying to simulate a different paradigm using constructs that are not natural to the language in question, in the same way that occurs when simulating polymorphism in structured programming. The result again is a good amount of code and complexity to manage it that would be dispensed with if the language in question already had this feature built in.

Often this goes unnoticed, but it occurs sometimes when we have that decision whether we create in the class A a lot of methods to deal with all different types of B or we create ourselves in the class B a lot of different methods to deal with all different types of A, or we end up creating objects that relate different types of A with different types of B in order to choose what to do with them. All these things would be denicessary in a language that already had the double-Dispatch naturally.

Multiple inheritance of implementation

One thing that has been considered a major problem in object-oriented programming languages is the inheritance of multiple implementations.

The first languages to go down this path allowed for multiple inheritance of implementation. Programs resulting from the use of multiple inheritance tend to be confusing and difficult to understand. The main problem that arises is the diamond problem:

 class A:
     void x()
         print('a')

 class B extends A:
     void x()
         print('b')

 class C extends A:
     void x()
         print('c')

 class D extends B, C:
     void y()
         x()

Note that the method y() class D invokes the method x which has been inherited. It is unclear whether the inherited method of C or the method inherited from B. Some languages try to solve by imposing an order of inheritance precedence, but it can create problems:

  • A method of B may end up calling a method of C on the same object where B is not subclass of C and neither C is subclass of B.

  • When there are several inherited methods, defining the correct order of the superclasses can be difficult. There are cases where the correct order can vary in different contexts of the same class implying that there are cases where no order is correct.

Another problem is in relation to casts. In many object-oriented languages, objects are organized in memory by placing members of the superclass first followed by members of the subclass. That way, by doing the cast of a subclass memory address for the superclass, the resulting address would be the same. In a cast from the subclass to the superclass as well, the address is the same. However, when there is more than one superclass, this trick no longer works and it is necessary to make address corrections in casts, which brings a lot of complications and causes the same object to have more than one memory address or to have an organization in memory significantly more complex.

Simple inheritance of implementation

Many object-oriented languages have abolished multiple implementation inheritance and only allowed simple inheritance with at most one superclass. It turns out even simple inheritance introduces problems.

Analyzing and understanding a superclass code can be difficult, as it is an incomplete code to be finished or overwritten by the subclass. A subclass is also something incomplete, because it is strongly coupled to its superclass. That is, inheritance introduces a type of strong coupling. For this reason, subclasses are especially fragile if the superclasses change. In particular, it is often the case that the behavior of the subclass depends on the implementation details of the superclass, breaking even in the face of internal details changes.

Inheritance can almost always be replaced by composition. An object in memory is composed of several fields that correspond to other objects (or primitive/built-in values). For example, a class object Veiculo would be represented by a sequence of data placa, proprietário, tipo-de-combustível. An object of the type Carro (subclass of Veiculo) would be represented by placa, proprietário, tipo-de-combustível, cor, modelo, marca. Note that this is almost the equivalent of making the subclass structure Veiculo, cor, modelo, marca. That is, when using composition in the place of inheritance, a structure with the same data is reached, but the subclass is more flexible as to what it can encapsulate the superclass and how.

Crosscutting-Concerns

One thing that tends to get in the way of object-oriented programs is the following case: Imagine you have a method that saves an employee’s registration. He would ideally be something like this:

void salvar(Funcionario f) {
    Arquivo a = ...;
    a.escrever(f.cpf);
    a.escrever(f.nome);
    a.escrever(f.salario);
}

But, it turns out that you still have to deal with concepts like logging, transactions, error handling, among others, and the code turns into this:

void salvar(Funcionario f) {
    Logger.trace("Salvando o funcionário " + f.id);
    Arquivo a = null;
    Transacao tx = Transacao.abrir();
    try {
        Arquivo a = ...;
        a.escrever(f.cpf);
        a.escrever(f.nome);
        a.escrever(f.salario);
        tx.commit();
        Logger.trace("Salvou o funcionário " + f.id);
    } catch (ErroDeIO x) {
        Logger.error("Erro ao salvar o funcionário " + f.id, x);
        tx.rollback();
    } finally {
        a.close();
    }
}

This introduces a lot of additional and accidental complexity to the program. In addition, all these logging, transaction, error handling features (called crosscutting-Concerns) are scattered and copied-and-dusted in a lot of different places for everything that is side in the code. When some detail regarding transaction management has to change, it will require extensive modifications to various parts of the code.

There are several attempts to solve this in object-oriented programming languages, but they all end up leaving at least some line of code, some command or some annotation behind in the code that still equates to crosscutting-Concern, and the ideal is that there was none of that in the code, but that it was still there at runtime.

It was with this in mind that the aspect-oriented programming that separates the code from the crosscutting-Concerns of the code where it is applied. However, aspect-oriented programming was not well accepted because it has a strong negative side as well: it causes the code to acquire in it behaviors that are not expressed there and that are encoded far from the point where they are executed, without there being any clear indication for such a fact. It’s hard or even impossible to look at a code and know what the crosscutting-Concerns which apply to it and whether they are being managed correctly.

Focus on objects and not on actions

This is a criticism of object-oriented languages by proponents of functional languages. In functional languages you have Lambdas which is like anonymous methods, pieces of code that you can pass as parameter to methods.

This gives to simulate in more purely object-oriented programming languages without much difficulty, but it has a cost: it produces an explosion in the number of classes and interfaces and a significant complexity to encode them. This has been mitigated in the more modern object-oriented programming languages that incorporate the concepts of Ambdas natively, making them hybrid between object-oriented and functional.

Inextensibility of classes

Everyone has already gone through a case where you want to add any method in an existing class, but there is no way to do this because such a class cannot be modified. It is from this limitation that classes like StringUtils, DateUtils and XptoUtils of life will come to life. These classes are due to the fact that there is a need to extend classes that for some reason cannot be modified.

The solution to this is in the concept of mix-ins, which consists of adding methods to existing classes, things that languages like Javascript and Ruby allow easily and that can not be done (at least not in an easy way and without gambiarras) in languages like Java and C#. However, the mix-in still has a downside, which is to be a behavior assigned to an object that does not appear in the code of the class corresponding to that object, being located outside the class where it is applied (and possibly somewhere far away from it and quite difficult to be determined).

For example, let’s assume you want to add a method to invert a string. In Javascript, which supports mix-ins, this is easy:

String.prototype.reverse = function() {
    let r = "";
    for (let x = 0; x < this.length; x++) {
        r = this.charAt(x) + r;
    }
    return r;
}

var teste = "abcd";
document.write(teste.reverse());

Note that the above code uses teste.reverse() instead of reverse(teste). That’s because the method* reverse was injected into the class* string.

*: In Javascript there are no classes and methods themselves, but the way it implements functions with scope capture and prototypes of objects serve to simulate these concepts well.

However, if we try to do the same in Java:

 public class StringUtils {
     public static String reverse(String in) {
         return new StringBuilder(in).reverse().toString();
     }
 }

public class Main {
    public static void main(String[] args) {
        String teste = "abcd";
        System.out.println(StringUtils.reverse(teste));
    }
}

Note that instead of using teste.reverse(), we have to use reverse(teste), reverting the code structure to a typical procedural programming structure. We cannot use teste.reverse() because we can’t change the class String nor inject an external method into it.

The resulting class StringUtils does not represent a concept of object orientation, because instances of this class do not make sense and it only serves to group methods that we wanted to be elsewhere.

Dependency injection

Several objects, in order to perform their work, must be able to locate their dependencies, that is, other objects with which they must collaborate.

Getting the right objects to know each other can be quite laborious, as it can involve very complicated object creation processes or very difficult constructors to use. From this comes a lot of creative design patterns such as the Builder and the Factory, that although they are patterns of projects, can also be seen in a negative way as gambiarras invented to circumvent language limitations.

A possible solution to this is the injection of dependencies, where the object To declares that it needs an instance of B to operate and when To was created, B is delivered to him from somehow somewhat magic (that often ends up turning into a framework of addiction injections or in a Service Locator).

In addition, there is the problem of the egg and the chicken. The object "egg" should create the object "chicken" or the object "chicken" should create the object "egg"? The DAO creates the Connection or the Connection creates the DAO? This problem becomes easier to solve with injection of dependencies, where the framework responsible for it takes care to discover the best order to create such objects. If the injection of dependencies can be lazy (i.e., made on demand only at the time it is needed), even if the objects To and B depend on each other, they can be created separately and will only know each other when they need each other.

Note that all these dependency injection approaches again add quite complexity to a project that will benefit from it. Again, we fall into the case where too much complexity is added to circumvent programming language or paradigm limitations of this.

Greater complexity than other paradigms

Understanding and knowing how to properly use the object-oriented programming paradigm is in fact much more difficult than doing this with the procedural paradigm. It is one thing to understand the concept of what a method, constructor, class, instance, inheritance, polymorphism, etc. It is quite another to know how to use it effectively and intelligently.

The design of a well-made object-oriented program is difficult to do, and sometimes it ends up being easier and faster to opt for a program with a more simplistic structure. Sometimes this more simplistic structure is a procedural model with little object orientation such as a anemic model (I explain more about him below).

It is very common in everyday life to have tight deadlines and insufficient training and experience, which causes structurally more deficient projects. In fact, this fact occurs in any programming language with any paradigm and with any software development methodology, but it affects more those that are more difficult to learn correctly, such as the object-oriented paradigm.

When this barrier is overcome and the programmer starts to use object orientation properly, no longer programming in a structured way or just heaping a lot of methods in any classes, he gains a lot of flexibility and robustness in the structure of the code, mainly due to polymorphism and encapsulation. However, to reach this point of maturity, it is necessary to go a long and difficult way, and many simply do not want or cannot get there or are still going through it and will still take some time. Before they are ripe, they will try to use object orientation (and will often think they are actually using it) but they will not be able to reap the fruits of it, so they will get the impression that it is just extra complexity for nothing and will naturally make various criticisms, claiming to be unproductive, overly complex or not delivering real value.

Bad programming practices in particular tend to make this path already quite difficult and slow to be traveled, even more difficult and slow:

  • It is common to see who insists on using switch instead of polymorphism and teach it to others.

  • It is common to teach procedural models painted OO instead of real OO, such as proliferation of classes that are nothing more than getters and setters, practices of the type PessoaJuridica extends Pessoa, monstrous classes that have several hundred different methods to do everything that is left and right, etc.

  • It is often seen people using inappropriate data structures such as a bunch of ints, strings and arrays instead of classes and objects.

  • It is common to see people imitating patterns and coding processes (often addicted) without understanding or questioning why they.

  • It is common to see people programming in the X language imitating the standards and coding conventions of the Y language and ignoring the recommended standards in X.

This spread of bad practices makes it more difficult for those who are learning to separate the tares from the wheat and introduces several vices that are difficult to unlearn afterwards. Again, I emphasize that this problem of learning and application applies to any programming paradigm and any language, but it affects more strongly those that are more difficult to learn correctly, reaching in full the paradigm of object-oriented programming.

Criticisms that I do not consider valid

Here I list some of the criticisms linked on Wikipedia that I don’t see as valid and some that I’ve seen elsewhere.

Extra complexity in the representation of abstract concepts

A common criticism is that it can often be simple and easy to use a int or a string to represent something like 1=monkey, 2=dog, 3=fish, 4=cat and then put a if or switch in the parts where the behavior varies from one case to another rather than defining specific classes for all of them. In more silly cases, this is valid, but this solution has no scale. One thing is when there are 1 or 2 places where these objects (animals in the case) can have different behaviors and you enter an arbitrary code 1, 2, 3 and 4 to deal with this, something else is when there are 1000 different places. Object orientation brings polymorphic behaviors into the object in question, eliminating the spread of ifs and switches with a lot of crazy and arbitrary codes that would dominate it otherwise.

Object-oriented programming has inferior performance

While it may be true that the calls to polymorphic functions require a more complex mechanism than non-corphic ones to materialize them and that this can inhibit some optimizations, in practice this is not a real problem. The largest performance bottlenecks are within loops that must be executed very often and as quickly as possible, and object-oriented programming settings are optimized in these circumstances very well by all decent compilers on the market, including those in interpreted languages (which typically compile just-in-time before executing the code).

In addition, most performance-related problems refer to design algorithms, which changes very little when it comes to choosing procedural vs object-oriented.

Over specification without generic types

It is often suggested that classes BoloDeCenoura, BoloDeChocolate and BoloDeMorango are subclasses of Bolo, and with it creates a lot of classes and subclasses for all kinds of things. This criticism ignores the fact that this is not a good modelling oriented to objects, although it is often taught so. The ideal is to do in the class Bolo, a method getSabor(). If the taste guy shouldn’t get lost Bolo<Cenoura>, Bolo<Chocolate>, Bolo<Morango>.

This type of class modeling appears when:

  • The language in question is strongly typed but has no generic types and the programmer tries to simulate it in a bad way (gambiarra) using inheritance.

  • The programmer modeled this because it seemed to him to be a good idea to use inheritance to specialize behavior in this way without considering the possibility of using composition.

In the case of languages with dynamic typing, this criticism is totally innocuous. In fact, this is a criticism of the misuse of inheritance and the lack of generic types in a strongly typed language. Using this to attack object orientation is not a valid thing, although this type of attack is common.

Lack of a canonical definition of object-oriented

It is true that there is no canonical, unique and universal definition of what is or is not object-oriented programming and its definitions will vary greatly depending on who you are asking. However, this is something that has little value in practice, and although there may be disagreement or disagreement about certain terms and certain occasions, most people agree more or less that object-oriented programming preaches the concepts of polymorphism, encapsulation, inheritance (of type and implementation) and the union of the structures with the codes that operate on it.

Anemic model

There are many people who create such objects FuncionarioVO which contains a lot of fields/attributes and a lot more of getters and setters with little or no additional functionality and then creates type business classes AtualizaFolhaDePagamentoFuncionario containing the business rules operating on FuncionarioVO.

This is a very bad architecture, called anemic model and that deserves much criticism for separating the behaviors that an object has or may have from the structure of it, spreading business logic in several different places, promoting a bad encapsulation and a low class cohesion. However, this is a typical architecture of a procedural system, and not object-oriented. In an object-oriented architecture, the data of an object should not be separated from its behaviors, which is exactly what the anemic model does.

I have seen many criticisms that object-oriented design turns out to be complicated and difficult to organize in this way. But in this case the problem is not object orientation, but precisely because it was violated. This type of criticism is not valid for putting the victim in the dock.

Difficulty writing a compiler

I have seen criticism of object-oriented languages because they are harder to write a compiler for. Now, in this case this is a compiler problem, not a language problem. It is true that in general it is more difficult to write a compiler for an object-oriented language than to write one for a procedural one, but this in no way serves as a justification for not adopting object-oriented languages, at most serves as a warning for someone who is designing a programming language or is in the mood to write a compiler. In addition, the challenges inherent in the implementation of object orientation in the compiler are generally much smaller than other inherent challenges, such as parsing and code generation.

  • First of all, thank you for the whim of the answer! Allow me to raise some points: on the opacity of polymorphic abstractions and the double-Ispatch, I confess that I never had problems with this, because in the case of double-Ispatch I never had to use it (but it is a valid point). About simulating polymorphism, since you touched on the subject structured programming, I must say that I suspect that in this one there is another important problem that would be limited scalability, due to abstraction not be imposed by the paradigm, but I may be talking nonsense (cont...)

  • About the inextensibility of classes, it sounds to me a little as if in most cases the problem was the bad design, either of the original class, or of the version "Utils". If you have an example that does not corroborate this I will want to know. As for the anemic model, I find it interesting to note that it has many advocates in IF, to the point that it seems that the discussion is in "technical tie" there (cont...)

  • Finally, the other points all seem to me very correct. I am also curious to know if you consider the difficulty of imposing a correct design in O a specific problem of the paradigm or a more general case that also occurs in the structured, for example.

  • The anemic model is in what you do not consider valid criticism?

  • 1

    @Jeffersonquesado Yes, because the anemic model is precisely a deliberate violation of the principles of OO, making the application does not obtain the advantages of the paradigm, so it does not count as criticism

  • @Piovezan I edited the answer.

  • Opa- the answer is quite complete and extensive - I confess that I have not read everything with due attention. but will all the raised balls are inherent OO programming, or some are more because of implementations of OO in some languages - mainly static? I wonder why I am a Python programmer, and the characteristic of being dynamic language seems to avoid almost all these problems (including the language implements multiple inheritance without any problem)

  • @jsbueno In the text, I state that "Some languages try to solve imposing an order of inheritance precedence". That’s exactly what Python does (see here). Whether it is inherent in OO languages is a bit difficult, since there is no canonical definition of what is or is not OO, but I would venture to say that implementation inheritance (whether simple or multiple) is always problematic for making the program relatively more confusing and difficult to understand (which is also somewhat subjective). [continues...]

  • @jsbueno [...continuation] As for the Double-Dispatch I only remember seeing one or two languages with this feature a few years ago (I can’t remember the name anymore), none of them was very successful, but it is something that can be resolved in OO and therefore is not inherent to them, but also that it is not inherent to them mainstream. The opacity of polymorphism is something inherent to polymorphism itself and therefore to OO itself: there is no way of having polymorphism without paying this price. So much so that any attempt to simulate polymorphism in a language that does not have it will make it appear. [continues]

  • @jsbueno [...continuation] Crosscutting-Concerns is something that can be corrected exactly with aspect-oriented programming (which does not exclude object-oriented programming), but I do not know if the negative side is something inherent to it (I suspect not, but I do not know the alternative). Inextensibility is not something inherent in OO and languages with dynamic typing do not suffer from it. Inextensibility is also not inherent in static typing, but I do not know static typing languages that do not suffer from this problem, although I believe they should exist. [continues]

  • @jsbueno [...continuation] The additional complexity is something inherent in OO. The OO paradigm is inevitably more complex than procedural because it is a significant addition to what is offered by it. The lack of Amblas is not something inherent and has already been solved in most languages mainstream who suffered from this problem. The injection of dependencies is not a problem inherent to OO, but I suspect that a more definitive solution of it leads to another paradigm (which I do not know the name) as with crosscutting-Concerns. [continues]

  • @jsbueno [... continuation] And returning to the question of simple and multiple implementation inheritance, the main problem is that implementation inheritance leads to a strong rather than weak coupling. However, this is a problem inherent in the legacy of implementation, but not of OO, because contrary to what many think (including I thought so for a few years), the legacy of implementation is not something inherent to OO. In fact, even type inheritance is not inherent in OO. Type inheritance is inherent only to OO languages with static typing, being dispensed with when typing is dynamic.

  • @Victorstafusa "In fact, this is a criticism of the misuse of inheritance and the lack of generic types in a strongly typed language". When is it possible to exist inheritance without OO? Simulating in procedural? In what other ways?

  • @Piovezan Actually, what I meant is that it is possible to have OO without inheritance, and not the other way around. In the procedural, it is even possible to simulate simple inheritance using structs within structs and Casts, where the struct which corresponds to superclass is the first member of the struct of the subclass and because of this, both are in the same memory address. For multiple inheritance, you end up having to replace the cast for something more complicated.

  • @Victorstafusa did not understand the case of X-Stream. The guys create a map called OrderRetainingMap and make him extend HashMap that it is just an implementation that does not retain order and then claim that the methods inherited from the superclass are incompatible with the intention of the class? Where is Liskov there? I do not understand how it strengthens the point of strong coupling in inheritance.

  • @Victorstafusa I saw that the problem happened because they hoped that HashMap#put() was called and instead for some reason was called such a HashMap#putVal(), what is a breach of the class contract (insertions should be made with put()). But I still don’t understand the relationship.

Show 11 more comments

6

This answer is not new but a summary of the other two answers. There is no need to upvote or anything. Serves to consolidate the arguments against OO and can serve to add/correct their understanding or give continuity to the discussion (in Victor’s answer fit more things, Maniero’s reached the limit).

Opacity of polymorphic abstractions

Inherent in polymorphic static languages

Victor: Disturbs beginners, who get lost trying to find which polymorphic version is being called.

Maniero: It is not a limitation of OO but of static languages making use of polymorphism. It impairs legibility and thus maintainability. Additionally, excess abstraction can be harmful.

Simulating polymorphism in a structured language

Irrelevant

Victor: cause patterns (syntaxes) gambiarradas because it goes against the language support.

Maniero: Disagrees. There is nothing wrong with doing this unless there is reason not to. Cohesion also has harms.

Piovezan: I do not understand why this criticism. It is only limitation in languages not designed for OO.

Double-Dispatch

Pertinent

Victor: occurs when it is necessary to do something that is not supported by the paradigm: choose which method to call based on the type of two objects and not one. Solutions involve the standard Visitor, introspection/Reflection or tables with n x m objects, and result in a good amount of code and complexity to manage.

Maniero: Agrees and finds one of the biggest problems of the paradigm. Common happens when trying to model something that does not exist, when it does not fit to use OO. When it happens maybe a relationship would be more appropriate. It occurs frequently and it is difficult to understand why it happens after all the relational model is usually easier to understand.

Multiple inheritance of implementation

Inherent in static typing

Victor: Diamond problem. And makes it difficult to implement the language.

Maniero: It’s actually a static-type complaint. Rarely do languages implement all the language resources needed to properly support multiple inheritance (abstract classes, interfaces, traits, mixins, roles, protocols, delegations, extensions, attributes, etc.). Moreover, people do not understand ontology and taxonomy and have difficulty dealing with multiple inheritance. If they understand have more ease also with the modular paradigm, which is simpler and organized.

Piovezan: Boy, if multiple inheritance needs all these resources to work well, then it’s a demo thing :P I’m glad to be only in simple inheritance, if this way works, for what else?

Simple inheritance of implementation

Pertinent

Victor: Inheritance introduces a strong coupling between the superclass and the subclass. Subclasses are especially fragile if the superclass undergoes changes. It is often the behavior of the subclass depends on the implementation details of the superclass, breaking down in the face of internal details changes. One way to mitigate this is by preferring composition to inheritance.

Maniero: Agree on everything. And the Car and Vehicle example is a relational and modular model, not OO.

Crosscutting-Concerns

Pertinent in several paradigms, including OO

Victor: Logging, transaction management, I/O resource closure, error handling, introduce additional and accidental complexity to the program. And they’re usually spread across the code and not concentrated at a single point, which makes it very difficult to maintain. The various attempts to resolve this have always left a little bit of Concerns behind. Thinking about it came the Aspect-Oriented Programming, which is not well accepted because it keeps distant the code that executes the behavior and what implements it.

Maniero: OO also and was very well accepted. Cross-Cutting Concerns are problems also in other paradigms. They are real world modeling and OOP does not get along with it. Some deny that this was the goal of the paradigm. It is the greatest limitation of the paradigm: taxonomy needs to be perfect to function well, but this is difficult or impossible.

Focus on objects and not on actions

Mitigated / irrelevant

Victor: is a criticism of proponents of functional languages to OO, although it is not an inherent problem to OO. It has been mitigated in more modern languages with the introduction of the concept of Lambdas, making them hybrid.

Maniero: It disagrees that languages with some functional resources have surrendered to functional; they remain imperative. And O has nothing to do with actions, O is data structures, zero algorithms.

Inextensibility of classes

Inherent in static typing

Victor: Everyone has already wanted to add functionality to an existing class, and by failing to create one StringUtils, DateUtils, etc. It is no problem inherent to OO, because in dynamic languages this is solved through mix-ins, but with the disadvantage of keeping away the extra code of the class that includes it.

Maniero: As far as you know the pure paradigm requires that classes should be extended, but there can be controversy. OOP tends to destroy cohesion by leaving together what is separate. The granularity of other paradigms avoids this.

Dependency injection

Relevant / misapplied

Victor: Creating an object implies providing dependencies to your constructor. The dependency chain can get complicated (Piovezan: I don’t understand ID so this phrase may be inaccurate). The solution are dependency injection frameworks, which unfortunately add complexity to projects.

Maniero: Agrees. Modeling objects is complicated, people learn DI to help test and then the tests are not effective, either because they are misapplied or because the quality philosophy of the project does not maintain consistency.

Piovezan: This is what I understood from Maniero’s reply, I don’t know if it’s correct.

Greater complexity than other paradigms

Pertinent

Victor: The way to master OO is longer and more difficult than procedural for example, and in addition people practice and perpetuate inadequate programming practices that hinder the way further.

Maniero: He agrees in part. Too bad people don’t understand that OOP is modeling. OOP is more useful for frameworks, in business systems the experience seems to be that it is not so good. Use wrong OOP and use where shouldn’t deliver value.

Extra complexity in the representation of abstract concepts

Criticism of abstraction and not OOP

Victor: Enumerations of ints or strings are preferable to classes only when they occur in a few parts of the code, otherwise they make maintenance difficult, while OO eliminates the problem.

Maniero: I consider the criticism valid, but abstraction and not OOP.

Object-oriented programming has inferior performance

Relevant when performance is important

Victor: In practice it is not a real problem.

Maniero: If performance is important, OOP can be slow when it is too late; it is a design error but the choice of paradigm contributes.

Over specification without generic types

Pertinent / Inherent in static typed OO languages

Victor: It is a criticism of languages without generic types or misuse of inheritance, not OO.

Maniero: You can’t do O in static languages the right way because you have to use a separate paradigm that is genericity, and this is a serious problem.

Lack of a canonical definition of object-oriented

Inconclusive

Victor: In practice there is sufficient agreement.

Maniero: No. For lack of consensus there are conflicting recommendations, like who tells you to put everything in class vs. who tells the class to only do one thing (example?).

Anemic model

Inconclusive

Victor: Anemic model deliberately violates OO, therefore it is not a valid criticism.

Maniero: Anemic model is a modular model that greatly facilitates maintenance. It is not a violation of cohesion. What matters is the sole responsibility. 100% OOP encourages to violate DRY, something that has encountered strong resistance lately.

Difficulty writing a compiler

Irrelevant

Victor and Maniero: Problem of who creates language and not who uses it (comment from Maniero: languages are to some degree moving away from the paradigm).

Additional points of the Maniero

  • OO was not much researched, otherwise the definition of OO would be canonical.

  • It is difficult to establish the limits of objects. In other words, OO does not shape the human mind.

  • Java’s static typing forces certain mechanisms to function in a way. This is mostly covered by Victor’s response.

  • Has problems with competition (no detailed answer).

  • OOP requires right modeling, requires ontology, which people have difficulty doing, and we always deal with problems we don’t know, or repeat what we already know. It’s an invitation to disaster.

  • OOP inhibits creativity, because it has to follow certain patterns to make it work. It works for recurrent things, modeling what we already know how to model.

  • Hide (encapsulate) state is the worst possible option compared to, for example, isolate it.

  • If you search OOP/OOD + flaw/bad/sucks/evil/misuse/etc. you will find many arguments that make sense.

  • Many excellent programmers beat OOP and have good arguments for it.

  • People are distancing themselves from OOP. Distancing is not abandoning, it’s using where you need it.

  • OOP in its pure form (without other mechanisms covering the deficiencies of the paradigm) requires doing things that are not pragmatic and inefficient codes.

  • It applies to 1%, maybe 10% of cases and not 100% as people think. In business systems it is not as beneficial.

  • If you follow all the rules.

  • 1

    Wouldn’t it be better to turn this here, this compendium of the best times, into a community wiki post?

  • @Jeffersonquesado The biggest advantage is that users would need only 100 points and not 2000 to edit the answer. Those interested in editing it already have this score and can edit it without problems. Other than that I see no objection. I’ll leave it to a moderator to decide.

  • @Jeffersonquesado My intention in creating it was to consolidate the arguments of a discussion that already occurs in the question. Who did not answer and has new arguments can well create a new answer.

  • @Piovezan now that I’ve seen this. It deserves a yes vote. I only change to CW if I ask. Let’s get to the points that I think deserve comment: All the time we make multiple inheritance of subtype and even a little behavior, rarely of state. In fact, it’s rare to have two states that can form a new one together. C++ has only one mechanism for everything, and is one of the biggest bombs ever created in languages. Better to have several mechanisms. In dynamic languages have only one also and until it works if you disregard the problem of exploding in your face at runtime.

  • About the generic types it was an irony. So your understanding didn’t consider it. What I meant is that the defense that OO is right is to use the genericity paradigm so you can’t do O in static languages the right way. To solve the mentioned problem you have to abandon the paradigm, so it is a serious problem. It is a highly pertinent criticism because OO itself has the problems that criticism points to. I almost negatively answered Victor because of this. It is very wrong. Criticism applies because it is only solved with another paradigm.

  • And I had already realized that people do not understand that genericity is not part of OO. We noticed how the lack of formal definition generates a lot of opinion. It is good to emphasize about the anemic model that my criticism is that OOP forces do bad things for maintenance, the well applied anemic model helps solve this, even running away from OOP, so my general criticism to the paradigm, the solutions to real problems always require getting out of it.

  • Some points are huge simplifications of the simplifications that I’ve already made, and I think Victor has, so consider this to form an opinion. And finally, I’m not saying that other paradigms are great, just that they don’t have the OOP problems and that they’re often easier to deal with. But for certain problems their limitations are worse than OOP. I’m not going down the drain in the paradigm, just criticizing where it fits. My biggest criticism is the abuse and use without complete understanding of what is and how the paradigm can be beneficial.

  • On the generic types, I replaced the irony with the argument itself; and on the canonical definition of the paradigm I requested an example, in my view necessary to strengthen the argument.

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.