c code reusability

I

Ian Collins

Richard said:
Ian Collins said:




Program X uses DLL Y. DLL Y is "improved", and a bug is introduced. New
version of DLL Y, with same name as before, is installed on system. Program
X now uses buggy version of DLL Y. Program X is now buggy.

Yes, you can avoid this if you're careful. No, not everyone is careful.

And it might not even be a "bug" - it might just be a change in
functionality that breaks program X. You can find some very relevant war
stories at http://www.heise.de/ct/english/99/01/070/
Ah, we are talking windows, I was thinking real shared libraries :)
That's fine if the system is well-managed. Indeed, it is the preferred
strategy not only in pizza parlours but also in dinosaur pens. But on
Windows, it's a recipe for disaster.
I thought they added the appropriate 70s technology to fix DLL hell?
 
S

Skarmander

Michael said:
mister catering said:
Imagine that you have
developed a library (YourLibrary) that is widely used by other
library/programs (Client1, Client2 ... ,ClientN). Programmer of Client1
knows about a new version of your library (YourLibrary 2.0) he is
interested in. He develop a new version of his program (Client1 2.0)
based on YourLibrary 2.0. [...]
Imagine a system
with all this clients installed... with the reusability style you
propose (that is the c reusability standard style) is not possible to
have Client1 2.0 and the rest of clients running at the same time.

Nonsense. If the library is designed with an ounce of sense, the
new version will be backward-compatible with the old. There's no
reason for it to be otherwise. New functionality can be provided by
new functions; old functionality can be left alone, or refactored as
cover routines that call the new functions with flags indicating that
the old behavior should be used. If the library is designed with a
bit more sense, the old functionality would already be forward-
compatible with new functionality thanks to reserved parameters,
behavior flags, and so forth.
I'm not sure that's so sensible. I've seen multiple instances of this
approach and they invariably blew up. Buggy old code that (accidentally or
otherwise) uses "do not use" parameters, functions that suddenly need a
pointer to a structure with an arbitrary additional amount of parameters,
structures with version or size fields (with potential for memory
corruption), functions that run out of flags and need to arbitrarily be
split up anyway, type overloading of reserved parameters (this one is
particularly nasty and a guarantee for maintenance headaches), mass
hysteria, rivers running red.

Forward compatibility is a very cuspy thing to have -- for things like file
formats. For library functions, it's not half as hot. Having to export a new
function may be inconvenient ("Oh, however shall we name it?" "What, surely
we're not up to twiddle_foo_bit5 already?") but trying to shove the old and
the new through the same interface has far more potential for inconvenience.

A library should provide hooks for its applications, not its internals,
which is basically what reserved parameters are.

S.
 
R

Richard Bos

Chris Torek said:
The second-listed problem above has a relatively easy cure: put
libXYZ-1.3 back in place of libXYZ-1.4, fix the problem with 1.4,
and then install libXYZ-1.5.

The first-listed problem is not a problem in a "correctly designed"
system: the fact that the new version of libXYZ is libXYZ-2.0
implies that it is *not* compatible with libXYZ-1.x (for any x),
and therefore applications dynamically linked against 1.x should
continue to link against 1.x (for the latest x), not 2.y (for any
y).

It would indeed be nice if all dynamically linked libraries worked that
way. Unfortunately, IME, not all do.

Richard
 
M

mister catering

Well... there's a lot of material. I think we may stop and look at our
discussion (i think is more a contruction than a discussion).

The numbers in brackets correspond to the related message order number
(by date)

The original question was about c language... is or not enough the
language "as is" for programming fully reusable code?

We begin having a discussion about versioning. I said that it would be
desirable to be backward compatible (not forever) to allow gradual
migration. I think all we agree in this point. Chris Torek (16) and
Richard Heathfield (10) propossed two ways to do it with the c language
as is:

1.- Use static linking as much as possible (Richard)
2.- Use a diferent module for each mayor version change (Chris)

Michael Wojcik (11) propossed another way (the thirth) that implies a
programming discipline: Keep new functionality separate by means of new
function and variable names.

The three options are good solutions in my view but all of them, also
in my view, have problems that, if possible, must be avoided:

1.- As Jacob Navia (13) said clients need to relink with a new version
(mayor or minor) of a static library and this is not always possible
since it supposes a toolset that may not be available at cilent's site.
2.- To mantain a unique module name across mayor versions have
advantages. A new interface implementation can use code that is part of
the implementation of the "previous" interface. Furthermore, is very
easy to keep track with a "one file" component. You only need to know
the last change's date, inspect the metadata and decide if you are
interested in his new interfaces/implementations
3.- As i said (15) to have more than one name for the same semantics is
not desirable from the client's point of view. Furthermore, this
solution opens new questions: how many versions are you going to
mantain? and, if the answar is not "endless"... how to establish the
client dependencies?

To be continued...
 
M

mister catering

Well... there's a lot of material. I think we may stop and look at our
discussion (i think is more a contruction than a discussion).

The numbers in brackets correspond to the related message order number
(by date)

The original question was about c language... is or not enough the
language "as is" for programming fully reusable code?

We begin having a discussion about versioning. I said that it would be
desirable to be backward compatible (not forever) to allow gradual
migration. I think all we agree in this point. Chris Torek (16) and
Richard Heathfield (10) propossed two ways to do it with the c language
as is:

1.- Use static linking as much as possible (Richard)
2.- Use a diferent module for each mayor version change (Chris)

Michael Wojcik (11) propossed another way (the thirth) that implies a
programming discipline: Keep new functionality separate by means of new
function and variable names.

The three options are good solutions in my view but all of them, also
in my view, have problems that, if possible, must be avoided:

1.- As Jacob Navia (13) said clients need to relink with a new version
(mayor or minor) of a static library and this is not always possible
since it supposes a toolset that may not be available at cilent's site.
2.- To mantain a unique module name across mayor versions have
advantages. A new interface implementation can use code that is part of
the implementation of the "previous" interface. Furthermore, is very
easy to keep track with a "one file" component. You only need to know
the last change's date, inspect the metadata and decide if you are
interested in his new interfaces/implementations
3.- As i said (15) to have more than one name for the same semantics is
not desirable from the client's point of view. Furthermore, this
solution opens new questions: how many versions are you going to
mantain? and, if the answar is not "endless"... how to establish the
client dependencies?

To be continued...
 
R

Richard Heathfield

mister catering said:

1.- As Jacob Navia (13) said clients need to relink with a new version
(mayor or minor) of a static library and this is not always possible
since it supposes a toolset that may not be available at cilent's site.

As I explained earlier, typically an application vendor would do the linking
back at base, and ship the resulting executable rather than the static
library. This is no more disadvantageous than shipping a new DLL. In each
case:

* one file must be shipped
* the customer must stop running his program
* the file must be copied to the system by the user
* the program must be re-started

So it makes no odds either way from that perspective.

<snip>
 
M

Malcolm

Richard Heathfield said:
Ian Collins said:


That's fine if the system is well-managed... :)
That sort of thing caught me out yesteday.
I knocked up a program to demonstrate a concept. The function took streams
as parameters to I simply called tmpfile() and set them up. Worked fine on
my desktop. Wored fine on a mate's laptop. Took it in, and of course the
university computers won't give write permission to temporary files, so the
thign fell over.
 
M

Michael Wojcik

Michael Wojcik said:

And your point?

My point is that a good programmer should not refuse to use a
perfectly useful OS facility on the grounds that poor programmers
misuse that facility. Dynamic linking is not somehow contaminated by
others' misuse of it. Idiots should avoid it, but then they should
avoid creating programs for others' consumption at all. There is no
need for non-idiots to avoid it.
Not so. Just fix the bug and ship the executable, which is no harder than
fixing the bug and shipping the DLL.

I am tempted to quote Dan Pop.

If a library is used by only one executable, why make it a library?
If it is used by more than one executable, then a fix to the library
requires shipping fixed versions of all executables, if it's
statically linked.
Yep, that strategy works for me. In any case, the analogy is flawed. In your
home, space is at a premium (unless you are extremely wealthy), whereas
disk space and computer memory are relatively cheap.

This argument is common (indeed, nearly universal) among the opponents
of dynamic linking, but it is entirely specious. On a typical modern
general-purpose OS, replacing all the dynamically-linked code with
statically-linked code would present a resource cost far in excess of
the "relative cheapness" of disk space and memory.

On one machine here in front of me, running Windows XP Pro, I
currently have 68 userspace processes running. 2192 DLLs are loaded
by them, from 358 distinct images, so on average an image is reused 6
times. The Windows loader isn't particularly smart, and is unable to
share an in- memory image if it's relocated; but I have only 58
relocations among those 2192, so the relocation rate is less than 3%.
The average size of a loaded DLL is 558 KB. So if we assume an even
distribution[1], the memory cost for DLLs on this system right now is
something like 358 * 1.03 * 558 KB = 200 MB. If they were statically
linked instead, the cost would be something like 2192 * 558 KB = 1194
MB, or about six times as much. I don't care to buy six times as
much RAM as I currently have installed, thank you very much. And the
disk space cost is worse.

There may be good arguments against dynamic linking, but I haven't
heard any yet from the proponents of static linking. I argued this
in the letters column of DDJ some years ago, and I've argued it since
on Usenet, and all I ever hear from the anti-dynamic camp is
"versioning is hard!" and "many dynamic libraries are bad!". The
latter is true, and the former is debatable; but they say nothing
about dynamic linking as a technology. Using them as an excuse to
reject dynamic linking is to succumb to guilt by association.
Ironically, it's the same logic that motivates most tirades against C
itself.


[1] That assumption is obviously unwarranted, but the point of this
simplistic analysis is that even a back-of-the-envelope estimate
suggests the "cheap memory" argument doesn't hold, which puts the
burden of more sophisticated analysis on those who advance such an
argument.

--
Michael Wojcik (e-mail address removed)

However, we maintain that our mission is more than creating high-tech
amusement--rather, we must endeavor to provide high-tech, high-touch
entertainment with an emphasis on enkindling human warmth.
-- "The Ultimate in Entertainment", from the president of video game
producer Namco
 
M

Michael Wojcik

Michael Wojcik ha escrito:
mister catering said:

Imagine that you have
developed a library (YourLibrary) that is widely used by other
library/programs (Client1, Client2 ... ,ClientN). Programmer of Client1
knows about a new version of your library (YourLibrary 2.0) he is
interested in. He develop a new version of his program (Client1 2.0)
based on YourLibrary 2.0. [...]
Imagine a system
with all this clients installed... with the reusability style you
propose (that is the c reusability standard style) is not possible to
have Client1 2.0 and the rest of clients running at the same time.

Nonsense. If the library is designed with an ounce of sense, the
new version will be backward-compatible with the old. There's no
reason for it to be otherwise. New functionality can be provided by
new functions; old functionality can be left alone, or refactored as
cover routines that call the new functions with flags indicating that
the old behavior should be used. If the library is designed with a
bit more sense, the old functionality would already be forward-
compatible with new functionality thanks to reserved parameters,
behavior flags, and so forth.

Of course, you always can qualify the name of the new functions with
the version number...

You can, but that would be stupid. If they're *new functions*, they
have new names, which are not used by any previous users of the
library. If they're new versions of existing functions, then they
should be backward-compatible. There are a number of ways to achieve
such backward compatibility; some of them involve a bit of forethought,
but they are not unique in that respect, in the realm of programming.
by this way you are backward compatible and the
problem proposed is solved. But i think there's a price to avoid

What's that? A programming technique that is a tradeoff?
Remarkable!
Think i'm the user of the new version... with your solution I need to
change the names i was using, while the semantics could be the same.

No you don't. I don't know where you got this idea.
If
i was using the function "rotate" of YourLibrary and now i'm going to
use the more powerful "rotate" of YourLibrary 2.0 i'm not more
interested in the old rotate semantics.

I'm not entirely sure what this sentence is supposed to mean, but if
it's my library, then the version 2.0 "rotate" will be backward-
compatible with the version 1.0 "rotate", unless there are
extraordinary and compelling reasons to remove the 1.0 "rotate".
That would be a very rare case; I can't immediately think of any
justification for making such a change.
I don't need to distinguish the
two meanings (only the servers needs it) and I always prefer to see
"rotate" printed in my code than "YourLibrary__v2r0__rotate".

This naming convention is a straw man of your own invention.
do you think it would be desirable to preserve the operation names
(when necessary) across versions?

First, an aside: C doesn't have "operation names". It has operators,
which are predefined by the language and not affected by library
versions, and it has function names. Function names should be
descriptive, of course, and what they describe should refer in some
fashion to the operation they perform, but that does not mean that
functions should be named solely for the operation they perform (what
is "rotate" in this context anyway?).

Second, I don't believe you understood my description of the library-
versioning process. When a new version of a library is released, it
should be backward compatible with the previous version; that means
maintaining syntax and (aside from corrections) semantics of the
previous version, for all the functions supplied by the previous
version. Some of those functions may have a larger domain in the the
new release - for example, "reserved" parameters may now have useful
values. And there may be new functions. Neither of these things will
affect correctly-written programs that use the documented interface
of the previous version.

Correctly-written programs written to the documented interface of the
new version may use the old version's functions, if those suit its
needs, or they may use the new functions.

Really, I fail to see what's so difficult about this concept.

--
Michael Wojcik (e-mail address removed)

There are many definitions of what art is, but what I am convinced art is not
is self-expression. If I have an experience, it is not important because it
is mine. It is important because it's worth writing about for other people,
worth sharing with other people. That is what gives it validity. (Auden)
 
M

Michael Wojcik

I'm not sure that's so sensible.

I wrote a fairly lengthy response to this, then decided I wasn't
sure what you're talking about. What's the antecedent of "that"?
Are you complaining about dynamic-library backward compatibility, or
about the techniques I mention for forward-compatibility?

--
Michael Wojcik (e-mail address removed)

Some there are, brave, high-souled fellows, who could borrow the world to
play at ball, and never feel the responsibility, whereas others are uneasy
and not themselves with a single shilling that does not belong to them.
-- Arthur Ransome
 
R

Richard Heathfield

Michael Wojcik said:
My point is that a good programmer should not refuse to use a
perfectly useful OS facility on the grounds that poor programmers
misuse that facility.

Certainly true, and indeed there are certain environments where DLLs are
customarily handled very well indeed - mainframe environments, for example.
I am tempted to quote Dan Pop.

If a library is used by only one executable, why make it a library?

Planning ahead. :)
If it is used by more than one executable, then a fix to the library
requires shipping fixed versions of all executables, if it's
statically linked.

Indeed. In other words, each executable carries all its code with it, so
that it can't be messed up just by someone using the "wrong" DLL with it
(whether it's "wrong" because it's buggy, or because it's an old version,
or because it's a too-new version, or whatever). This can be seen as an
advantage or a disadvantage - it depends on your point of view.

<snip>
 
J

Joe Wright

Richard said:
Michael Wojcik said:


Certainly true, and indeed there are certain environments where DLLs are
customarily handled very well indeed - mainframe environments, for example.


Planning ahead. :)


Indeed. In other words, each executable carries all its code with it, so
that it can't be messed up just by someone using the "wrong" DLL with it
(whether it's "wrong" because it's buggy, or because it's an old version,
or because it's a too-new version, or whatever). This can be seen as an
advantage or a disadvantage - it depends on your point of view.

If I understand you Richard, I agree completely. Shared libraries and
especially Dynamically Linked Libraries (DLL's) leave me cold.
Frightened actually.

On my particular Windows XP install there are 2,228 dll files in the
system32 directory (folder ?).

Twenty or more of them have been written or refreshed in the last 60
days. I didn't do it! I wouldn't trust a .dll as far as I could throw it.
 
M

mister catering

... If they're new versions of existing functions, then they
should be backward-compatible. There are a number of ways to achieve
such backward compatibility; some of them involve a bit of forethought,
but they are not unique in that respect, in the realm of programming.

I think is possible (and frequent) to have a new version of a existing
function with a
new parameter in his signature. what way you propose to achieve such
change mantaining
backward compatibility?
 
M

mister catering

1.- As Jacob Navia (13) said clients need to relink with a new version
As I explained earlier, typically an application vendor would do the linking
back at base, and ship the resulting executable rather than the static
library.

I think this solution limits reusability because the only clients you
can have are application vendor (not final users). Think your library
is a grammar checker and the application is a word processor... they
may be different components (from the user's point of view).
Application vendor uses your library but only if the user decides to
pay the grammar checker's price.
 
P

Philip Potter

Who wrote the above lines? Your post references straight back to the OP, and
I'm not searching the entire thread to find these lines.

Please do not omit attribution lines in future. In addition, if your post
clearly follows-on from one other post, make sure it references that post.

<snip rest of post>

Philip
 
S

Skarmander

Michael said:
I wrote a fairly lengthy response to this, then decided I wasn't
sure what you're talking about. What's the antecedent of "that"?
Are you complaining about dynamic-library backward compatibility, or
about the techniques I mention for forward-compatibility?
Yes, I'm complaining about backward compatibility. I'm very much against it;
out with the old, in with the new.

But seriously, "that" referred to "[designing] libraries with a bit more
sense [...] thanks to reserved parameters, behavior flags, and so forth"; in
other words, forward compatibility on the function level. This technique is
rather brittle, and solves a problem (naming) that ought to have a cleaner
solution than changing around the semantics of existing code.

From an executable code point of view, the name of a function is its least
relevant part, and the reserved parameter technique makes no sense. Of
course, as programmers we know that how things are named makes a great deal
of difference, and it's not entirely reasonable to suggest everyone use
'defenestrate_foo4' and forget about the three deprecated predecessors, but
still.

S.
 
C

CBFalconer

mister said:
I think is possible (and frequent) to have a new version of a
existing function with a new parameter in his signature. what
way you propose to achieve such change mantaining backward
compatibility?

No, it is not possible. You create a new function with a different
name.

--
Some informative links:
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html
 
J

jacob navia

CBFalconer a écrit :
No, it is not possible. You create a new function with a different
name.

Unless you change ALL signatures to:

int myFn(int NbOfParameters,...);
// ... reserved for future use :)

But that would be quite an overkill :)
 
R

Richard Heathfield

mister catering said:
I think this solution limits reusability

All solutions limit reusability.
because the only clients you
can have are application vendor (not final users).

The responsibility for an program's functionality lies with the writer(s) of
the program. They must decide whether or not to incorporate the changed
library into their program. It is not the library writer's decision to
make.
Think your library
is a grammar checker and the application is a word processor... they
may be different components (from the user's point of view).

Typical users think of "the computer" as being a single component, alas.
More clueful users do exist, but they are relatively rare.
Application vendor uses your library but only if the user decides to
pay the grammar checker's price.

That's the user's decision to make.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,072
Latest member
trafficcone

Latest Threads

Top