Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

In Martin Fowler's book Refactoring, Fowler speaks of how when developers learn something new, they don't consider when it's inappropriate for the job:

Ten years ago it was like that with objects. If someone asked me when not to use objects, it was hard to answer. [...] It was just that I didn't know what those limitations were, although I knew what the benefits were.

Reading this, it occurred to me I don't know what the limitations or potential disadvantages of Object-Oriented Programming are.

What are the limitations of Object Oriented Programming? When should one look at a project and think "OOP is not best suited for this"?

share|improve this question

migrated from stackoverflow.com Feb 27 '11 at 15:17

This question came from our site for professional and enthusiast programmers.

    
The closest potential duplicate I found was Pitfalls of Object oriented programming whose answers are more about hardships when using OOP - not about when not to use it outright. –  LeguRi Feb 27 '11 at 13:48

11 Answers 11

up vote 11 down vote accepted

IMHO one, would consider refraining from OOP, and look towards plain structured C for instance, would be in projects where constraints are imposed e.g. memory constraints in embedded systems for example or real-time constraints.

In this case one would weight the "overhead" of polymorphism and virtual inheritance to gain as much possible.

Having said that, I can not think of any other case of project that OOP would be unsuitable.

The discussion would then be what are the pitfalls in OOP design. But this is not what you are asking for, right?

share|improve this answer
    
Yup, that's not what I'm asking for! +1 –  LeguRi Feb 27 '11 at 14:42
4  
+1 - but the memory overheads come more from garbage collection than from OOP. C++ doesn't have the same memory overheads, and you only get a virtual call overhead if you ask for it. If you asked for it, you presumably need it, so a non-OOP language would need to implement that which-implementation decision some other way - ie it isn't really "overhead". C++ classes can be considered an evolution of common "parameter block" patterns in C (yes, I know about Simula, but C++ adapted rather than directly copying) and C++ classes have similar efficiency to those C patterns. –  Steve314 Feb 28 '11 at 4:45

OOP is not suitable for applications, where the task is converting some kind of input to output, functional or procedural approach is much better for that. As others noted: command line programs, compilers, numeric calculations, engines of antivirus programs, web server side scripts (PHP!) etc. The common in them, that they get some kind of input, do calculations, then spit out some kind of output then they exit.

OOP is good for systems that are started once and they will run till someone shut them down: GUI applications, games, servers, etc. The common in them, that the components of these applications are responding to events: GUI elements has an OnClick event, monsters in a game may have an OnHit event, a server respond to the incoming connection by creating a working thread, etc. These event processor components should be objects.

share|improve this answer

Object oriented programming is poorly suited to tasks where individual items or collections of data are not the most useful level of abstraction.

For example, when defining a mathematics library, one notices that there are a lot of binary operations: x dot y and M*x and so on. The level of abstraction isn't the data (matrices and vectors) so much as it is the operations of inner and outer product, tensor multiplication, and so on. So you will see, for example, Java matrix libraries where the operations are classes (?!). Functional programming provides a more comfortable fit, but even plain function calls provide a more sensible framework than hierarchies of classes that don't correspond to any data.

Object oriented programming is also poorly suited to tasks where the Liskov substitution principle fails to hold. In particular, subtracting functionality is not something that OOP techniques handle well. Birds fly--except for flightless birds!

And OOP is poorly matched to situations where giving commands is the most natural thing to do. cp my_file.txt that_file.txt is a more natural fit conceptually than "my_file.txt".copySelf("that_file.txt"). The file isn't doing the copying. The file is sitting there. It's the OS and file subsystem handling it. But you don't want to have to filesystem.cp("my_file.txt","that_file.txt") either; the object is a distraction to what you're trying to accomplish.

In any of these cases, you can come up with workable solutions using OOP, but they're not IMO the most powerful way to conceive of the problem.

share|improve this answer
    
Could you make the words "Liskov principle" link to something, like the wikipedia article about it? I for one didn't know (or didn't remember?) what it was until I read this. –  Richard JP Le Guen Feb 27 '11 at 22:58
    
filesystem.cp is an interesting example. Would shell.cp or OS.cp be better or is making the function belong to an object the problem? The function to perform the copy is in code that can be described by a name: device driver, filesystem, virtual filesystem, operating system, service, command line interface. Because the function can be described as residing in a named place I don't think that using an object to contain the function is wrong, but it might not be helpful. –  this.josh Sep 10 '11 at 7:58
1  
@this.josh - As you pointed out, a filesystem object is the appropriate place for copy, and there is also rarely a good reason to make that an object rather than just a package/module/namespace/whatever. If you deal with a number of different filesystems at once (especially if some are derivatives of others with added features), sure, make it an object. Otherwise it's just getting in your way. –  Rex Kerr Sep 12 '11 at 3:13

In a comment to an answer to another question, Frank Shearar pointed me to On Understanding Data Abstraction, Revisited by William Cook. This line seems particularly relevant:

Reynolds noticed that abstract data types facilitate adding new operations, while “procedural data values” (objects) facilitate adding new representations. Since then, this duality has been independently discovered at least three times [18, 14, 33].

We always like to use abstraction to allow for extensibility, but there's a fundamental distinction between abstracting to allow new implementations of a message receiver (objects), and abstracting to allow new operations to apply to the same data representation (ADTs). OOP is good for the former; functional (and maybe procedural?) languages tend to be better at the latter.

share|improve this answer
    
I read about this, and found it to be a poor expression. I interpret it like this (perhaps wrongly?): "Procedural code allows you to extend functionality by adding one function which supports behavior for all the required data structures. OO code, on the other hand, requires you to add the new function to all the different data structures. Procedural code makes you adjust all functions to support a new data structure. OO code makes you implement a new function in all data structures.". I discussed it on my blog. –  Steven Jeuris Feb 27 '11 at 20:36
    
Key here is OO enforces a correct implementation while procedural doesn't. Also, an OO approach provides more cohesion. Anyhow, thanks for the link to the paper, It'll be an interesting read! –  Steven Jeuris Feb 27 '11 at 20:49
3  
@Steven - look into type classes. These provide type-level rigor to ADTs, enforcing correctness and improving cohesion just as effectively as object-types can, IMO. –  Aidan Cully Feb 27 '11 at 22:06
3  
OO absolutely does not enforce a correct implementation! –  Frank Shearar Feb 27 '11 at 22:09
    
Another of Cook's papers might shed more light on the topic, which is more explicit in the tradeoff between ADTs and objects: cs.utexas.edu/users/wcook/papers/OOPvsADT/CookOOPvsADT90.pdf –  Frank Shearar Feb 27 '11 at 22:10

Rather than trying to find what OOP is ill-suited to, perhaps it would be more productive to look at some alternatives like functional programming, generic programming and aspect-oriented programming, and considering what they do particularly well and areas where they provide advantages over OOP.

Compared to generic programming, OOP requires that you define a relationship between types, even if there is none. In reality, "debt" and "rainbow" don't have much in common -- but if we're going to use them in Java (for example), they're going to have some common traits that most normal people would never associate with either one (e.g., hashCode, wait, and notify).

In theory the classes at the bottom of the hierarchy are concrete and those at the top abstract. In reality, as you get close to the top of the hierarchy, classes rarely represent a meaningful, coherent abstraction -- rather, they represent the the union of the requirements of a miscellaneous set of lower-level classes that somebody decided needed to be able to apply to all the other classes (e.g., the aforementioned hashCode, so you can store any object in a hash-based collection). I don't mean to pick on Java in particular here either -- .NET is similar in this regard, and Smalltalk is (if anything) considerably worse -- when you get to the base of its hierarchy, you have a "knot" that almost nobody even attempts to understand; a pretzel is hardly twisted all compared to what your mind has to do to fool itself into believing that mess represents anything even similar to a coherent abstraction of anything!

Generic programming does away with specifying a common base class to represent the set of operations required by a particular collection or algorithm or whatever. Instead, you define a set of requirements, and work with anything that meets those requirements. This, of course, can have consequences of its own -- e.g., mistakes with C++ templates are notorious for producing error messages that contain reams of meaningless garbage.

Aspect-oriented programming deals with a somewhat similar problem, but in a considerably different way. AOP is generally concerned (at least primarily) with cross-cutting concerns. A classic example is security. In a typical program, you end up with security-oriented code scattered throughout the program, "tangled up" with implementations of everything else. This means when/if you want to modify the security aspects of the program, you typically end up having to look at nearly everything else. AOP attempts to address that so you can move all the security code into its own, independent module, and specify points in the main stream of the code where the security code will be injected (so to speak) to do its job.

Functional programming can address a couple of completely different areas in which OOP is (or can be) weak. One is the ability to formally prove correctness -- lack of side effects makes formal proofs (and reasoning in general) easier. Note, that this is frequently misstated as "possible" rather than "easier" -- but this is incorrect. Formal proofs are possible in the presence of side-effects, but they are substantially more difficult.

Functional programming also limits communications between different parts of the code (for the most part, the only incoming communication is a function's parameters, and its own outgoing communication is the return value). This can be extremely useful for things like distributed systems. It's relatively easy to detect exactly where communications will be needed, and what parts of the system can run in parallel.

share|improve this answer
1  
I'll just say the reams-of-error-messages issue isn't a generic programming issue so much as a C++ issue. Concepts would be nice, but we won't be getting them for a while yet. Based on a superficial understanding, Haskell has a generic-programming type system similar to templates-with-concepts, but already working. There's plenty I don't like about Haskell, but the generic programming model isn't in that set. On AOP, when I looked at it I saw a good idea, but I also saw that one hammer being used to bang in every screw IYSWIM. –  Steve314 Feb 28 '11 at 5:00
    
@Steve314: Quite true -- the lousy error messages aren't necessarily endemic to generic programming, but they do point toward the difficulty in implementing it well. Yes, I've seen a bit the same with AOP, but its being misused doesn't invalidate the concept or make OOP handle those situations any better. –  Jerry Coffin Feb 28 '11 at 5:35
    
In C++, debt and rainbow classes would not normally have any connection. We like shallow inheritance diagrams and independent classes. –  David Thornley Feb 28 '11 at 15:38
    
Object oriented software development does not equal inheritance. The counterexample you provided with rainbow and debt would be implemented by a good Java developer familiar with best practices of OO design and Java would likely implement these common methods with interfaces that describe the common behavior and not inheritance. –  glenviewjeff Jun 19 '11 at 20:44
1  
@glenviewjeff: How exactly would you create these classes so they didn't inherit (at least indirectly) from java.lang.Object? I was rather under the impression that all classes in Java inherited from Object. The point here isn't whether it's better to model the commonality via inheritance or interfaces, but to realize that there is no commonality at all, but Java forces an inheritance relationship (tight coupling) even though in reality there's no relationship between the types at all. –  Jerry Coffin Jun 20 '11 at 3:32

Very small programs

When ever a program does something extremely simple and doesn't last long (think quick command line programs), the overhead of OOP and the OOP spaghetti you must use becomes too much of an overhead. Half your code shouldn't be OOP baggage.

share|improve this answer
1  
+1 This is why I started using Python. For small scripts a language which enforces OO just sucks (see en.wikipedia.org/wiki/Hello_world_program_examples#Java). –  Oliver Weiler Feb 27 '11 at 23:25
3  
@Helper - but Python supports OOP! Of course the principle holds, but Python is a bit of a misleading example. A big advantage in Python compared with non-OOP C is that you have all these prepackaged libraries at your fingertips - you get more value from less code because you're standing on giants shoulders. C has libraries for anything you can think of, of course, but you get all these packaging-things-to-work-together issues before you can start coding. –  Steve314 Feb 28 '11 at 4:52
1  
@Steve314 Python supports OOP, but it can be used with other programming styles. I bet TheLQ meant those other styles in his answer. –  Andres F. Oct 29 '12 at 13:24

From experience, I never found a situation where OOP is not appropriate, but I did found places were overused or misdesigned OOP was not appropriate. OOP, deep down and roughly put, is syntactic sugar and a code organization schema. Overusing it may, in some cases, trigger a sense of frustration and complexity that is uncalled for. You may point out that these are due to design mistakes, but most design mistakes producing an over-designed piece of code tend to overuse OOP concepts.

Another trouble of OOP is when developers don't know about it, something that is way common in some development environments. The approach can be either mocked, frowned upon, angrily rejected or perceived as without sense. Again, personal experience here at work.

Apart from these factors, there are places where other approaches may be better suited to describe your problem. A simple example are declarative languages. They are not OO-based, but they are incredibly efficient and idiomatic in their expression.

share|improve this answer

It is easier to list domains for which OOP fits well. There are not that many. All the other domains can't be properly expressed in terms of OOP.

To name a few exceptionally unfit areas:

  1. Compilers - representing ASTs and graphs; Pattern matching does not go well with OOP.
  2. Most of the numeric and symbolic mathematics - functional approach fits better.
  3. Business rules - logic/constraint programming is a much better fit here
  4. Anything that can be expressed as a state machine
  5. Graphics. Yes, yes, all the OOP textbooks contains mandatory examples. Square is a subclass of a rectangle, and all that bullshit. The best graphical DSLs are not OOP at all.
  6. Concurrency. In fact, messages in OOP were supposed to be asynchronous. But they are not. So, scrap the OOP, it can't be properly used in a highly parallel setting.
  7. Anything that can be expressed in a dataflow semantics. OOP does not fit it at all.
  8. Anything that is better expressed using the term rewriting systems.
share|improve this answer
2  
I would probably change numeric to mathematic or something of a kind (missing the right word here). For numerical processing functional approach is not so suitable. –  Rook Feb 27 '11 at 16:18
9  
SK-logic: (1) Smalltalk's compiler is written in Smalltalk. (2) Function and OO are not opposites. Go read William Cook's work. (6) Erlang, as OO as they come. (Just ask Joe Armstrong.) I can't be bothered to list counters to the rest. –  Frank Shearar Feb 27 '11 at 22:03
5  
@Frank Shearar, most of the Smalltalk implementations I've seen are trivial (and needless to mention that Smalltalk syntax is almost as minimalistic as S-expressions). Think of a more complex compiler. And, as I said, if messages were asynchronous, OO will be a perfect fit. Unfortunately, they aren't, and Erlang is not a classic OO at all. For numeric, you simply don't need OO. And it certainly will harm if you start expressing your problem domain in useless and alien terms. –  SK-logic Feb 27 '11 at 22:46
2  
Fortress is object-oriented. Guy Steele justified this as follows: Fortress is a library language, i.e. a language in which almost everything which looks like its part of the language is actually defined in a library. And OO is great for writing libraries, which can then expose a data flow or procedural or functional DSL to the user. –  Jörg W Mittag Feb 28 '11 at 4:35
3  
@SK-logic it sounds that you're saying that OOP's bad for writing compilers because it's hard to add operations to the tree walkers. Yes, and it's easy to add new nodes. (The classic trade-off between ADTs and objects.) So since one (probably) adds operations - new ways of walking the AST - more often than extending the language - adding new types of nodes - you're probably right. –  Frank Shearar Feb 28 '11 at 10:02

The only clear case (For me anyhow..) is when writing "Disposable" code for a one time task IE the code will be run once then tossed.

There is no need for any re-use.

There is no need to re-fractor.

There is no need for maintainability.

There is no real need for readably.

Get the thing working, as quickly as possible, test it, make backups in case it blows up, run it & toss it (Or archive it if you the sentimental type).

share|improve this answer
4  
You implicitly state that all non OOP code is disposable? –  Rook Feb 27 '11 at 16:20
    
No, I say this is a clear case to not use OOP. –  Morons Feb 27 '11 at 16:27
    
Sometimes it's more of an effort to give up good habits. –  JeffO Feb 27 '11 at 19:20
    
I'm not sure this is a case where OOP is ill suited, but a case where one could "get by" without it. –  glenviewjeff Jun 19 '11 at 20:45

Many people will confuse OOP with specific implementations of OOP. User10326, for example, mentions virtual inheritence and methods. These are not OOP concepts, they are specific implementation of OOP problems.

In general, OOP will likely have more overhead than procedural languages, but it's not strictly certain it will. So, it's appropriate to say that most OOP languages have more overhead than non-oop languages, and therefore those specific languages may not be as suitable for low memory conditions.

I think the real answer is that different paradigms may be more appropriate for a given problem than OOP. For example, functional based languages like F# (even though F# is still object oriented) is better for some problems (scientific problems for instance).

Functional languages don't have to be object oriented, but they're not mutually exclusive. A procedural language can be functional as well.

share|improve this answer
1  
I'd say that no particular paradigm can be a perfect fit for any given problem domain. Some are closer, some can't be used at all, but always the best language for modelling a problem domain is the very language of that domain itself. And they are all different. –  SK-logic Feb 27 '11 at 16:39

This is a hard question, there are so many shades of grey!

There are times when e.g. the relational model (databases) copes better with large amounts of information. OOP works nicely often if you have everything in memory. A database e.g. allows you to select smaller cross sections of a table (only certain properties), e.g. you want a list of all customer e-mail addressses for a mailing and you don't need all of the customer other information (addresses, orders etc) to be loaded. Ofen in OOP you just load complete objects and even complete object graphs (e.g. read a XML file with data). I find that databases offer a lot more in the area where you want to get a very specific cross section of data from multiple tables, or do e.g. an transactional update of a subset of data.

And then there is the functional school, OOP normally tends to not result in parallizable code, but on the other hand functional code does. So with the world moving towards multicore, this is a nice advantage (there are a few nice demo's about F# and Haskell that will open your eyes in this area).

I usually combine all these techniques in the projects that I do, especially in ASP.NET MVC you tend to just need subsets of data to display on a web page, so there's not a whole lot of value in using OOP. Normally you just display 1 record, or a list of records, so I take a record oriented approach there, with not too much interconnected object graphs.

share|improve this answer
    
Could you add some links to sources and resources for the paragraph on parallizable code? –  LeguRi Feb 27 '11 at 14:43

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.