[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Time to rewrite dpkg



On Wed, May 19, 1999 at 03:01:12PM -0700, Aaron Van Couwenberghe wrote:
> On Thu, May 20, 1999 at 12:50:19AM +1000, Anthony Towns wrote:
> > That seems... the wrong way around.
> see comments below ;P

Perhaps I should expand on that. The `Unix way' (yes, you can stop reading
this paragraph here, if you like) always seems to me to have been more along
the lines of "build a simple tool, then, if you want some grander, integrate
that into something grander". So you take grep and sed, and write a shell
script that uses them to get your `find the name of all users on the system'
program to work.

As opposed to writing a plugin to grep.

That's not to say plugins are bad, just that the alternative *does* work,
and *does* result in useful, expandable systems.

> > One alternative that's probably worth considering is improving libdpkg, so
> > that Apt and friends can make use of dpkg that way, and provide their own
> > front ends however they see fit.
> This isn't nearly the same scenario as I have in mind.

Yes, I realise this. That's why it's an alternative.

> Polymorphism is such an obvious pillar of structured programming that I
> can't understand how anybody could live without it.

You mean, I presume, that polymorphism is an obvious pillar of object
oriented programming.

Anyway. I'm not so convinced dpkg's core functionality (the grep part
of it, so to speak), really *needs* polymorphism all that much.

You have to process dependencies, you have to unpack and build .deb's, you
have to keep track of everything that's on the system, and be able to
install and remove stuff.

Now, one thing you can do is to replace `deb' with `package', and have
`deb' and `rpm' be two subclasses of package, each of which can be
installed and queried and unpacked and whatever. You could then add
`debdiff' or something to cope with bindiffs, and see where you go
from there. [0] That could be really useful.

Now sure -- that's polymorphism, you want to be able to do all the same
operations on a couple of completely different objects. But it's not
particularly complicated: you've got a single level of inheritance,
and an abstract base class.

struct PackageInfo {
    enum PackageType;
    char *name;
    void *PackageDetails;
    DependsList *getDependencies(struct PackageInfo *foo);
    void addDependency(struct PackageInfo *foo, struct PackageInfo *bar);
    ...
};

struct Deb {
    ...
};

Package myDebDetails = { ... };
Package myDeb = { DEB, "my", &myDebDetails, ... };

No, it's not pretty. But it's also not that ugly or that inconvenient in
this case. It's also trivially usable directly from C.

Note that you can probably also get away with keeping all of the
DebDetails completely private -- as long as libdpkg knows it's an rpm or
a bindiff and can cope, dpkg(1) doesn't really have to care *that* much.

But I dunno. Perhaps a better thing to do would be to write a
library in C++, but just limit its exported symbols to be `extern "C"'
functions. Then have a nice C++ based program like Apt that has its own
inheritance and whatever else to cope with access methods, and selection
preferences and whatever else.

> > In particular, there are established ways of linking programs written in
> > any language against C based libraries. As far as I'm aware doing the same
> > to C++ (or other object-oriented languages) is a pain in the neck.
> This is simply not true.

If it's not true, you won't have any problem countering all the problems then,
will you?

How do you propose cope with the fragile base class problem? (ie, having
to recompile every C++ app that uses a library everytime a base class in
that library changes -- for example you decide that "Versioned Provides"
needs a different function prototype than the old "Provides" did)

How do you cope with differences in name-mangling? Or are we simply
willing to say `you'll use egcs' name mangling. If egcs decides to do
different name mangling later, we'll do a major revision of libdpkg so
new programs can link to it'?

How do you integrate C++ objects with C, Objective-C, Python, Perl, etc?

With C, you either don't export your structures, or you have enough
control over how your structures are used that you can avoid having
fragile base classes entirely exactly where necessary; and people have
already written all the wrapper functionality and integrated it with
their languages, so that `linking to C' is generally a documented feature.

> > And I don't particularly think it's much of a gain to say "You want
> > access to dpkg's internals? Just use C++!". C++ is all well and good,
> > but it's not *that* good.
> No, there are leaps and bounds to be made by this sort of organization.
> Basically, any one feature or behavioural pragma need only be implemented in
> one component; afterwards it's applicable to all future setups.

Object orientated design does not imply C++. It doesn't even imply
a language that natively supports object oriented programming, just
as structured programming doesn't require a language with control
structures other than goto. Yes, C++ might make this easier, but there
*are* tradeoffs, and you'd do well to consider them.

Cheers,
aj

[0] .md5sums might be useful for bindiffs, btw. Anything not listed in the
    old md5sums gets included in the bindiff, as does anything
    whose md5sum is different, including the list of md5sums itself.
    This doesn't let you include only parts of files, but does only
    require you to have to old md5sums file, not the whole .deb, and
    seems pretty easy to actually implement.

    For those of you playing along at home, this is related to a thread on
    debian-policy atm.

-- 
Anthony Towns <aj@humbug.org.au> <http://azure.humbug.org.au/~aj/>
I don't speak for anyone save myself. PGP encrypted mail preferred.

       ``There's nothing worse than people with a clue.
             They're always disagreeing with you.'' 
                                 -- Andrew Over

Attachment: pgpMlGg2JUGSv.pgp
Description: PGP signature


Reply to: