The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Cutting & Pasting is good

In the old days, if I found something in two programs that was simlar, I'd make a function that generalized the task and then import it into both projects. Over time this led to thousands of utility functions. Code reuse is good right?

But then I have thousands of files to search through, add to the project, new #includes. Making a small tool now involves dragging in hundreds of these files and all their dependencies on other files.

Because you know what code reuse is? Code reuse is COUPLING. Make a small implementation change to one file and now you have to retest 50 different projects affected by the change.

Lately I've been cutting and pasting when I need to reuse code. It bypasses all the coupling problems. Cutting and pasting is great!
Art Wilkins
Friday, July 14, 2006
 
 
Unless you change the signature of the function, you should be able to make internal changes with out retesting the clients using the lib...

You'll be in pain when you realize there's an edge case you missed and have to upgrade all the little pieces of cut 'n paste.
PHDude Send private email
Friday, July 14, 2006
 
 
Art,

cut/paste to avoid coupling is a valid thing to do in C but not in OO languages (no polymorphism).

The martin metric of cut/paste code most likely is in the (0, 0) area, not along the main sequence (check on www.objectmentor.com what this MM is about).

Software with MM in that area is too concrete for its stability. It will not scale up well with complexity (it becomes fragile rapidly). In other words you write a lot of code for little functionality.

Sorry, but I cannot agree with you - not from an OO pespective. There are other ways to effectively decouple components in your system.
Dino Send private email
Friday, July 14, 2006
 
 
Denis Krukovsky Send private email
Friday, July 14, 2006
 
 
"Unless you change the signature of the function, you should be able to make internal changes with out retesting the clients using the lib..."

Assuming those functions stand on their own and therefore don't use global variables or anything else that couples them to other parts of the code.
DHofmann
Friday, July 14, 2006
 
 
Yeah, well if it's all so safe to reuse and there's technically no risk since it 'should' maintain behavior across changes, then let's do away with testing, OK?
Art Wilkins
Friday, July 14, 2006
 
 
Personally I like reuse for reliability's sake.  If some function is used in 20 different apps, that function gets 20x the amount of testing.  And if I find a bug and fix it in one place, many products get better.  Code reuse isn't just about productivity, but also about reliability and robustness.
Doug
Friday, July 14, 2006
 
 
I find there are two things that are reusable:

1. Function and Object Libraries that are regulated by a standards committee.

2. Frameworks maintained by a for-profit company with annual income of at least $1 billion.

Anything else, you are better off cutting and pasting.
Art Wilkins
Friday, July 14, 2006
 
 
Art, Do you use an editor/IDE that provides source code navigation? ie. It knows about every function, class etc. and can instantly jump to any one. If not I would urge you to, as it makes life oh so much easier.

I will freely admit I'm biased as my editor (ED4W http://www.getsoft.com) does this. That said, I couldn't imagine working without this capability.

As for cut and paste, I'm afraid not.
Neville Franks Send private email
Friday, July 14, 2006
 
 
Yes, but it does not support automatic refactoring, which everyone says is the bomb.
Art Wilkins
Friday, July 14, 2006
 
 
Art,

What you're saying about cut-and-pasting, I was saying a while back about public fields (as opposed to properties).  Don't worry.  It's a phase.  I got over it, and you will too.  :)
Kyralessa Send private email
Friday, July 14, 2006
 
 
That's blashpemy!!!

..and it happens all the time.  Art, aren't you a standards committee of one, especially for the code that you have written?  I know that I am developing a codebase of my own - as I do different projects - so that I don't have to redo anything that I have already done.  Admittedly, lots of situations are different, but sometimes you can reuse things you have already done, particularly if they are tested and work for a very specific function. 

Also, if you can find it to cut and paste it, then why is it so hard to find in your library?
Joshua Volz Send private email
Friday, July 14, 2006
 
 
There is a history to this dialog between "cut and paste" and code reuse.

The mantra and drumbeating for code reuse made sense 10 or more years ago, when the industry was full of people who were NOT comfortable with OOP and who may have struggled with "structured programming".

By 'structured programming' I simply mean application of old-school Algol-like languages such as Pascal, C, Ada etc per http://en.wikipedia.org/wiki/Structured_programming. What preceded this were much clumsier tools such as interpreted BASIC and FORTRAN.

Before 1995 or so, there were tons of programmers around (still employable) who relied upon real life GOTOs and FORTRANish idioms such as cryptically named blocks of variables. I recall working on several projects in the early 90s where some retrograde dumbass using C++ for the first time and being an idiot about it absolutely insisted on keeping his beloved trashy global variables with program scope.

Today, the war has been won. Anyone lame enough to not comprehend how to shove functionality into a procedure has almost without doubt been pressured out of the industry and is no longer anywhere near a compiler. As it should be. Today a programmer who does not understand 1) basic data structures and 2) block structured procedural languages is an anachronism, like a doctor that still uses leaches and does not understand infection control. 10 or more years ago it was possible to actually work with someone like that and they may have made more money than you.

Today you can assume that anyone who programs understands the value of a procedure, and probably understands what a class represents.

So today, this isn't a point worth making either way.
Bored Bystander Send private email
Saturday, July 15, 2006
 
 
I think you're arguing a different point. I might think it's a straw man, but I've not noticed you to use straw men, so I assume you're making a different point.

As you know, I've been doing this since before the young ones here were born. I have a first edition of Y&C's Structured Design and I attended one of the talks that led to that book. Maybe I can even remember efferent vs afferent if I tried really hard.

When OO came out I jumped in right away and was using C++ *before a compiler even existed for that language*.

What I have found after all these years, is that you pay a price when you add a dependency. And adding a library or a module to get ahold of a some utility functions COSTS. Sometimes it's worth it. You all are saying it is ALWAYS worth it. I am saying that sometimes it is NOT worth it. Sometimes it is better to copy that code you want right out and paste it in and NOT have that dependency.
Art Wilkins
Saturday, July 15, 2006
 
 
Yes, I'd agree on SOMETIMES. 

Just recently I had the case where I copied a function to another module because I was trying to avoid a dependency.  And it bothered me :)  If I found a bug in that function, I KNEW I'd forget to go and fix it in the second copy.  Later, I realized the second module already depended on the first, so I was able to remove the copy and just call the original function.  I was at ease!

I think code reuse is the greatest thing ever.  I have two apps that use 95% of the same code base (no kidding).  I've almost finished a 3rd (took two weeks?) and will start selling it soon.  You can imagine how solid this code base is getting with 2x the QA on most functions and any single bug found anywhere fixing two apps.  I'll soon be getting 3x the investment.  And I don't have to depend on my (poor) memory to remember/search for copies everytime I make a fix/improvement.  (And these aren't wimpy little apps--b2b apps used in business and gov't around the world).

So yes, there are cases for copy-and-paste, but I personally believe they are fairly rare, and _in_general_ lead to less robust code then reuse does.
Doug Send private email
Saturday, July 15, 2006
 
 
Well, sure, "sometimes" cutting and pasting is good.

Sometimes you can eat the yellow snow, too... I just don't think you want to make a regular practice of it when you're not getting a Slushie from the QuickieMart.

RE: testing - my point was that only the library would need to be tested, you seemed to be suggesting you had to test the code dependent ont he libraries too, which is patently not the case unless they depend on the bugs in the function.

What I don't understand is, what benefit are you getting by cutting and pasting that you're not getting from including libraries? To cut 'n paste you still have to go through the process of finding all the libraries, but now theres an additional step of finding the functions and copying them. It sounds like *more* work to me.

If you are substantialy modifying the function for each project, it sounds like a function that shouldn't be in a library and really should be just copied... that case you're looking at it more like a design pattern/template than a function though, IMO.
PHDude Send private email
Sunday, July 16, 2006
 
 
"Lately I've been cutting and pasting when I need to reuse code. It bypasses all the coupling problems. Cutting and pasting is great!"

You still have the coupling; now you just can't find it.  I mean, if that code needs a modifcation (bug fix or enhancement) you have to do in several places -- in that sense those places are still implicitly coupled. Ugh.

But maybe you'll decide to do the modification in only one of the copied versions.  That should be good enough, right?

But if you need the function a third time?  Which version do you copy from?  The fixed version or the other one that's still floating around?  Without an authoratative source you'll have to check them all to find the one that's most up-to-date.  Ugh again.

Art, what you have actually discovered is the need for automated testing.  Those several places that use the bit of common functionality should be tested automatically, e.g. nightly by a script that you don't have to touch.  If you had that in place, you wouldn't be worrying about retesting when library code is modified.

Yes, using common code makes explicit (requiring header files etc.) your logical dependencies; but much experience shows that it is better for these dependencies to be explicit rather than implicit, in the form of copied code.
Will Dowling Send private email
Monday, July 17, 2006
 
 
Every practice has it's application! Cut & paste is good in some situations...
Iskandar Zaynutdinov Send private email
Tuesday, July 18, 2006
 
 
I agree that sometimes cut & paste to avoid a dependence is a Good Thing, but the reasons stated (easy to find, retesting the app when the function changes, "coupling") are utterly crapstastic.

Adding tests should be a trivial and normal thing to do. Finding a function in your libraries or header files is a matter of classification and organization ("libutils" is not a very good name.) Adding a dependence shouldn't be an issue if you are using a good build system and source control. Documentation _is_ mandatory. So, unless you are writing a small, quick, throw-away program, you shouldn't just copy and paste.
Leonardo Herrera Send private email
Tuesday, July 18, 2006
 
 
I have listened to the evidence for and against. After careful consideration, I stand by my original post completely and note that I am more productive than anyone I know.
Art Wilkins
Tuesday, July 18, 2006
 
 
Baby, meet bathwater. The two of you are going on a long trip together.

Tuesday, July 18, 2006
 
 
1)
If you practiced design by contract the argument that a change to a method necessitates testing all the calling apps is negated.  Assuming of course, when you find that the contract is not upheld, you fix it, instead of working around it.

2)
It seems an argumeent for not using functions in libraries is the size of th elirbaries you might be bringing in.  Perhaps you need a smaller footprint for the app, whatever.

But isn't this a pointer at being able to refactor libraries so that functions are grouped logically together to give you just what you need.

Why bring in all of the MFC when you just need to print a string to a file?
Gornin Send private email
Wednesday, July 19, 2006
 
 
"After careful consideration, I stand by my original post completely and note that I am more productive than anyone I know."

If you'd quit wasting time having to debug copy-and-paste code, you'd have a chance to get out and meet more people.  :)
Kyralessa Send private email
Wednesday, July 19, 2006
 
 
Please tell me I didn't just see this:

"Unless you change the signature of the function, you should be able to make internal changes with out retesting the clients using the lib..."

I really hope what you're suggesting is that it will COMPILE ok as long as you don't change the function signature.

Because what you wrote suggests that you don't need to re-test the 20 other applications that link to that function/library?

The internals of the function have changed and you NEED to test everywhere it is used or you're opening yourself up for bugs the next time you modify each of those applications.
damon
Thursday, July 20, 2006
 
 
"Sometimes it is better to copy that code you want right out and paste it in and NOT have that dependency."

Agreed.

I usually copy -n- paste -n- modify to suite my needs! :0
~Eric
Friday, July 21, 2006
 
 
Note to self: code review for Art.
Art's Boss
Friday, July 21, 2006
 
 
> I really hope what you're suggesting is that it will
> COMPILE ok as long as you don't change the function
> signature.

> Because what you wrote suggests that you don't need to
> re-test the 20 other applications that link to that
> function/library?


Umm, you have a test suite for your libraries, right? And it passes? Goooooood.

If you fix a bug in a lib and it breaks an app dependent on it, you have a bug in the app. Fix it.
PHDude Send private email
Saturday, July 22, 2006
 
 
Art -- could you explain why you're producing so many apps? It sounds from your opening email that you're maintaining around 50 applications which all need to be kept current and don't benefit from high-level structural similarities; is that right?

That situation has to be significantly different from 'the norm' -- where I guess the ratio of people:applications is between 8:1 (a team working on one product) and 1:3 (micro ISV working on a few products). Your 1:50 ratio probably needs significantly different methods to the norm.

So - how do you come to be in this unusual situation?
Steve Cooper
Monday, July 24, 2006
 
 
> If you fix a bug in a lib and it breaks an app dependent on > it, you have a bug in the app. Fix it.

Agreed.  But in order to find that bug in your app, it must be TESTED against the new lib version.  That means when a lib changes, all apps using it must be retested as well.
wjy Send private email
Tuesday, July 25, 2006
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz