58

Perhaps the greatest promise of using object-oriented paradigm is the code reuse. Some dispute that this was achieved. Why was it (not) achieved?

Does code reuse as OOP defines it, make projects more productive?

Or more manageable? Or easier to maintain? Or with more quality?

Probably we all agree that code reuse is a good thing, but there are several ways to achieve this goal. The question is about the method of code reuse offered by OOP. Was it a good thing? Are there better methods to achieved code reuse than object orientation, sub-classing, polymorphism, etc.? What ways are better? Why?

Tell us your experience with OOP reuse or other paradigms reuse.

10

19 Answers 19

36

Code reuse is a pretty good idea. Not a great one.

I have a perspective drawn from about 30 years of software engineering, trying to "reuse".

I started investigating "code reuse" as a research topic back in the 80s, after discovering I had reused the design of one OS I built in the early 70s, for another OS I built in the late 70s.

The good part of code reuse is the ability to sometimes reuse honest-to-god preexisting code. But the world is full of code; how can find what you want? Here's what I call the Reuse Curse:

I'm Santa Claus (ok Open Source), and I have a bag of 1 billion software components. You can have any one of them.

Good luck choosing.

To solve the reuse problem well:

  • the reuser needs to somehow specify what he needs (functionaly, performance, target language, environment assumptions, ...)
  • there must be a library of "reusable" code that has been indexed in various ways by these potential criteria
  • some mechanism must exist to pick out candidate elements (at a billion elements, you can't look at them all personally)
  • there needs to be a way to characterizer how far away from the specification the chosen candidates are
  • some regular process should exist to allow the reuser to modify the chosen reusable code (here is OOP's greatest contribution: you can edit an existing component/object by overriding its slots. OOP doesn't provide any other help).
  • all this must clearly be cheaper than simply recoding it

Mostly what has been discovered over the years is that for code to be reusable, it sort of has to be designed for that purpose, or it contains too many implicit assumptions. The most successful code reuse libraries have actually been pretty small. Arguably libraries and frameworks are "reusable" code and they are extremely successful; Java and C# succeed not because they are pretty good computer languages, but rather because they have huge well-designed, implemented and documented libraries available. But people don't look at the source code in the libraries; they simply call a well-documented API (designed to be generally usable).

What code reuse hasn't done (OOP neither) is provide orders of magnitude improvement in our ability to code systems.

I think the key flaw is that any kind of code reuse is fundamentally limited because code has too many assumptions built in. If you make the code tiny, you minimize assumptions, but then the cost to build from scratch isn't very big and the reuse gains are not effective. If you make the code chunks huge, they're pretty much useless in a new context. Like Gulliver, they are tied to the beach by a million tiny strings, and you simply can't afford to cut them all.

What we should be working on is reuse of knowledge to construct code. If we can do this, then we can apply that knowledge to construct code that we need, handling the current set of assumptions.

To do this, one still needs the same specification capability to characterize software components (you still have to say what you want!). But then you apply this "construction" knowledge to the specifications to generate the code you want.

As a community, we aren't very good at this yet. But people do it all the time; why can't we automate it? There is a lot of research, and this shows it can be done in many circumstances.

One key piece of machinery needed for this are mechanical tools for accepting "component descriptions" (these are just formal documents and can be parsed like programming languages) and apply program transformations to them.

Compilers already do this :-} And they are really good at the class of problem they tackle.

UML models with code generation are one attempt to do this. Not a very good attempt; pretty much what one says in most UML models is "I have data that looks like this". Pretty hard to generate a real program if the functionality is left out.

I'm trying to build practical program transformation systems, a tool called DMS. Been pretty well distracted by applying program transformations not so much to abstract specifications to generate code, but rather to legacy code to clean it up. (These are the same problem in the abstract!). (To build such tools takes a lot of time; I've been doing this for 15 years and in the mean time you have to eat).

But DMS has the two key properties I described above: the ability to process arbitrary formal specifications, and the ability to capture "code generation knowledge" as transforms, and apply them on demand. And remarkably, we do generate in some special cases, some rather interesting code from specifications; DMS is largely built using itself to generate its implementation. That has achieved for us at least some of the promise of (knowledge) reuse: extremely significant productivity gains. I have a team of about 7 technical people; we've written probably 1-2 MSLOC of "specifications" for DMS, but have some 10MSLOC of generated code.

Summary: reuse of generation knowledge is the win, not reuse of code.

2
  • 5
    IMHO, The best answer. The important thing is knownledge/idea reuse, not the code.
    – kravemir
    Mar 15, 2015 at 14:32
  • 5
    Mostly what has been discovered over the years is that for code to be reusable, it sort of has to be designed for that purpose, or it contains too many implicit assumptions. I've reached a similar conclusion but I couldn't express it so succinctly.
    – biziclop
    Sep 10, 2015 at 8:55
37

Code re-use is achieved in OOP but it is also achieved in functional programming. Anytime you take a block of code and make it callable by the rest of your code such that you can use this functionality elsewhere is code re-use.

This type of code re-use also makes code more manageable because changing this one callable block changes all places that it is called. I would say this result increased quality too and readability.

I am not sure OOP is simply there to provide code reuse. I look at OOP as more of a way to interact with objects and abstract away the details of the data structure.

From Wikpedia:

Object-oriented programming has roots that can be traced to the 1960s. As hardware and software became increasingly complex, manageability often became a concern. Researchers studied ways to maintain software quality and developed object-oriented programming in part to address common problems by strongly emphasizing discrete, reusable units of programming logic[citation needed]. The technology focuses on data rather than processes, with programs composed of self-sufficient modules ("classes"), each instance of which ("objects") contains all the information needed to manipulate its own data structure ("members"). This is in contrast to the existing modular programming that had been dominant for many years that focused on the function of a module, rather than specifically the data, but equally provided for code reuse, and self-sufficient reusable units of programming logic, enabling collaboration through the use of linked modules (subroutines). This more conventional approach, which still persists, tends to consider data and behavior separately.

8
  • 9
    +1 functional programming may be the way to go for code reuse.
    – Jonas
    Sep 27, 2010 at 21:11
  • 1
    @Matthieu M.: Well, how reusable is double sqrt (double x)? Pure functions are the archetype of reusability. Jan 25, 2011 at 10:59
  • 3
    @Joonas: double sqrt(double x), float sqrt(float x), int sqrt(int x) you can define a lot of them, while with a Generic Programming language you would have Number sqrt(Number x) and be done with it. Jan 25, 2011 at 15:18
  • 1
    @Matthieu M.: Indeed, generics reduce code replication, so it's "more reusable", yes. However, I think the real key to reusability is to define simple, small, sane, pure functions (this is the "functional programming" direction), and pass them around, which is possible in C. It's more about the general programming style than about the capabilities of the language itself. Jan 26, 2011 at 10:37
  • 1
    @Joonas: Ah, I had missed the pure word, you're right, composing small pure functions is just great, and even C features pointers to functions for that. Jan 26, 2011 at 10:58
15

Yes and No

Code reuse is a catch-all term for many different activities.

  1. Code reuse within a single project. OO is perfectly suitable for this, a well-designed application will have mapped the relationships of the modelled world closely, thus eliminating duplicate code as much as possible and advisable. However, you can argue that pre-OO technologies could achieve the same thing, which is true, but OO is in many ways more convenient.
  2. Third party libraries This seems to work equally well with or without OO.
  3. Cross-purpose code reuse The biggest code-reuse promise of OO was that code, once written for one application can later be reused for another, which it hadn't been specifically designed for. This was all the rage when the notion of OO filtered through the doors of higher management offices, and OO completely failed to achieve it. It turned out that purpose was a crucial aspect of OO design (and possibly all procedural code, but that's only my theory) and attempts at repurposing code ended in maintenance disasters. (The well-known antipatternsof an old framework nobody dares to modify and its friend, the slightly-different-frameworks-for-every-app usually stem from here.)
13

I would post a long answer but why? Udi Dahan explains it much better than I can.

http://www.udidahan.com/2009/06/07/the-fallacy-of-reuse/

Here is the start of the post:

This industry is pre-occupied with reuse.

There’s this belief that if we just reused more code, everything would be better.

Some even go so far as saying that the whole point of object-orientation was reuse – it wasn’t, encapsulation was the big thing. After that component-orientation was the thing that was supposed to make reuse happen. Apparently that didn’t pan out so well either because here we are now pinning our reuseful hopes on service-orientation.

Entire books of patterns have been written on how to achieve reuse with the orientation of the day. Services have been classified every which way in trying to achieve this, from entity services and activity services, through process services and orchestration services. Composing services has been touted as the key to reusing, and creating reusable services.

I might as well let you in on the dirty-little secret:

Reuse is a fallacy

4
  • 4
    -1. Mr. Dahan is preoccupied with strawmen; no one seriously reuses non-generic code as he implies, and if you remove that argument from his article, he is in fact in favor or reusing code appropriately. Dec 5, 2010 at 3:04
  • 3
    @Steven A. Lowe Well I wish that were true. I wish I had your luck because I have seen code reuse in the non-generic form. It wasn't pretty.
    – Tony
    Dec 6, 2010 at 13:00
  • 1
    i'm sure it wasnt - but were they serious? dilbert.com/strips/comic/1996-01-31 Dec 6, 2010 at 14:29
  • 1
    Agreed, the cost of making code reusable is really high, so it does not pay off unless you're talking on the scale of the Java or .NET base classes. See youtube.com/watch?v=aAb7hSCtvGw
    – Andomar
    Jan 24, 2011 at 11:17
13

I agree with Chris, functional programming is a good way to reuse code.

Many programs has code structures that is recurring. For this some design patterns are used in the OOP-world, but this can be achieved by recursive functions and pattern matching in functional programming languages. For more on this see the first chapter in Real World Functional Programming.

I think that deep inheritance in OOP can be misleading in many cases. You have a class and many of the closely related methods are implemented in different files. As Joe Armstrong said about OOP:

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.

High order functions are also very useful when it comes to code reuse e.g. map and foldr that is the foundation for Google's MapReduce.

Asynchronous message passing is also a good way to organize complex software, and some computer scientists state that objects was assumed to communicate with eachother asynchronous as in the Tell, don't ask OOP principle. See more about this in Object Oriented Programming: The Wrong Path? were Joe Armstrong is quoted:

I started wondering about what object oriented programming was and I thought Erlang wasn't object oriented, it was a functional programming language. Then, my thesis supervisor said "But you're wrong, Erlang is extremely object oriented". He said object oriented languages aren't object oriented. I might think, though I'm not quite sure if I believe this or not, but Erlang might be the only object oriented language because the 3 tenets of object oriented programming are that it's based on message passing, that you have isolation between objects and have polymorphism.

Asynchronous message passing as in event driven systems and in Erlang is also a very good way to decouple systems and loose coupling is important in complex systems. With a sufficiently decoupled system you can evolve the system while it is running, maybe on different nodes. Unibet made a great presentation about this: Domain Event Driven Architecture

However I think that most of the code reuse is done by using libraries and frameworks.

2
  • 2
    I love that Gorilla quote. ^^
    – gablin
    Jan 24, 2011 at 10:09
  • I thought the question was about code reuse, not nice semantics..? Jun 18, 2011 at 19:37
7

The humble unix pipe has done more for code reuse than anything else that has come and gone. Objects just happened to be an intuitive way of structuring code when they came along and later people started to tack on anything and everything onto it. In general objects are for encapsulation and not for code reuse, code reuse requires something more and the class inheritance hierarchy is a poor substitute for what a code reuse mechanism should really be.

4

OOP is no special; you can make reusable code with or without OOP. Pure functions are particularly reusable: for example, java.lang.math.sqrt(double) takes a number in and gives a number out. No OOP, but definitely more reusable than most code out there.

4

From a functional programming view OOP is mostly about managing state.

In functional programming you can easily have hundreds of useful functions for lists: http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/Data-List.html.

Would you have hundreds of methods in a List-class? Public methods are considered an interface to the internal state which you want to keep small.

Sadly, instead of (re)using lots of small functions, some people duplicate functionality. To me that is because OOP does not encourage code reuse as much as functional programming does.

2
  • 1
    Your conclusions are all wrong, @Lenny222. There is nothing about OOP that requires classes to maintain state. That's a question of its architecture whether it stores state internally or, like Smalltalk's Integer classes, instantiates new objects with new state. Oct 13, 2010 at 15:49
  • 1
    I am sorry that i have not expressed myself in a way that has prevented this misunderstanding: what i meant is that the difference between OOP and FP is not that OOP ecourages code reuse more than FP does (what the headline implies). I have experienced much better code reuse with FP. If you have only immutable classes, you're emulating FP, why do OOP in the first place? In my POV it's about imperative state management. Oct 14, 2010 at 11:28
3

For me, yes, but not all the time, and it could have been done other ways.

Most of the time by creating an abstract base class and creating concrete implementations of that class.

Also many frameworks make use of inheritance to provide code reuse (Delphi, Java, .Net are just some that spring instantly to mind).

That's not to say that lots of utility libraries and snippets of code couldn't have done the job as well, but there's something pleasing about a well designed object hierarchy.

0
3

In my experience, I've had more success leveraging "reusable" code through generic programming facilities (like C++ templates) than I've had using OOP principles like inheritance hierarchies.

2

OOP is too open for effective reuse.

There's too many ways to reuse. Each public class asks: "make a new instance of me!", each public method says: "call me!", each protected method yields: "override me!" - and all these ways of reuse are different, they have different parameters, they appears in different context, all have their different rules, how to call/extend/override it.

API is better, it's a strict subset of OOP (or non-oop) points, but in the real life, APIs are overfeatured and forever-growing, there're still too many connection points. Also, a good API can make life easier, it's the best way to provide interface for OOP.


Datadlow paradigm provides a strict interface for components, they have ports of following types:

  • consumers (inputs), and
  • producers (outputs).

Depends on the domain, there're some packet types, so consumers and producers can be connected it they have same (or compatible) ports. The most beautiful part of it, that it can done visually, because there're no parameters or orher tweaks on connections, they really just connects a consumer and a producer.

I was a bit unclear, you may take a look on "dataflow" tag on StackOverflow, or Wikipedia "datafow programming" or Wikipedia "flow-based programming".

(Also, I've written a dataflow system, in C++. So OOP and DF are not enemies, DF is a higher level organization way.)

2

In CommonLisp there are lots of means to achieve reuse:

  • dynamic typing, having your code be generic by default

  • imperative abstractions, i.e. subroutines

  • object-orientation, with multiple inheritance and multiple dispatch

  • syntax-abstraction, the ability to define new syntactic constructs or abbreviate boiler-plate code

  • functional abstractions, closures and high-order-functions

If you try to compare the CommonLisp experience to other languages you'll see that the major feature that eases code reuse is the presence of both object-oriented and functional abstractions. They're more complementary than alternative: without one of them you're forced to reimplement the missing features in a clumsy way. See, for example, functor classes used as closures and pattern matching to get non-extensible method dispatch.

1

There really is no such thing as "reuse" the way that people describe it. Reuse is an accidental property of anything. It's difficult to plan for it. What most people mean when they talk about "reuse" is "use". It's a far less attractive and exciting term. When you use a library, you are using it for what it was intended for, normally. You are not reusing it unless you're doing something really crazy with it.

In that sense, reuse in the real world is about re-purposing things. I can reuse these seats here and rearrange them to form... a bed! Not a very comfortable bed, but I can do that. That's not their primary use. I am reusing them outside their original domain of applicability. [...] Tomorrow, I will fly back to the UK. I will not reuse the plane. I will just use it for the purpose it was intended for, there's nothing fancy or exciting about that.

— Kevlin Henney

3
  • 3
    People will believe anything they see in print. Kevlin Henney is incorrect and based his reasoning on a lack of historical context and poor semantic interpretation. Reusing code was a fundamental programming principle from the days of the UNIVAC and IBM vacuum tube computers. Reusing code wasn't about re-purposing it for some functionality other than that for which it was planned. You wrote and assembled (later it was compiled) your sub-routines to produce object code which was then linked into your program. Reuse really does mean what it's commonly taken to mean in the industry today. Oct 12, 2010 at 17:49
  • If you write two functions that do the exact same thing, you have NOT reused the code regardless of how many times you've used them.
    – JeffO
    Dec 4, 2010 at 23:52
  • The chair analogy is nice and all that but just one word: Lego.
    – biziclop
    Jan 24, 2011 at 10:25
1

I'm going to risk ridicule and confess, I've only been using OOP very recently. It doesn't come to me automatically. Most of my experience involves relational databases, so I think in tables and joins. There are claims that it is better to learn it from the beginning which avoids having to rewire your thinking when it comes to programming. I don't have that luxury and refuse to scrap my career over some ivory tower theory. Like everything else, I'll figure it out.

At first I thought the whole concept didn't make sense. It just seemed unnecessary and too much trouble. I know, this is crazy talk. Obviously it takes a certain level of understanding before you can appreciate the benefits of anything or dismiss it for better methods.

Code reuse takes a willingness to not repeat code, an understanding of how to accomplish it, upfront planning. Should you avoid reusing code when you've decided you have a case where it's just not worth it? And no language is so strictly OO that it will throw an error when it thinks you should have inherited code from another class. At best they provide an environment conducive to implementing it.

I think the biggest benefit of OOP is the general acceptance of how code should be organized. Everything else is gravy. A team of programmers may not fully agree on how all the classes should be structured, but they should be able to find the code.

I've seen enough procedural code to know it could be anywhere, and sometimes it's everywhere.

1
  • "And no language is so strictly OO that it will throw an error when it thinks you should have inherited code from another class" - not yet, anyways! Dec 5, 2010 at 3:02
1

OOP gives you more ways to reuse code. That is all.

3
  • OOP also promotes interface reuse and design reuse.
    – rwong
    Dec 5, 2010 at 6:16
  • It gives me much less ways of writing a generic, reusable, highly abstract code than the other paradigms, such as functional programming (mind currying, combinator libraries, etc.) and metaprogramming. Actually, OOP seems to have a level of abstraction cup, when the alternatives are not limited at all.
    – SK-logic
    Jan 24, 2011 at 11:15
  • @SK-logic: orthogonal. Jan 25, 2011 at 16:14
1

Horizontal Reuse: aspects, traits, grafts

Classic OO sometimes falls short on code reuse, specially when you go all inheritance crazy for lack of a better way to share actual functionality between classes. For this problem, horizontal reuse mechanisms have been created, such as AOP, traits and grafts.

Aspect Oriented Programming

I consider AOP as the missing half-orange of OOP. AOP is not really that known, but it has made it to production code.

I'll try it to explain in simple terms: imagine that you can inject and filter functionality with a special structure called an aspect, these aspects have "methods" that define what and how is going to be affected through reflection, but at compile time, this process is called weaving.

An example would be an aspect that tells "for all methods of certain classes that start with get, you program will write to a log file the data that was got and the time it was get".

Watch this two talks if you want to understand AOP better:

Traits & Grafts

Traits are another construct for defining reusable code that complement OOP, they are similar to mixins, but cleaner.

Rather than explaining them, there is a great PHP RFC that explains both. Traits are coming to PHP btw, they are already commited to trunk.

In summary

OOP is key in modularity, still, in my opinion and as we commonly know it today OOP is still incomplete.

0

OOP Provides a set of useful tools that allow you to write code that can be used in more places than you could have without those tools. If you write a PrintIt function that takes any old object and calls .toString() on it, you will have re-used that code as soon as you call it with more than one type of object. With these tools, each line of code does more.

Functional programming is very hot right now among the hipsters. It provides you with a whole separate set of tools to make each line of code do more. It's probably not better or works, but provides another tool in the toolbox.

(There was a crazy idea for a whole extra level of object oriented re-use: The idea was that we could define a single Customer class and use it in every application we wrote. Then applications would just be a little glue here and there. This did not work. But that doesn't mean the OO Failed, or even that Re-use failed. The basic types of code re-use within applications made it possible to write applications that did more, and to write them faster.)

0

Reading the above posts, a few remarks:

  • Many think that code reuse in OOP implies inheritance. I do not agree. Interfaces and contracts are the core to code reuse in OOP systems. OOP is a gray box attempt in creating a component technology.
  • The difference between domain specific and generic "frameworks" as subject of re-use deem me too abstract. In my view on things, a component (a concise, minimal and re-usable interface contract and the implementation behind) can only be done, if the problem it addresses is well understood. A domain specific component, which allows non-domain experts to do their job with less knowledge about the domain is a (re-)useful component. Users need to understand the interface, less so the intricacies of the problem domain.
  • Levels of re-use often forgotten: Idea re-use, Specification re-use, Architecture/Design re-use, Interface re-use, Test-case re-use. Code re-use is not always favorable. But it is a big time saver often to stick to a specific architecture to tackle a new, similar product.
  • The OOP Design patterns (Gamma et. al) in my eyes elaborated on tactical implementation techniques rather than being meaningful in the context of code re-use on a larger scale. They help write an application with OOP elements, yet I would not see them as a solution to the "code re-use" question beyond a single application.
  • Maybe it is not fair: 20 years of C/C++/C# experience and 6 months functional programming (F#). One major element of enabling re-use is: People need to easily find "the interface", study it, understand it, then use it. Pure functional programming does not make it easy for me to see structure, candidates for reuse or where it all starts and where it all ends. The so praised "syntactic sugar" often is salt in my eyes, preventing me from easily seeing what happens. Thusly I would less likely try to re-use a functional (what is it - bunch of functions?), which may have hidden side-effects I cannot even see (lazy evaluation, monads,...). Don't get me wrong, functional programming has very cool sides, but all the strengths proclaimed I see with a good measure of doubt. I am very curious what the post-functional future brings and hope to see it before I retire ;)
  • Specification, Design, Implementation are coupled, yet not easily traversable views on the "same thing". Much more vital for increased future productivity than a new programming paradigm is, to close the gap, to increase (automated reasoning, traceability) the mutual benefits between those views. Formalized specification languages, standardized test notations (e.g. ttcn3) and programming languages supporting verification of interfaces and contracts against specifications without comment-littering might be what we need most urgently.
0

The problem is more subtle imho:

  1. OOP is a great method for structuring code with mutable state. By encapsulating the state into objects, imperative statefull code becomes more understandable because, for example, if a piece of state is expressed as private fields of a class, you know that at least this particular piece of state can only be modified by methods of this class. (And you can easily break this benefit by abusing inheritance, btw.) This is now enough, but waaay better than not having even this.
  2. code with mutable state is inherently hard to reuse. Way harder than code using immutable data structures.

So OOP in itself is not bad from pov of making reusable code, but the kinds of code that get written using OOP are inherently hard to reuse.

Also, functional programming may results in more reusable code. But getting the abstractions right to write sane functional code while meeting a deadline may not be doable. And "half-right" abstractions will be easier to express OOP style. And it will not tend to result in easier to reuse code - higher level of abstractions means that code understanding will require a higher upfront investment from programmers' limited cognitive capacity.

As a practical example: Game code involves lots of mutable state, because this is the natural way to think about coding a game, unless it's a very puzzle/algorithmic one, so it obviously ends up being structured using OO. And of course it's hard to reuse. But the same code, containing the same knowledge, would be even harder to reuse without OOP. And rewriting it to be functional style might need totally changing the way you think about that code, the knowledge behind it. Yeah, the resulting knowledge behind the code would be much clearer after the OO to FP rewrite maybe... but the cost could be huge and it might be the kind of cost that would also have to be payed by people wishing to reuse the incredibly smart and well abstracted code you end up with, so paradoxically, people would end up not reusing the code, even if technically it's more reusable.

...which leads to the last subtlety: code reuse is about the People|Code interface, not about the code only. OOP does a decent job of serving this interface because it maps well with how many people think about many kinds of code written nowadays. FP might be better for code reuse, but imho not for easily reusing the kind of code that people actually need to write nowadays. This will change as the kind of code that we need to write changes.

P.S. And if anyone wants to say that "OO is not about mutable state, you can also have OO with immutable state"... I call that "FP using classes as namespaces". It's great when it works for you and it avoids some shortcomings of some language's module systems and may result in more reusable code. But that ain't OO ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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