Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #12027 > unrolled thread
| Started by | Heck <heckja_in@ordertostymieharvestersverizon.net> |
|---|---|
| First post | 2011-12-02 13:50 -0500 |
| Last post | 2011-12-11 17:02 -0500 |
| Articles | 15 — 8 participants |
Back to article view | Back to comp.lang.c++
only call dtor of derived class? Heck <heckja_in@ordertostymieharvestersverizon.net> - 2011-12-02 13:50 -0500
Re: only call dtor of derived class? Victor Bazarov <v.bazarov@comcast.invalid> - 2011-12-02 16:50 -0500
Re: only call dtor of derived class? Heck <heckja_in@ordertostymieharvestersverizon.net> - 2011-12-03 22:01 -0500
Re: only call dtor of derived class? jt@toerring.de (Jens Thoms Toerring) - 2011-12-03 00:32 +0000
Re: only call dtor of derived class? Heck <heckja_in@ordertostymieharvestersverizon.net> - 2011-12-03 22:07 -0500
Re: only call dtor of derived class? Heck <heckja_in@ordertostymieharvestersverizon.net> - 2011-12-04 18:08 -0500
Re: only call dtor of derived class? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2011-12-04 22:07 -0500
Re: only call dtor of derived class? Stuart Redmann <DerTopper@web.de> - 2011-12-04 23:36 -0800
Re: only call dtor of derived class? Werner <werasm@gmail.com> - 2011-12-05 00:53 -0800
Re: only call dtor of derived class? Stuart Redmann <DerTopper@web.de> - 2011-12-05 04:33 -0800
Re: only call dtor of derived class? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2011-12-11 18:47 -0500
Re: only call dtor of derived class? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2011-12-11 18:26 -0500
Re: only call dtor of derived class? Juha Nieminen <nospam@thanks.invalid> - 2011-12-05 13:00 +0000
Re: only call dtor of derived class? Goran <goran.pusic@gmail.com> - 2011-12-05 05:12 -0800
Re: only call dtor of derived class? Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2011-12-11 17:02 -0500
| From | Heck <heckja_in@ordertostymieharvestersverizon.net> |
|---|---|
| Date | 2011-12-02 13:50 -0500 |
| Subject | only call dtor of derived class? |
| Message-ID | <cu5id7l8bgtqdmm8udluq4batgujd09cpd@4ax.com> |
Can it be (easily) arranged to call only the destructor of a derived class, and call none of the destructors in the classes from which it derives? This may seem to seek to negate the simple and compelling value of the destructor tree, so, perhaps my design is flawed, but, perhaps not. I wrote the classes I'm wrestling with to handle memory-mapped files. The files that already exist require different sharing and access rights and different attributes than the files that are to be created and the files that are to be created are to be resized upon completion (extra bytes removed). Rather than pass in a small slew of args to effect this, I just wrote the sequence of calls twice, each set appropriately parameterized. With respect to the constructors, the derived classes happen to require parameters the base class does not, so, with that I can call the constructors appropriately, but as far as the destructors, it's either not allowed or it is and I don't know how to control which class gets which series of destructors called for it. I've pointers in the base class that I want to use in the derived classes. Simple tests in the base class' destructor will suffice to restrict the execution to the approriate objects, but, is there a way C++'s semantics of inheritance facilitates such a scenario? Thanks
[toc] | [next] | [standalone]
| From | Victor Bazarov <v.bazarov@comcast.invalid> |
|---|---|
| Date | 2011-12-02 16:50 -0500 |
| Message-ID | <jbbh76$snv$1@dont-email.me> |
| In reply to | #12027 |
On 12/2/2011 1:50 PM, Heck wrote: > Can it be (easily) arranged to call only the destructor of a derived > class, and call none of the destructors in the classes from which it > derives? This may seem to seek to negate the simple and compelling > value of the destructor tree, so, perhaps my design is flawed,[..] No, and certainly. V -- I do not respond to top-posted replies, please don't ask
[toc] | [prev] | [next] | [standalone]
| From | Heck <heckja_in@ordertostymieharvestersverizon.net> |
|---|---|
| Date | 2011-12-03 22:01 -0500 |
| Message-ID | <7jold7tdvlbqbf3e29obev8vtapd73vvrs@4ax.com> |
| In reply to | #12033 |
On Fri, 02 Dec 2011 16:50:30 -0500, Victor Bazarov <v.bazarov@comcast.invalid> wrote: >On 12/2/2011 1:50 PM, Heck wrote: >> Can it be (easily) arranged to call only the destructor of a derived >> class, and call none of the destructors in the classes from which it >> derives? This may seem to seek to negate the simple and compelling >> value of the destructor tree, so, perhaps my design is flawed,[..] > >No, and certainly. > >V Ouch. You should be glad to have had this opportunity to be so amusing.
[toc] | [prev] | [next] | [standalone]
| From | jt@toerring.de (Jens Thoms Toerring) |
|---|---|
| Date | 2011-12-03 00:32 +0000 |
| Message-ID | <9jt913FpolU1@mid.uni-berlin.de> |
| In reply to | #12027 |
Heck <heckja_in@ordertostymieharvestersverizon.net> wrote:
> Can it be (easily) arranged to call only the destructor of a derived
> class, and call none of the destructors in the classes from which it
> derives? This may seem to seek to negate the simple and compelling
> value of the destructor tree, so, perhaps my design is flawed, but,
> perhaps not.
> I wrote the classes I'm wrestling with to handle memory-mapped files.
> The files that already exist require different sharing and access
> rights and different attributes than the files that are to be created
> and the files that are to be created are to be resized upon completion
> (extra bytes removed).
> Rather than pass in a small slew of args to effect this, I just wrote
> the sequence of calls twice, each set appropriately parameterized.
> With respect to the constructors, the derived classes happen to
> require parameters the base class does not, so, with that I can call
> the constructors appropriately, but as far as the destructors, it's
> either not allowed or it is and I don't know how to control which
> class gets which series of destructors called for it.
> I've pointers in the base class that I want to use in the derived
> classes.
> Simple tests in the base class' destructor will suffice to restrict
> the execution to the approriate objects, but, is there a way C++'s
> semantics of inheritance facilitates such a scenario?
As Victor has put it short and bluntly you're on the wrong
track. Not only can't that be done but you're violating one
of the most basic principles of OOP, i.e. that inheritance
is all about an "is-a" relationship. If for the derived class
the destructor of the base class can't be called for what-
ever reasons then the derived class isn't an object of the
type that is a specialization of the type of object the base
class is for. Even when you have to check in the base class
what actual kind of oject it's dealing with (as you seem to
consider as a "fix") you're on the wrong path.
A base class must never, ever have any idea what it's derived
classes do look like whatsoever. If it does it's already too
specialized for being a base class you can derive all the
types you want to from.
What you seen to be having here is a case like a base class
for vehicles where you started your design with the assump-
tion that all vehicles have an engine that can be switched
on and off. Thus you may have something to switch off thed
engine in the destructor of the "Vehicle" class. And that
works quite nicely for cars, motorcycles, lorries, most
airplanes etc. But then you realize that you also want to
have bicycles and gliders - and suddenly everything seems
to break down. You now ask if there's a way to avoid having
the destructor getting called that switches off the (non-
existent) engine. But the problem is that your base class
is simply too specialized.
Instead of "repairing" things in the base class by testing
if the vehicle has an engine and make it behave accordingly
(thus forcing the base class to be "aware" of what additional
properties its descendants can have) create a new, more
general class that doesn't know about the existence of an
engine and create two intermediate base classes, both in-
heriting from the original base class, that are for vehicles
with and without an engine. Now make your already existing
derived classes derive from the new intermediate class for
"vehicle with an engine" while deriving bicycles and gliders
from the new internediate class for "vehicle without an
engine".
The way you describe your problem it looks as if you started
with the assumption that memory-mapped files are all the same,
so having a single base class for them looked reasonable. But
now you've recognized that the property of just being "memory-
mapped" isn't what they all have in common. So revise your base
class to contain only what's common to all of them and create
intermediate classes you can derive from the more specialized
cases where there aren't any issues when all the destructors
are called.
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
[toc] | [prev] | [next] | [standalone]
| From | Heck <heckja_in@ordertostymieharvestersverizon.net> |
|---|---|
| Date | 2011-12-03 22:07 -0500 |
| Message-ID | <clold7diidtq80a23qnrtd2skrnlvaa4ar@4ax.com> |
| In reply to | #12036 |
On 3 Dec 2011 00:32:35 GMT, jt@toerring.de (Jens Thoms Toerring) wrote: >Heck <heckja_in@ordertostymieharvestersverizon.net> wrote: >> Can it be (easily) arranged to call only the destructor of a derived >> class, and call none of the destructors in the classes from which it >> derives? This may seem to seek to negate the simple and compelling >> value of the destructor tree, so, perhaps my design is flawed, but, >> perhaps not. > >> I wrote the classes I'm wrestling with to handle memory-mapped files. >> The files that already exist require different sharing and access >> rights and different attributes than the files that are to be created >> and the files that are to be created are to be resized upon completion >> (extra bytes removed). > >> Rather than pass in a small slew of args to effect this, I just wrote >> the sequence of calls twice, each set appropriately parameterized. >> With respect to the constructors, the derived classes happen to >> require parameters the base class does not, so, with that I can call >> the constructors appropriately, but as far as the destructors, it's >> either not allowed or it is and I don't know how to control which >> class gets which series of destructors called for it. > >> I've pointers in the base class that I want to use in the derived >> classes. > >> Simple tests in the base class' destructor will suffice to restrict >> the execution to the approriate objects, but, is there a way C++'s >> semantics of inheritance facilitates such a scenario? > >As Victor has put it short and bluntly you're on the wrong >track. Not only can't that be done but you're violating one >of the most basic principles of OOP, i.e. that inheritance >is all about an "is-a" relationship. If for the derived class >the destructor of the base class can't be called for what- >ever reasons then the derived class isn't an object of the >type that is a specialization of the type of object the base >class is for. Even when you have to check in the base class >what actual kind of oject it's dealing with (as you seem to >consider as a "fix") you're on the wrong path. > >A base class must never, ever have any idea what it's derived >classes do look like whatsoever. If it does it's already too >specialized for being a base class you can derive all the >types you want to from. > >What you seen to be having here is a case like a base class >for vehicles where you started your design with the assump- >tion that all vehicles have an engine that can be switched >on and off. Thus you may have something to switch off thed >engine in the destructor of the "Vehicle" class. And that >works quite nicely for cars, motorcycles, lorries, most >airplanes etc. But then you realize that you also want to >have bicycles and gliders - and suddenly everything seems >to break down. You now ask if there's a way to avoid having >the destructor getting called that switches off the (non- >existent) engine. But the problem is that your base class >is simply too specialized. > >Instead of "repairing" things in the base class by testing >if the vehicle has an engine and make it behave accordingly >(thus forcing the base class to be "aware" of what additional >properties its descendants can have) create a new, more >general class that doesn't know about the existence of an >engine and create two intermediate base classes, both in- >heriting from the original base class, that are for vehicles >with and without an engine. Now make your already existing >derived classes derive from the new intermediate class for >"vehicle with an engine" while deriving bicycles and gliders >from the new internediate class for "vehicle without an >engine". > >The way you describe your problem it looks as if you started >with the assumption that memory-mapped files are all the same, >so having a single base class for them looked reasonable. But >now you've recognized that the property of just being "memory- >mapped" isn't what they all have in common. So revise your base >class to contain only what's common to all of them and create >intermediate classes you can derive from the more specialized >cases where there aren't any issues when all the destructors >are called. > Regards, Jens Yes, I understand. I agree my conception was flawed. In C, you can start with a flawed design such as this and make it work despite its deficiencies. This illustrates that C++ is both more powerful and more precise in its semantics than C. Thanks for your detailed and helpful reply.
[toc] | [prev] | [next] | [standalone]
| From | Heck <heckja_in@ordertostymieharvestersverizon.net> |
|---|---|
| Date | 2011-12-04 18:08 -0500 |
| Message-ID | <12vnd7ddptspj740m2uc43cc6lummn4d2l@4ax.com> |
| In reply to | #12045 |
On Sat, 03 Dec 2011 22:07:56 -0500, Heck <heckja_in@ordertostymieharvestersverizon.net> wrote: >On 3 Dec 2011 00:32:35 GMT, jt@toerring.de (Jens Thoms Toerring) >wrote: > >>Heck <heckja_in@ordertostymieharvestersverizon.net> wrote: >>> Can it be ...my design is flawed... >>As Victor has put it short and bluntly you're on the wrong >>track. Not only can't that be done but you're violating one >>of the most basic principles of OOP, i.e. that inheritance >>is all about an "is-a" relationship. If for the derived class >>the destructor of the base class can't be called for what- >>ever reasons then the derived class isn't an object of the >>type that is a specialization of the type of object the base >>class is for. Even when you have to check in the base class >>what actual kind of oject it's dealing with (as you seem to >>consider as a "fix") you're on the wrong path. >> >>A base class must never, ever have any idea what it's derived >>classes do look like whatsoever. If it does it's already too >>specialized for being a base class you can derive all the >>types you want to from. >> >>What you seen to be having here is a case like a base class >>for vehicles where you started your design with the assump- >>tion that all vehicles have an engine that can be switched >>on and off. Thus you may have something to switch off thed >>engine in the destructor of the "Vehicle" class. And that >>works quite nicely for cars, motorcycles, lorries, most >>airplanes etc. But then you realize that you also want to >>have bicycles and gliders - and suddenly everything seems >>to break down. You now ask if there's a way to avoid having >>the destructor getting called that switches off the (non- >>existent) engine. But the problem is that your base class >>is simply too specialized. >> >>Instead of "repairing" things in the base class by testing >>if the vehicle has an engine and make it behave accordingly >>(thus forcing the base class to be "aware" of what additional >>properties its descendants can have) create a new, more >>general class that doesn't know about the existence of an >>engine and create two intermediate base classes, both in- >>heriting from the original base class, that are for vehicles >>with and without an engine. Now make your already existing >>derived classes derive from the new intermediate class for >>"vehicle with an engine" while deriving bicycles and gliders >>from the new internediate class for "vehicle without an >>engine". >> >>The way you describe your problem it looks as if you started >>with the assumption that memory-mapped files are all the same, >>so having a single base class for them looked reasonable. But >>now you've recognized that the property of just being "memory- >>mapped" isn't what they all have in common. So revise your base >>class to contain only what's common to all of them and create >>intermediate classes you can derive from the more specialized >>cases where there aren't any issues when all the destructors >>are called. >> Regards, Jens > >Yes, I understand. I agree my conception was flawed. In C, you can >start with a flawed design such as this and make it work despite its >deficiencies. This illustrates that C++ is both more powerful and >more precise in its semantics than C. Thanks for your detailed and >helpful reply. I don't mean to say that you can't simply make something flawed work in C++, as you can in C. C++ is just as flexible as C. The advantage of C++ over C in this regard is that it pragmatically encourages a coder to design and write clearly, and to some degree even promotes clear thinking.
[toc] | [prev] | [next] | [standalone]
| From | Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> |
|---|---|
| Date | 2011-12-04 22:07 -0500 |
| Message-ID | <4edc3576$0$2569$c3e8da3$f5af001f@news.astraweb.com> |
| In reply to | #12056 |
Heck wrote: > On Sat, 03 Dec 2011 22:07:56 -0500, Heck > <heckja_in@ordertostymieharvestersverizon.net> wrote: > >> On 3 Dec 2011 00:32:35 GMT, jt@toerring.de (Jens Thoms Toerring) >> wrote: >> >>> Heck<heckja_in@ordertostymieharvestersverizon.net> wrote: >>>> Can it be ...my design is flawed... > >>> As Victor has put it short and bluntly you're on the wrong >>> track. Not only can't that be done but you're violating one >>> of the most basic principles of OOP, i.e. that inheritance >>> is all about an "is-a" relationship. If for the derived class >>> the destructor of the base class can't be called for what- >>> ever reasons then the derived class isn't an object of the >>> type that is a specialization of the type of object the base >>> class is for. Even when you have to check in the base class >>> what actual kind of oject it's dealing with (as you seem to >>> consider as a "fix") you're on the wrong path. >>> >>> A base class must never, ever have any idea what it's derived >>> classes do look like whatsoever. If it does it's already too >>> specialized for being a base class you can derive all the >>> types you want to from. >>> >>> What you seen to be having here is a case like a base class >>> for vehicles where you started your design with the assump- >>> tion that all vehicles have an engine that can be switched >>> on and off. Thus you may have something to switch off thed >>> engine in the destructor of the "Vehicle" class. And that >>> works quite nicely for cars, motorcycles, lorries, most >>> airplanes etc. But then you realize that you also want to >>> have bicycles and gliders - and suddenly everything seems >>> to break down. You now ask if there's a way to avoid having >>> the destructor getting called that switches off the (non- >>> existent) engine. But the problem is that your base class >>> is simply too specialized. >>> >>> Instead of "repairing" things in the base class by testing >>> if the vehicle has an engine and make it behave accordingly >>> (thus forcing the base class to be "aware" of what additional >>> properties its descendants can have) create a new, more >>> general class that doesn't know about the existence of an >>> engine and create two intermediate base classes, both in- >>> heriting from the original base class, that are for vehicles >>> with and without an engine. Now make your already existing >>> derived classes derive from the new intermediate class for >>> "vehicle with an engine" while deriving bicycles and gliders >> >from the new internediate class for "vehicle without an >>> engine". >>> >>> The way you describe your problem it looks as if you started >>> with the assumption that memory-mapped files are all the same, >>> so having a single base class for them looked reasonable. But >>> now you've recognized that the property of just being "memory- >>> mapped" isn't what they all have in common. So revise your base >>> class to contain only what's common to all of them and create >>> intermediate classes you can derive from the more specialized >>> cases where there aren't any issues when all the destructors >>> are called. >>> Regards, Jens >> >> Yes, I understand. I agree my conception was flawed. In C, you can >> start with a flawed design such as this and make it work despite its >> deficiencies. This illustrates that C++ is both more powerful and >> more precise in its semantics than C. Thanks for your detailed and >> helpful reply. > > I don't mean to say that you can't simply make something flawed work > in C++, as you can in C. C++ is just as flexible as C. The advantage > of C++ over C in this regard is that it pragmatically encourages a > coder to design and write clearly, and to some degree even promotes > clear thinking. Generalizations you said and heard are both right and wrong. OOP is a mixed blessing. C++ (and OOP) make you "design for future" and no one knows the future. Changes in the requirements often alter what are "the right things" to hide and expose; and then the cognitive biases and non-technical issues stand in a way of re-designing the class structure all over again as it would be appropriate "in an ideal world". The result is often much messier than in procedural-oriented language. A case in point is Linux kernel: it is not only because of its low-level nature is it beneficial that it is written in C rather than C++: it is also because the kernel is extremely dynamic, the whole subsystems are being fully re-written between minor versions *and their roles and responsibilities (separation of duties) are changing at that*. OOP works well when roles and responsibilities of base classes are relatively stable; this is far from true in many subject areas. Sometimes even in well-defined areas programming with classes is more limiting and creates less usable legacy than programming with subroutines/functions only. A good example are matrix manipulation libraries. If you choose to manipulate with matrices in an old-fashion FORTRAN way (i.e. based on conventions about matrix internal representation and adding functions perusing it which is a mortal sin in OOP), your can reuse the libraries written as far back as in 70th (NAG, IMSL, SSP etc) from your C++ or C program and all these are data-compatible each with other. What I mean by that, you can allocate and initialize internal representations (arrays) in C++, call some subroutines from NAG, call SSP subroutines from SSP on the results, then call your own C function you wrote decades later etc. all without any extra copying or conversions. On the other hand, I have yet to see a pair of C++ matrix manipulation libraries that could re-use one another's matrices without copying/conversions. Back to your original problem, I am not sure what the responsibilities of the base class were and why the destructor of the base class should have done anything non-common (I would only do unmapping there based on the information you gave; closing could be done right after mapping in constructors if you write for a POSIX-compliant system; resizing etc. could be done in derived classes only). If you showed your tentative hierarchy structure, it would be easier to help. Just a thought, -Pavel
[toc] | [prev] | [next] | [standalone]
| From | Stuart Redmann <DerTopper@web.de> |
|---|---|
| Date | 2011-12-04 23:36 -0800 |
| Message-ID | <0a902d12-0323-4cf6-a5a5-5f118c15d3de@u5g2000vbd.googlegroups.com> |
| In reply to | #12059 |
Sorry for interrupting your discussion On 5 Dez., Pavel wrote: > [snip]. > OOP is a mixed blessing. C++ (and OOP) make you "design for future" > and no one knows the future. Changes in the requirements often alter > what are "the right things" to hide and expose; and then the cognitive > biases and non-technical issues stand in a way of re-designing the class > structure all over again as it would be appropriate "in an ideal world". > The result is often much messier than in procedural-oriented language. I found a nice page that might be of interest to you: http://reocities.com/tablizer/oopbad.htm There is also a very sweet observation about communism in it. > A case in point is Linux kernel: it is not only > because of its low-level nature is it beneficial that it is written in C rather > than C++: it is also because the kernel is extremely dynamic, the whole > subsystems are being fully re-written between minor versions *and their > roles and responsibilities (separation of duties) are changing at that*. > OOP works well when roles and responsibilities of base classes are > relatively stable; this is far from true in many subject areas. I thought that Linus didn't want to use C++ because C++ uses much more stack memory (which is quite limited in the kernel). Perhaps I should do some research... However, even if we only used procedural programming under Linux, it would still be quite nice to use objects in the functions. Whole chapters in Linux tutorials are dedicated to the containers (mostly lists) inside the kernel. If Linux were written under C++, we would never have to read those chapters. I agree that many problem-spaces cannot be adequately structured by OOD, but that should not mean that we should design each and every sub- problem-space in an procedural way. The beauty of C++ is that we can use both design paradigms at the same time. Besides, C++ offers more than just OOD (think of generics). > Sometimes even in well-defined areas programming with classes is more > limiting and creates less usable legacy than programming with > subroutines/functions only. A good example are matrix manipulation > libraries. If you choose to manipulate with matrices in an old-fashion > FORTRAN way (i.e. based on conventions about matrix internal > representation and adding functions perusing it which is a mortal sin > in OOP), your can reuse the libraries written as far back as in 70th > (NAG, IMSL, SSP etc) from your C++ or C program and all these are > data-compatible each with other. What I mean by that, you can allocate > and initialize internal representations (arrays) in C++, call some > subroutines from NAG, call SSP subroutines from SSP on the results, > then call your own C function you wrote decades later etc. all > without any extra copying or conversions. > > On the other hand, I have yet to see a pair of C++ matrix manipulation > libraries that could re-use one another's matrices without > copying/conversions. [snip] My co-worker spent quite some time to write a C++ wrapper for the BLAS library so that he can use operator+ and operator*. Such simple things make the code much more readable. Why can't we do that under C? Regards, Stuart
[toc] | [prev] | [next] | [standalone]
| From | Werner <werasm@gmail.com> |
|---|---|
| Date | 2011-12-05 00:53 -0800 |
| Message-ID | <7e1f8eb8-bfe2-43a3-a1e0-077ed9dbb209@13g2000vbu.googlegroups.com> |
| In reply to | #12064 |
On Dec 5, 9:36 am, Stuart Redmann <DerTop...@web.de> wrote: > Sorry for interrupting your discussion > > On 5 Dez., Pavel wrote: > > > [snip]. > > OOP is a mixed blessing. C++ (and OOP) make you "design for future" > > and no one knows the future. Changes in the requirements often alter > > what are "the right things" to hide and expose; and then the cognitive > > biases and non-technical issues stand in a way of re-designing the class > > structure all over again as it would be appropriate "in an ideal world". > > The result is often much messier than in procedural-oriented language. > > I found a nice page that might be of interest to you:http://reocities.com/tablizer/oopbad.htm > There is also a very sweet observation about communism in it. I did not read all the oopbad stuff, but I've seen a lot of bad code due to programming in OOP languages without OOD. I've also found that using good OOD in conjunction templates allows one to reuse and share code. Especially SRP (Single Responsibility Principle). I've also noticed that many a procedural programming uses some form of pseudo OOD to organize his code, in fact - almost all of the ones I've seen do this (Even if this means using some directory structure or file for related functions). OOD gives us the means to factorize the organization/architecture into byte sizes, heh? OT: About communism (and maybe this is your point too): Perfect communism would make perfect sense. As reference you can consider the early church in Acts (The Bible). Perfect OOP perhaps too? Yes, early 20th century to modern day communism have capitalist leaders, hence it does not make sense ;-). They are into "self-enrichment", and living at the cost of others. Perhaps many OOD programs have C programmers running the design (with respect)? Capitalism... - Will evolve something terrible yet, the consequences far worse (global, perhaps catastrophical). Regards, Werner
[toc] | [prev] | [next] | [standalone]
| From | Stuart Redmann <DerTopper@web.de> |
|---|---|
| Date | 2011-12-05 04:33 -0800 |
| Message-ID | <17340084-0106-4cc4-af8d-8d3b8b6cabfa@d10g2000vbk.googlegroups.com> |
| In reply to | #12067 |
On Dec 5, Stuart Redmann wrote: > > I found a nice page that might be of interest to > > you:http://reocities.com/tablizer/oopbad.htm > > There is also a very sweet observation about communism in it. On 5 Dez., Werner wrote: > I did not read all the oopbad stuff, but I've seen a lot > of bad code due to programming in OOP languages without OOD. This is very likely the reason why many don't like OOP: If you use it badly, you'll screw it up much more magnificently ;-) Seriously, I think that the author of http://reocities.com/tablizer/oopbad.htm wants to say that there are some problems that can never, ever be accurately represented in an OO manner, no matter how much effort you spend in OOD. I would agree, since I recently encountered some data- driven problem where OO does not make much sense. [snip] On 5 Dez., Werner wrote: > OT: > > About communism (and maybe this is your point too): > > Perfect communism would make perfect sense. As reference > you can consider the early church in Acts (The Bible). > Perfect OOP perhaps too? Yes, early 20th century to > modern day communism have capitalist leaders, hence it > does not make sense ;-). They are into "self-enrichment", > and living at the cost of others. Perhaps many OOD > programs have C programmers running the design (with > respect)? In fact, I didn't have this in mind, I just found the remark about communism quite concise. Regards, Stuart
[toc] | [prev] | [next] | [standalone]
| From | Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> |
|---|---|
| Date | 2011-12-11 18:47 -0500 |
| Message-ID | <4ee5412f$0$2777$c3e8da3$3a1a2348@news.astraweb.com> |
| In reply to | #12067 |
Werner wrote: > On Dec 5, 9:36 am, Stuart Redmann<DerTop...@web.de> wrote: >> Sorry for interrupting your discussion >> >> On 5 Dez., Pavel wrote: >> >>> [snip]. >>> OOP is a mixed blessing. C++ (and OOP) make you "design for future" >>> and no one knows the future. Changes in the requirements often alter >>> what are "the right things" to hide and expose; and then the cognitive >>> biases and non-technical issues stand in a way of re-designing the class >>> structure all over again as it would be appropriate "in an ideal world". >>> The result is often much messier than in procedural-oriented language. >> >> I found a nice page that might be of interest to you:http://reocities.com/tablizer/oopbad.htm >> There is also a very sweet observation about communism in it. > > I did not read all the oopbad stuff, but I've seen a lot > of bad code due to programming in OOP languages without OOD. > > I've also found that using good OOD in conjunction templates > allows one to reuse and share code. Especially SRP (Single > Responsibility Principle). > > I've also noticed that many a procedural programming > uses some form of pseudo OOD to organize his code, in > fact - almost all of the ones I've seen do this (Even > if this means using some directory structure or file > for related functions). > > OOD gives us the means to factorize the > organization/architecture into byte sizes, heh? > > OT: > > About communism (and maybe this is your point too): > > Perfect communism would make perfect sense. Perfect communism with real people (and I do not mean leaders; those actually had to be perfect-for-communism) did exist. Maoism/Stalinism/Khmer rogue regimes are good examples. Perfect communism with perfect-for-communism people does make logical sense but be careful in you wishes (even after forgetting about implementation issues). There are plentiful examples of such communism in the Nature: ants in ant house, bees in a heave, cells in your body. Would you care to become either? > As reference > you can consider the early church in Acts (The Bible). > Perfect OOP perhaps too? Yes, early 20th century to > modern day communism have capitalist leaders, hence it > does not make sense ;-). They are into "self-enrichment", > and living at the cost of others. Perhaps many OOD > programs have C programmers running the design (with > respect)? Or perhaps OOD is just slightly less practical than it is often thought of and advertised? > > Capitalism... > > - Will evolve something terrible yet, the consequences > far worse (global, perhaps catastrophical). And communism would never do such a thing, would it? > > Regards, > > Werner > > Regards, -Pavel
[toc] | [prev] | [next] | [standalone]
| From | Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> |
|---|---|
| Date | 2011-12-11 18:26 -0500 |
| Message-ID | <4ee53c10$0$2893$c3e8da3$dbd57e7@news.astraweb.com> |
| In reply to | #12064 |
Stuart Redmann wrote:
> Sorry for interrupting your discussion
>
> On 5 Dez., Pavel wrote:
>> [snip].
>> OOP is a mixed blessing. C++ (and OOP) make you "design for future"
>> and no one knows the future. Changes in the requirements often alter
>> what are "the right things" to hide and expose; and then the cognitive
>> biases and non-technical issues stand in a way of re-designing the class
>> structure all over again as it would be appropriate "in an ideal world".
>> The result is often much messier than in procedural-oriented language.
>
>
> I found a nice page that might be of interest to you:
> http://reocities.com/tablizer/oopbad.htm
Thank you very much, it was a very interesting article: makes some valid points.
Slightly too extreme, to my taste; but otherwise, gives a lot of food for thought.
> There is also a very sweet observation about communism in it.
Even though what it tells about communism is more or less accurate, the analogy
is little lame: the communism does not work (in a sense that people would want
it to work that is; in some technical sense it does work -- but you don't want
to live in THAT society) because of faulty design (ignoring generally known
facts about human nature is only one of the flaws). On the other hand, where OO
works poorly, it does so due to unpredictability of change requirements. I would
not go so far to say applying OO is always wrong; I would not even say it is
always humanly possible to say whether OO is going to benefit a particular
project (all because of no one knows the future, even that of a simple software
project future).
Trying to deduce at least a semi-useful practical conclusion of the above:
business managers who try hard to explain "the big picture" to their software
teamd and fire those who does not listen are doing themselves a big favor. And
vice versa.
>
>
>> A case in point is Linux kernel: it is not only
>> because of its low-level nature is it beneficial that it is written in C rather
>> than C++: it is also because the kernel is extremely dynamic, the whole
>> subsystems are being fully re-written between minor versions *and their
>> roles and responsibilities (separation of duties) are changing at that*.
>> OOP works well when roles and responsibilities of base classes are
>> relatively stable; this is far from true in many subject areas.
>
>
> I thought that Linus didn't want to use C++ because C++ uses much more
> stack memory (which is quite limited in the kernel). Perhaps I should
> do some research...
Nah, Linus is finicky about many things, C++ included -- but he is a very smart
guy, so it will certainly entertain you to read what he really thinks of C++.
Just google "Linus Torvalds about C++" -- you won't miss *that* piece.
Stack size *is* an issue; but less of it these days; in older day, EPOC32
"Embedded C++" solved this issue by limiting exception mechanisms in quite
annoying matter (especially given their OS interface actually used exception)
but that limitation did not affect C++ OO-related features.
> However, even if we only used procedural programming under Linux, it
> would still be quite nice to use objects in the functions. Whole
> chapters in Linux tutorials are dedicated to the containers (mostly
> lists) inside the kernel. If Linux were written under C++, we would
> never have to read those chapters.
Yes and no.. intrusive lists that are mostly there certainly can be modeled in
C++ classes (in fact my recent projects involved such modeling); but, to be
completely honest, being in a position to both design and use these (what can be
less problematic), I cannot sincerely testify that "C++ way" brought up lots of
advantages with it (and it surely brought increased compilation time which is
soooooooo annoying and code bloating; quite moderate but I would not want it in
my kernel). I feel like I could live with C functions to manipulate lists.
But you touched on an IMHO fundamental question of how bad is exposing the dat
structure. My point is that exposing a really simple and reusable structure (I
remember I mentioned Linux kernel was very dynamic, but its lists in particular
are so fundamental and so simple that they stay mainly intact) is not always
evil (but you already know it from my FORTRAN matrix examples).
>
> I agree that many problem-spaces cannot be adequately structured by
> OOD, but that should not mean that we should design each and every sub-
> problem-space in an procedural way. The beauty of C++ is that we can
> use both design paradigms at the same time. Besides, C++ offers more
> than just OOD (think of generics).
I agree, of course. My personal complaints about C++ though is not that it has
OO-features but that it requires keeping bigger context in my head to understand
the meaning of given code; and thus I have less of it left to think of business
aspects of the problem at the same time. That is, the code
int i = 5;
f(i);
printf("%d\n", i);
in C always prints 5 (except if f is a macro but that would be a malicious code
that can be written in any langage). If it's in C++, you may have to sift
through quite a bit of headers to predict the printout. And the other complaint
is certainly the compilation time. Both drawbacks reduce the performance and
annoy programmers (and everyone knows annoying programmers who program for
living, not from academic interest, is not the smartest thing to do).
>
>
>> Sometimes even in well-defined areas programming with classes is more
>> limiting and creates less usable legacy than programming with
>> subroutines/functions only. A good example are matrix manipulation
>> libraries. If you choose to manipulate with matrices in an old-fashion
>> FORTRAN way (i.e. based on conventions about matrix internal
>> representation and adding functions perusing it which is a mortal sin
>> in OOP), your can reuse the libraries written as far back as in 70th
>> (NAG, IMSL, SSP etc) from your C++ or C program and all these are
>> data-compatible each with other. What I mean by that, you can allocate
>> and initialize internal representations (arrays) in C++, call some
>> subroutines from NAG, call SSP subroutines from SSP on the results,
>> then call your own C function you wrote decades later etc. all
>> without any extra copying or conversions.
>>
>> On the other hand, I have yet to see a pair of C++ matrix manipulation
>> libraries that could re-use one another's matrices without
>> copying/conversions.
> [snip]
>
> My co-worker spent quite some time to write a C++ wrapper for the BLAS
> library so that he can use operator+ and operator*. Such simple things
> make the code much more readable.
Maybe, but it's a mixed blessing, too (I know I overuse this expression :-).
Consider the future (I lived in this particular one) in which your friend's
matrices grow real big and they want to change the multiplication algorithm to
recursive Strassen to be easier on CPU. Now, recursive Strassen is
mathematically equivalent to the vanilla approach but from rounding perspective
s/he may be worried (and especially with big matrices) so suppose s/he designs a
modification that can keep the rounding error below the specified limit (e.g.,
by limiting the recursion depth). If s/he had a mulmat() procedure, s/he would
just add a "double tolerance" parameter to it (maybe with a default value or
function overload to protect old code -- for which C++ (but not OO) is quite
useful, for a change); but what is s/he going to do with operator* in this case?
My evil guess: if s/he he is going to meet this challenge far enough in the code
life, when the * has already been used in tens of generic algorithms, s/he will
add some "tolerance" hack to the matrix wrapper class. And, this is most
certainly not a good OO design: multiplication tolerance does not belong to a
matrix -- it belongs to the algorithm. The imperfection of the hack will lead to
many questions from peers and bugs: Just consider: which matrix, right or left
keeps the "right" tolerance to use.. what if the two are different.. how will
one propagate it to the results? Etc.. Etc..
In ideal world, you would model multiplication algorithm as a class -- but who
would do such a thing from the outset and what business manager would pay for it
from the outset?
I think this is another perfect example of inherent imperfection of modeling:
the root cause of the issue is that multiplying matrices is (in infinitely
complex "real world") quite different from multiplying numbers; but if the
difference was not important for the original requirements (or design, like in
this case), OO will entice designers into a "premature generalization" sin (in
this case -- adding generic algorithms that heavily depend on the overly simple
interface operator* and making it all but impossible to change it in the future).
Why can't we do that under C?
Maybe, for a good reason, like the one above?
>
> Regards,
> Stuart
Sincerely,
Pavel
[toc] | [prev] | [next] | [standalone]
| From | Juha Nieminen <nospam@thanks.invalid> |
|---|---|
| Date | 2011-12-05 13:00 +0000 |
| Message-ID | <4edcc071$0$3065$7b1e8fa0@news.nbl.fi> |
| In reply to | #12059 |
Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> wrote: > OOP works > well when roles and responsibilities of base classes are relatively stable; this > is far from true in many subject areas. Inheritance is not the biggest advantage of OOP (even though it was intended to be when originally designed). It's still extremely useful, of course (for example inheritance-heavy OOP fits GUI implementations so well that one could well think that OOP was invented precisely to solve the problem of how to program GUIs). However, in average inheritance is not the strongest point. The biggest advantage of OOP is modularity. This goes well beyond what you can do with C compilation units and structs. (Compilation units have the big disadvantage that you can't "instantiate" more than one of them at a time. C structs have accessibility and lifetime management problems.) In C++ in particular OOP is a very strong tool because you can achieve a high level of abstraction yet still produce very efficient code (especially in term of memory usage, unlike most other OOP languages). RAII is also an enormous advantage over C (even though strictly speaking it's not an OOP feature). Inheritance is just a "nice to have" extra feature that is sometimes useful. It's not the main selling point.
[toc] | [prev] | [next] | [standalone]
| From | Goran <goran.pusic@gmail.com> |
|---|---|
| Date | 2011-12-05 05:12 -0800 |
| Message-ID | <e6839c8b-4ef6-461c-9087-73d93f7d1054@p9g2000vbb.googlegroups.com> |
| In reply to | #12059 |
On Dec 5, 4:07 am, Pavel <pauldontspamt...@removeyourself.dontspam.yahoo> wrote: > Heck wrote: > > On Sat, 03 Dec 2011 22:07:56 -0500, Heck > > <heckja...@ordertostymieharvestersverizon.net> wrote: > > >> On 3 Dec 2011 00:32:35 GMT, j...@toerring.de (Jens Thoms Toerring) > >> wrote: > > >>> Heck<heckja...@ordertostymieharvestersverizon.net> wrote: > >>>> Can it be ...my design is flawed... > > >>> As Victor has put it short and bluntly you're on the wrong > >>> track. Not only can't that be done but you're violating one > >>> of the most basic principles of OOP, i.e. that inheritance > >>> is all about an "is-a" relationship. If for the derived class > >>> the destructor of the base class can't be called for what- > >>> ever reasons then the derived class isn't an object of the > >>> type that is a specialization of the type of object the base > >>> class is for. Even when you have to check in the base class > >>> what actual kind of oject it's dealing with (as you seem to > >>> consider as a "fix") you're on the wrong path. > > >>> A base class must never, ever have any idea what it's derived > >>> classes do look like whatsoever. If it does it's already too > >>> specialized for being a base class you can derive all the > >>> types you want to from. > > >>> What you seen to be having here is a case like a base class > >>> for vehicles where you started your design with the assump- > >>> tion that all vehicles have an engine that can be switched > >>> on and off. Thus you may have something to switch off thed > >>> engine in the destructor of the "Vehicle" class. And that > >>> works quite nicely for cars, motorcycles, lorries, most > >>> airplanes etc. But then you realize that you also want to > >>> have bicycles and gliders - and suddenly everything seems > >>> to break down. You now ask if there's a way to avoid having > >>> the destructor getting called that switches off the (non- > >>> existent) engine. But the problem is that your base class > >>> is simply too specialized. > > >>> Instead of "repairing" things in the base class by testing > >>> if the vehicle has an engine and make it behave accordingly > >>> (thus forcing the base class to be "aware" of what additional > >>> properties its descendants can have) create a new, more > >>> general class that doesn't know about the existence of an > >>> engine and create two intermediate base classes, both in- > >>> heriting from the original base class, that are for vehicles > >>> with and without an engine. Now make your already existing > >>> derived classes derive from the new intermediate class for > >>> "vehicle with an engine" while deriving bicycles and gliders > >> >from the new internediate class for "vehicle without an > >>> engine". > > >>> The way you describe your problem it looks as if you started > >>> with the assumption that memory-mapped files are all the same, > >>> so having a single base class for them looked reasonable. But > >>> now you've recognized that the property of just being "memory- > >>> mapped" isn't what they all have in common. So revise your base > >>> class to contain only what's common to all of them and create > >>> intermediate classes you can derive from the more specialized > >>> cases where there aren't any issues when all the destructors > >>> are called. > >>> Regards, Jens > > >> Yes, I understand. I agree my conception was flawed. In C, you can > >> start with a flawed design such as this and make it work despite its > >> deficiencies. This illustrates that C++ is both more powerful and > >> more precise in its semantics than C. Thanks for your detailed and > >> helpful reply. > > > I don't mean to say that you can't simply make something flawed work > > in C++, as you can in C. C++ is just as flexible as C. The advantage > > of C++ over C in this regard is that it pragmatically encourages a > > coder to design and write clearly, and to some degree even promotes > > clear thinking. > > Generalizations you said and heard are both right and wrong. OOP is a mixed > blessing. C++ (and OOP) make you "design for future" and no one knows the > future. Changes in the requirements often alter what are "the right things" to > hide and expose; and then the cognitive biases and non-technical issues stand in > a way of re-designing the class structure all over again as it would be > appropriate "in an ideal world". The result is often much messier than in > procedural-oriented language. A case in point is Linux kernel: it is not only > because of its low-level nature is it beneficial that it is written in C rather > than C++: it is also because the kernel is extremely dynamic, the whole > subsystems are being fully re-written between minor versions *and their roles > and responsibilities (separation of duties) are changing at that*. OOP works > well when roles and responsibilities of base classes are relatively stable; this > is far from true in many subject areas. This cannot go unchallenged ;-). What are saying here is that OOP is intrinsically more rigid than some other style, and therefore unsuited for something like an OS kernel, which is somehow more dynamic than something else. You are further making an argument that for such software all should be left out in the open, and that this will be more flexible. Well, yes, but the price of doing that is that it all turns into a thing commonly known as a "big ball of mud". That's it, really. There's another thing: you are mostly talking about information hiding, really. Well, if you fear rigidity, nothing stops you to leave all out in the open and be done with it. Goran.
[toc] | [prev] | [next] | [standalone]
| From | Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> |
|---|---|
| Date | 2011-12-11 17:02 -0500 |
| Message-ID | <4ee52894$0$31505$c3e8da3$9b4ff22a@news.astraweb.com> |
| In reply to | #12073 |
Goran wrote: > On Dec 5, 4:07 am, Pavel > <pauldontspamt...@removeyourself.dontspam.yahoo> wrote: >> Heck wrote: >>> On Sat, 03 Dec 2011 22:07:56 -0500, Heck >>> <heckja...@ordertostymieharvestersverizon.net> wrote: >> >>>> On 3 Dec 2011 00:32:35 GMT, j...@toerring.de (Jens Thoms Toerring) >>>> wrote: >> >>>>> Heck<heckja...@ordertostymieharvestersverizon.net> wrote: >>>>>> Can it be ...my design is flawed... >> >>>>> As Victor has put it short and bluntly you're on the wrong >>>>> track. Not only can't that be done but you're violating one >>>>> of the most basic principles of OOP, i.e. that inheritance >>>>> is all about an "is-a" relationship. If for the derived class >>>>> the destructor of the base class can't be called for what- >>>>> ever reasons then the derived class isn't an object of the >>>>> type that is a specialization of the type of object the base >>>>> class is for. Even when you have to check in the base class >>>>> what actual kind of oject it's dealing with (as you seem to >>>>> consider as a "fix") you're on the wrong path. >> >>>>> A base class must never, ever have any idea what it's derived >>>>> classes do look like whatsoever. If it does it's already too >>>>> specialized for being a base class you can derive all the >>>>> types you want to from. >> >>>>> What you seen to be having here is a case like a base class >>>>> for vehicles where you started your design with the assump- >>>>> tion that all vehicles have an engine that can be switched >>>>> on and off. Thus you may have something to switch off thed >>>>> engine in the destructor of the "Vehicle" class. And that >>>>> works quite nicely for cars, motorcycles, lorries, most >>>>> airplanes etc. But then you realize that you also want to >>>>> have bicycles and gliders - and suddenly everything seems >>>>> to break down. You now ask if there's a way to avoid having >>>>> the destructor getting called that switches off the (non- >>>>> existent) engine. But the problem is that your base class >>>>> is simply too specialized. >> >>>>> Instead of "repairing" things in the base class by testing >>>>> if the vehicle has an engine and make it behave accordingly >>>>> (thus forcing the base class to be "aware" of what additional >>>>> properties its descendants can have) create a new, more >>>>> general class that doesn't know about the existence of an >>>>> engine and create two intermediate base classes, both in- >>>>> heriting from the original base class, that are for vehicles >>>>> with and without an engine. Now make your already existing >>>>> derived classes derive from the new intermediate class for >>>>> "vehicle with an engine" while deriving bicycles and gliders >>>> >from the new internediate class for "vehicle without an >>>>> engine". >> >>>>> The way you describe your problem it looks as if you started >>>>> with the assumption that memory-mapped files are all the same, >>>>> so having a single base class for them looked reasonable. But >>>>> now you've recognized that the property of just being "memory- >>>>> mapped" isn't what they all have in common. So revise your base >>>>> class to contain only what's common to all of them and create >>>>> intermediate classes you can derive from the more specialized >>>>> cases where there aren't any issues when all the destructors >>>>> are called. >>>>> Regards, Jens >> >>>> Yes, I understand. I agree my conception was flawed. In C, you can >>>> start with a flawed design such as this and make it work despite its >>>> deficiencies. This illustrates that C++ is both more powerful and >>>> more precise in its semantics than C. Thanks for your detailed and >>>> helpful reply. >> >>> I don't mean to say that you can't simply make something flawed work >>> in C++, as you can in C. C++ is just as flexible as C. The advantage >>> of C++ over C in this regard is that it pragmatically encourages a >>> coder to design and write clearly, and to some degree even promotes >>> clear thinking. >> >> Generalizations you said and heard are both right and wrong. OOP is a mixed >> blessing. C++ (and OOP) make you "design for future" and no one knows the >> future. Changes in the requirements often alter what are "the right things" to >> hide and expose; and then the cognitive biases and non-technical issues stand in >> a way of re-designing the class structure all over again as it would be >> appropriate "in an ideal world". The result is often much messier than in >> procedural-oriented language. A case in point is Linux kernel: it is not only >> because of its low-level nature is it beneficial that it is written in C rather >> than C++: it is also because the kernel is extremely dynamic, the whole >> subsystems are being fully re-written between minor versions *and their roles >> and responsibilities (separation of duties) are changing at that*. OOP works >> well when roles and responsibilities of base classes are relatively stable; this >> is far from true in many subject areas. > > This cannot go unchallenged ;-). > > What are saying here is that OOP is intrinsically more rigid than some > other style, and therefore unsuited for something like an OS kernel, > which is somehow more dynamic than something else. Absolutely not. As you should have noticed I am avoiding generic statements almost as a matter of principle (because generalizations is what allow people to smuggle wrong notions under the cover of generally correct ideas). I gave a very specific example: Linux Kernel. EPOC32 (now known as Symbian) kernel and API was all natively-C++ (more accurately, a rather limited subset thereof but with all traditional OO-features included). It has been a wonderful little RTOS that pioneered lots of usable features of pen-based user interfaces (currently evolved to touch-screens). The proof of its rigidity is simple: Linux is well and kicking and the last holdout of Symbian consortium, Nokia (they are the greatest mobile-phone producer hardware-wise, IMHO), is suffering major losses and switching to (C-based AFAIK) Windows 8 only because they could not upkeep now-theirs Symbian with all needed changes to stay competitive among mobile users. And don't get me wrong: I believe Nokia guys are great in writing high-quality software, too; it's just that C++-based Symbian was not greatly helpful in achieving their goals. As a former developer of apps for EPOC32 I can assure you that, from both functionality and implementation quality, that RTOS beat xxx out of any other RTOS alternative I evaluated at the time -- and I was younger and was seeking perfection with more zeal than I do now. And, it did not have C++ stack usage issue that someone (not you) mentioned at this thread (at the cost of one of their C++ limitations I mentioned above -- quite annoying, but unrelated to the OO features). But.. programming for its C++ API was no fun at all. We had to spend lots of energy to make Psion add a semi-usable clone of simple POSIX-like API.. and they could never make it fully usable (not on my tenure, anyway) despite that their native C++ system API was implemented with high quality and hardly had any bugs (I do not remember finding any but maybe I was just lucky). Which, BTW proves that seemingly simple and naive constructions of classic UNIX APIs are much better thought of than it's often believed and require quite non-trivial thinking to implement them correctly -- whereas using them is a piece of cake. I do not want to get into a discussion of whether UNIX API is OO by its nature (it very well may be and this does not contradict my position on OO because it's been very stable, too -- and it's still relevant because it was designed from the start by very smart people with great diligence; and the changes were carefully designed, too) but it's worth noting that its native programming language, for both API and implementation, is C -- which many people here obviously regard as not OO enough. > You are further > making an argument that for such software all should be left out in > the open, and that this will be more flexible. Excuse me? You generalized my idea to the point I can't recognize it so I leave it up to you to draw a connection between what I said and what you made out of it -- after which I will be happy to point out where the confusion is coming from. Well, yes, but the > price of doing that is that it all turns into a thing commonly known > as a "big ball of mud". That's it, really. The biggest balls of mud I have seen so far (and I saw quite a lot) were written in C++. I am not trying to theorize on why it is, just sharing the experience. > There's another thing: you are mostly talking about information > hiding, really. Wrong. If anything, I was talking OO modeling. If you insist on generalities, I was talking about how the real world is not just necessary different from our models but how *unexpectedly different* it turns out when a new requirement (that itself is more often than not, unexpected) comes and what troubles you have when you incorporate another aspect of the infinitely complex world to your model. I was also talking that these "accidents" are actually common and inevitable because no one, even the best designer in the world, can know for sure what aspect of this infinitely complex world s/he will be required to add to their design next. To narrow this a little bit, I specifically mentioned the design of class hierarchies (it has little to do to hiding, isn't it?). Most of the time (and always, when designing OO frameworks) a base class is designed for new classes to be derived from it. To avoid acquisitions in tautology: I mean the new classes that have to be designed AFTER the library is released. For frameworks it's always true that some classes have to be derived and for other class libraries it's very often true for their new versions. It happens, but relatively rarely, that a hierarchy is "naturally closed". When a new requirement arrives, it's often that "if you knew it from the beginning" you would design base classes differently (meaning, you would like to re-distribute their responsibilities and behaviors; you may also wish you had a different set of base classes altogether). But re-designing base classes from scratch is usually not an option for non-technical reasons, valid and/or subjective. What it results with is that "the best in class" OO designer either: a) "swallows it" and adds more stuff into their best classes -- this time with little regard to the "right thing to do" (which would be, let me repeat myself, to re-design the class structure from scratch). b) departs from the company leaving it to others to clean the mess (and those others would usually do same, but in even worse and less consistent manner than the original OO designer would do unless they are wise and bold enough and have enough clout to lead the business management to paying for the complete rewrite) A technical consequence of the OO-model-patching described above is that the derived classes (usually "the old" ones, introduced in former releases) acquire state, code and dependencies that they ideally wouldn't need and start performing less-than-optimally, the further the more so. I am not daring to even call in this good community what those base classes become from OO point of view.. The above is, by the way, how what you called "a big ball of mud" is usually constructed. A procedural programmer in such situation will be expected just to write new procedures and design new data structures -- which s/he would do after some deliberation. When old procedures/structures are no longer used (to be completely honest, this does not happen at once or very often, but after some 10-20 years and with only few of them), this can be detected automatically and they can be retired without a big pomp -- if the firm has more or less decent software lifetime governance. > Well, if you fear rigidity, nothing stops you to leave > all out in the open and be done with it. I am not sure I follow these references to "all out in the open". The source code shall be accessible to its maintainers, shan't it? -- otherwise, they would not be able to even fix simplest bugs, let alone implementing a meaningful new requirement. As for, say, library users, I am not implying they have to have access to the source code. Giving access to full definitions of data structures is sometimes useful at low- and not-so-low levels; where it's not useful, it should be avoided -- but I would not get out of my way at it. The thing is, where you need a change it is often "the right way" to create a completely new data structure rather than to force the old one into serving for the new purpose. I thought I gave a good example of it discussing how FORTRAN matrices have had their data structure "in the open" and stayed easily re-usable and extendable over decades (and how C++ matrices with everything encapsulated have not been a match in this regard). > > Goran. -Pavel
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c++
csiph-web