Thread: Re: [GD-General] Eiffel (Page 3)
Brought to you by:
vexxed72
From: Jesse J. <jes...@mi...> - 2001-12-23 22:40:46
|
At 9:09 AM -0800 12/22/01, Brian Hook wrote: >At 10:08 AM 12/21/2001 -0500, Thatcher Ulrich wrote: >>but IMHO the STL stinks as far as usability goes. > >THANK you for saying that. I'm so tired of people going on and on >about how great STL is (it's probably the #1 validation of C++ and >templates I've seen), Templates are flawed but great. There might be better options in other languages, but for C++ there's just a ton of useful stuff you can do with them. In my code I make heavy use of smart pointers (exception safety, memory management, COM-style interface ptr wrappers, and preferences), the boost callback classes, type-safe logging functions, and STL. Note that this is all stuff that is very useful to ordinary programmers. >when in fact IT'S NOT THAT GOOD. It's convoluted, difficult to >debug, has bizarre syntax, takes forever to compile, generates tons >of warnings, requires third party implementations for stability. >The only reason people dig on it is that they didn't have to write >it. > >Someone should sift through the STL source code some time then come >back and tell me it's GOOD. The design is more important than the implementation and IMO the design is quite good. I've yet to see a really good implementation, but CodeWarrior's at least doesn't suck. -- Jesse |
From: Kent Q. <ken...@co...> - 2001-12-24 16:15:51
|
I *really* have to disagree here. The DESIGN of the STL is absolutely gorgeous. I have never seen another container library that has such a neat separation of containers, iterators, algorithms, and data. The more I use the STL the more I love its design. Yes, there are warts on the usage of the STL that mostly come from limitations in C++. Plauger's implementation (for Microsoft) is appalling in its use of (nearly) obfuscated variable names, etc. But I have found that idiomatic use of the STL drastically reduces both the amount of code I have to write and the number of errors I make in that code. One of my frustrations with Java is the lack of ability to write anything like the STL in it. It's a frustration because I otherwise like it a great deal. STLPort fixes a lot of the problems with MS's version, btw, though it's still not perfect. Kent Brian Hook wrote: > > At 10:08 AM 12/21/2001 -0500, Thatcher Ulrich wrote: > >but IMHO the STL stinks as far as usability goes. > > THANK you for saying that. I'm so tired of people going on and on about > how great STL is (it's probably the #1 validation of C++ and templates I've > seen), when in fact IT'S NOT THAT GOOD. It's convoluted, difficult to > debug, has bizarre syntax, takes forever to compile, generates tons of > warnings, requires third party implementations for stability. The only > reason people dig on it is that they didn't have to write it. > > Someone should sift through the STL source code some time then come back > and tell me it's GOOD. > > The primary advantage is that if you need a List or a Map you can just use > STL without having to reroll it, but since I have that stuff lying around > anyway, it doesn't bother me. -- ----------------------------------------------------------------------- Kent Quirk | MindRover: "Astonishingly creative." Game Architect | Check it out! ken...@co... | http://www.mindrover.com/ _____________________________|_________________________________________ |
From: Brian H. <bri...@py...> - 2001-12-21 15:36:54
|
At 01:56 AM 12/21/2001 -0500, Kent Quirk wrote: >definitely use a fourth revision. (It appears he wrote a book in 1999 by >starting from the paper, so you probably have to buy the book to get an >update.) I have the book. It's good, and very length expansion on his previous critique. He does seem to try to be objective, but there is a bit of a C++ negative sentiment and a positive Eiffel bias; not so much in absolutes, but where he's willing to cut slack, e.g.: "While C++ does possess feature XYZ, it's a royal pain in the ass to get to" vs. "While Eiffel lacks feature XYZ, it is trivial to work around by blah blah blah" I'm also beginning to see some areas of Eiffel that I'm not sure I'm comfortable about (other than the different implementations that aren't entire compatible). For example, Eiffel supports and almost pushes MI because they have a model of what inheritance means, even Ian does talk at length about the differences between interface and implementation inheritance (which is almost never discussed in introductory C++ texts but which is absolutely vital to not screwing up a framework design). In Eiffel, it feels like inheritance is pushed for mix-in style programming where you're pulling in multiple implementations instead of multiple interfaces. I personally prefer using inheritance for interface/implementation separation, not as an extension for code reuse (I use aggregation for the latter). I think Obj-C and SmallTalk's emphasis on simplicity gives them an advantage. For example, inheritance is discouraged as a form of extension by a client. Areas where you would normally use inheritance they tend to push either aggregation or, more likely, delegation. Have I mentioned that Cocoa is just a joy to work with? >No overloading. I dislike overloading. I think this is a preference thing, but I would much rather see: SetPositionWithVector( ... ); SetPositionWithXYZ( ... ); SetPositionWithTransform( ... ); Than just three different versions of SetPosition(). This is for both pragmatic (I want to search for all instances where I set position with a vector; I want the environment to choose the right function to start hinting to me about the parameter types) and stylistic reasons. But I've heard the counter-argument of "I don't want to remember all those variants" and it seems valid to me. I've just seen it abused, a lot, and it ends up making potentially difficult to read or maintain code (not to mention when things go to hell with inheritance and default arguments). >Again, it comes down to favoring readability over writeability >and eliminating ambiguity. Yep. >No nested classes. I'm with them on this one too, although this is primarily because I dislike the entire linkage and file system model that C/C++ impose. Nested classes are nominally private to the enclosing class, yet for some reason when you change the nested class you force a recompile of, well, everything that includes the specification of the enclosing class. Blah. >C: "You can do whatever you want." Personally I think all the languages let you do whatever you want, so long as in the end they let you call out to C for the gritty low level stuff. These days doing what I want isn't an issue, is how I go about doing it. C++ feels like a really bad practical joke. Take STL. Please. The only reason I can fathom that people love it so much is that it's there (and even then, you have to go get a "real" implementation to avoid the scorn of those that laugh when you say you're using Microsoft's implementation). Hey, I don't have to write a map class, it's just there! STL isn't particularly well designed, it's a bitch to compile, and a bitch to debug. Having stepped into STL code on accident, that's just not a neighborhood I want to visit again. STL just seems like "Oh, someone wrote some code that's more reusable than the stuff I've hacked together over time...cool!" I personally just try to make my code reusable. Go figure. Brian |
From: Jesse J. <jes...@mi...> - 2001-12-23 00:29:59
|
At 7:35 AM -0800 12/21/01, Brian Hook wrote: >In Eiffel, it feels like inheritance is pushed for mix-in style >programming where you're pulling in multiple implementations instead >of multiple interfaces. I personally prefer using inheritance for >interface/implementation separation, not as an extension for code >reuse (I use aggregation for the latter). Unfortunately MI has a bad reputation in C++. Even people who should know better like Scot Myers rag on it. But essentially all of the problems with MI in C++ are because of virtual base classes. So how do you avoid virtual base classes? By avoiding diamond shaped inheritance hierarchies. One way to do this is by using mixin classes. You have your main-line classes like Widget or Monster or whatever and then you have mixin classes like ReferenceCountedMixin or ObserverMixin or whatever. Mixins only descend from other mixins so you never wind up with the diamond of death. This turns out to be a very nice way to design frameworks and, unlike Java, you *can* reuse implementation. >I think Obj-C and SmallTalk's emphasis on simplicity gives them an >advantage. For example, inheritance is discouraged as a form of >extension by a client. Areas where you would normally use >inheritance they tend to push either aggregation or, more likely, >delegation. Or they just rely on name commonality. So, you can have a container of Foo's and Bar's and still call name() or process() or whatever and it will just work, even if there's no common base class. >Take STL. Please. The only reason I can fathom that people love it >so much is that it's there (and even then, you have to go get a >"real" implementation to avoid the scorn of those that laugh when >you say you're using Microsoft's implementation). Hey, I don't have >to write a map class, it's just there! STL isn't particularly well >designed, I disagree. The division between containers, iterators, and algorithms is great. The attention to performance and the performance guarantees are great. The ease of use coupled with flexibility and extensibility is great. Type checking is great (might as well leverage one of the things that C++ does well). The fact that it's a compile time library is at least cool because it lets the library adapt itself at compile time to the types you're using (eg int's can be memcpy'ed). >it's a bitch to compile, and a bitch to debug. I'll give you this one. :-) >Having stepped into STL code on accident, that's just not a >neighborhood I want to visit again. I bet you'd say the same thing about an awful lot of libraries that you use though. Unfortunately most of those libraries are compiled so that you can't see how poorly they're written. The problem with STL is that templates add quite a bit of visual clutter, the better implementations have a lot of different cases for things like POD and non-POD types, and the most popular implementation looks like (but isn't) shrouded. -- Jesse |
From: Thatcher U. <tu...@tu...> - 2001-12-27 21:53:42
|
On Dec 22, 2001 at 04:30 -0800, Jesse Jones wrote: > > Unfortunately MI has a bad reputation in C++. Even people who should > know better like Scot Myers rag on it. But essentially all of the > problems with MI in C++ are because of virtual base classes. So how > do you avoid virtual base classes? By avoiding diamond shaped > inheritance hierarchies. > > One way to do this is by using mixin classes. You have your main-line > classes like Widget or Monster or whatever and then you have mixin > classes like ReferenceCountedMixin or ObserverMixin or whatever. > Mixins only descend from other mixins so you never wind up with the > diamond of death. I've been pondering this. I've always depended on virtual inheritance for effective mixins. For example, how do you implement smart pointers to mixins of ref-counted classes, without virtual inheritance? It would be great if I'm wrong, since virtual inheritance is a PITA in some ways (in other ways, I think it's the only usable form of C++ MI, but lets leave that aside for now). -- Thatcher Ulrich <tu...@tu...> http://tulrich.com |
From: Jesse J. <jes...@mi...> - 2001-12-27 23:46:04
|
At 4:56 PM -0500 12/27/01, Thatcher Ulrich wrote: >On Dec 22, 2001 at 04:30 -0800, Jesse Jones wrote: >> >> Unfortunately MI has a bad reputation in C++. Even people who should >> know better like Scot Myers rag on it. But essentially all of the >> problems with MI in C++ are because of virtual base classes. So how >> do you avoid virtual base classes? By avoiding diamond shaped >> inheritance hierarchies. >> >> One way to do this is by using mixin classes. You have your main-line >> classes like Widget or Monster or whatever and then you have mixin >> classes like ReferenceCountedMixin or ObserverMixin or whatever. >> Mixins only descend from other mixins so you never wind up with the >> diamond of death. > >I've been pondering this. I've always depended on virtual inheritance >for effective mixins. For example, how do you implement smart >pointers to mixins of ref-counted classes, without virtual >inheritance? I assume you're talking about a smart pointer class that requires invasive changes to the object it's pointing at. For example, a smart pointer class that maintains ref counts and requires that the object have a common reference counted implementation. In general I think it's better to try to come up with a non-invasive design. However I have dealt with problems like this. For example, I used to have an Invariant class that allowed for DbC-style invariant checks. The class had a virtual Invariant method and a counter that was incremented when entering a public method and decremented when exiting a public method. But mixins still wanted to call the invariant so what I did was dynamic_cast the mixin this pointer to an Invariant* and call the Invariant method if the result wasn't NULL. However I've fairly recently dropped the Invariant class. -- Jesse |
From: Thatcher U. <tu...@tu...> - 2002-01-03 04:47:17
|
On Dec 27, 2001 at 03:46 -0800, Jesse Jones wrote: > At 4:56 PM -0500 12/27/01, Thatcher Ulrich wrote: > >On Dec 22, 2001 at 04:30 -0800, Jesse Jones wrote: > >> > >> Unfortunately MI has a bad reputation in C++. Even people who should > >> know better like Scot Myers rag on it. But essentially all of the > >> problems with MI in C++ are because of virtual base classes. So how > >> do you avoid virtual base classes? By avoiding diamond shaped > >> inheritance hierarchies. > >> > >> One way to do this is by using mixin classes. You have your main-line > >> classes like Widget or Monster or whatever and then you have mixin > >> classes like ReferenceCountedMixin or ObserverMixin or whatever. > >> Mixins only descend from other mixins so you never wind up with the > >> diamond of death. > > > >I've been pondering this. I've always depended on virtual inheritance > >for effective mixins. For example, how do you implement smart > >pointers to mixins of ref-counted classes, without virtual > >inheritance? > > I assume you're talking about a smart pointer class that requires > invasive changes to the object it's pointing at. For example, a smart > pointer class that maintains ref counts and requires that the object > have a common reference counted implementation. Yup, that's what I meant. > In general I think it's better to try to come up with a non-invasive > design. I'm curious to know more; can you explain, or point me at a reference? > However I have dealt with problems like this. For example, I used to > have an Invariant class that allowed for DbC-style invariant checks. > The class had a virtual Invariant method and a counter that was > incremented when entering a public method and decremented when > exiting a public method. But mixins still wanted to call the > invariant so what I did was dynamic_cast the mixin this pointer to an > Invariant* and call the Invariant method if the result wasn't NULL. I've been pondering this. I think dynamic_cast has a couple of problems for this usage. For one thing, it's slower than a virtual base class lookup. More importantly, dynamic_cast<C*>(p) returns null if *p has more than one C in its inheritance hierarchy! This is explained in TC++PL, however the text mistakenly says that this problem only occurs with virtual inheritance. For example: B B | | C D A \|/ E E inherits from B twice. dynamic_cast<B*>((A*) ptr to E) returns 0! I coded this up, and both GCC and MSVC agree. I checked with Stroustrup (the person, not the book), and he agrees too; he's going to correct the text in TC++PL. On the other hand, if you *always* use virtual inheritance, the ambiguity *never* occurs; the above graph looks like: B |\ C D A \|/ E And presuming that B is your base class with the reference count, the compiler will force you to derive A from B as well, if you try to make a smart pointer to A. I realize that you're advocating a hierarchy that looks like this: B | C D A \|/ E But I don't think there's a good way to enforce that. -- Thatcher Ulrich <tu...@tu...> http://tulrich.com |
From: Jesse J. <jes...@mi...> - 2002-01-03 07:28:40
|
At 11:49 PM -0500 1/2/02, Thatcher Ulrich wrote: >On Dec 27, 2001 at 03:46 -0800, Jesse Jones wrote: >> At 4:56 PM -0500 12/27/01, Thatcher Ulrich wrote: > > >On Dec 22, 2001 at 04:30 -0800, Jesse Jones wrote: > > I assume you're talking about a smart pointer class that requires >> invasive changes to the object it's pointing at. For example, a smart >> pointer class that maintains ref counts and requires that the object >> have a common reference counted implementation. > >Yup, that's what I meant. > >> In general I think it's better to try to come up with a non-invasive >> design. > >I'm curious to know more; can you explain, or point me at a reference? For the case above you can put the ref count inside the smart pointer class. The only tricky bit is that the smart pointer objects have to share the count, but you can handle this by making the first smart pointer object instantiated allocate the count on the heap. When a smart pointer is copied it copies the ref count ptr and adjusts the ref counts. This is a bit slower because of the one extra allocation, but it's awfully nice to be able to easily pass around ref-counted pointers for arbitrary types. > > However I have dealt with problems like this. For example, I used to >> have an Invariant class that allowed for DbC-style invariant checks. >> The class had a virtual Invariant method and a counter that was >> incremented when entering a public method and decremented when >> exiting a public method. But mixins still wanted to call the >> invariant so what I did was dynamic_cast the mixin this pointer to an >> Invariant* and call the Invariant method if the result wasn't NULL. > >I've been pondering this. I think dynamic_cast has a couple of >problems for this usage. For one thing, it's slower than a virtual >base class lookup. Big deal. As long as you're aware of the overhead and don't do anything silly it should be fine. >I realize that you're advocating a hierarchy that looks like this: > >B >| >C D A > \|/ > E > >But I don't think there's a good way to enforce that. Nope, and even if you're careful and rigorously distinguish between main-line and mixin classes it's still possible to accidentally mix in the same class twice into an inheritance hierarchy. However in practice I haven't found this too be much of a problem and this approach neatly sidesteps all of the subtleties and ugliness associated with virtual inheritance. -- Jesse |
From: Thatcher U. <tu...@tu...> - 2002-01-03 16:38:11
|
On Jan 02, 2002 at 11:28 -0800, Jesse Jones wrote: > >I realize that you're advocating a hierarchy that looks like this: > > > >B > >| > >C D A > > \|/ > > E > > > >But I don't think there's a good way to enforce that. > > Nope, and even if you're careful and rigorously distinguish between > main-line and mixin classes it's still possible to accidentally mix > in the same class twice into an inheritance hierarchy. However in > practice I haven't found this too be much of a problem and this > approach neatly sidesteps all of the subtleties and ugliness > associated with virtual inheritance. My point is, *always* using virtual inheritance is the only way to make MI truly safe. Then the subtleties and ugliness are all in the compiler (where they belong). You (and Meyers for that matter) have this backwards -- the "diamond of death" is actually what you want in all the class hierarchies I've come across. If you find yourself wanting non-virtual inheritance, it means you're trying to model a kind of "is-implemented-in-terms-of", which should not be done with inheritance at all. Non-virtual multiple inheritance is a bug in C++. IMHO, of course :) -- Thatcher Ulrich <tu...@tu...> http://tulrich.com |
From: Chris B. <Chr...@ma...> - 2001-12-13 06:21:55
|
I'm currently coding up a zip loader myself. I've been reading over the pkware docs, however I'm finding their descriptions to be difficult to nut out in some cases. I turned to some sample implementations on the net and now it's even more confused. The first thing I read was to walk the whole file, reading the local file descriptors as you go : http://epicboy.flipcode.com/tutorials_ZIP.htm eeek, I can't imagine this scaling to a large resource file! Then after reading the pkware docs, and using a little wisdom it seems more likely that the Central Directory is what I should be using. My intention is the build an STL map that maps file names to data offsets. To do this I need to find the beginning of the central directory, something which seems a little difficult. The only way I've found to do this so far is to jump back about 65k(assuming the file is that big) and then start reading forward comparing each byte to the header 0x02014b50. This might be a bit faster if I knew the tag was 4 byte aligned, but it still seems a little silly to find the main table by a random scan like this. Is there a better way? Many thanks Chris No picking on the disclaimer, it's added at the server. :) -----Original Message----- From: Gareth Lewin [mailto:GL...@cl...] Sent: Friday, 7 December 2001 7:49 AM To: gam...@li... Subject: RE: [GD-General] Building pak/zip files Hmm, you might want to look at the zip file definition again (http://www.pkware.com/support/appnote.html). If you seek to the end of the file, make sure you don't have comments or Zip64 code ( Both a logical requirement for a game based zip file ) then the last 16 bytes will be: <quote> number of this disk: (2 bytes) The number of this disk, which contains central directory end record. If an archive is in zip64 format and the value in this field is 0xFFFF, the size will be in the corresponding 4 byte zip64 end of central directory field. number of the disk with the start of the central directory: (2 bytes) The number of the disk on which the central directory starts. If an archive is in zip64 format and the value in this field is 0xFFFF, the size will be in the corresponding 4 byte zip64 end of central directory field. total number of entries in the central dir on this disk: (2 bytes) The number of central directory entries on this disk. If an archive is in zip64 format and the value in this field is 0xFFFF, the size will be in the corresponding 8 byte zip64 end of central directory field. total number of entries in the central dir: (2 bytes) The total number of files in the .ZIP file. If an archive is in zip64 format and the value in this field is 0xFFFF, the size will be in the corresponding 8 byte zip64 end of central directory field. size of the central directory: (4 bytes) The size (in bytes) of the entire central directory. If an archive is in zip64 format and the value in this field is 0xFFFFFFFF, the size will be in the corresponding 8 byte zip64 end of central directory field. offset of start of central directory with respect to the starting disk number: (4 bytes) Offset of the start of the central directory on the disk on which the central directory starts. If an archive is in zip64 format and the value in this field is 0xFFFFFFFF, the size will be in the corresponding 8 byte zip64 end of central directory field. </quote> Also you should be able to assume that you don't use multidisk spanning. _____________________ Regards, Gareth Lewin Lead Programmer Climax Development Fareham Heights Standard Way Fareham P016 8XT > -----Original Message----- > From: Brian Sharon [mailto:bs...@mi...] > Sent: 06 December 2001 18:47 > To: Thatcher Ulrich; Tom Spilman > Cc: gam...@li... > Subject: RE: [GD-General] Building pak/zip files > > > Things like WinZip will (by default) try to compress > everything, so you > would want to set command line flags to disable compression for > uncompressible things like sound files. > > And I can't imagine a zip implementation that wouldn't add > files to the > end of the zip in the order that you insert them, because the > alternative (shifting files down) would be so inefficient. > > But the worst part of zip files is that the catalog lives at an > unspecified distance from the end of the file, so opening an archive > means seeking to somewhere near the end and walking around looking for > the catalog. If you're really worried about speed, you > probably want to > have a post-process step where you generate another copy of > that catalog > in a spot where it can be loaded quickly...like placed on the > DVD, right > in front of the zip archive. > > --brian > > -----Original Message----- > From: Thatcher Ulrich [mailto:tu...@tu...] > Sent: Thursday, December 06, 2001 6:21 AM > To: Tom Spilman > Cc: gam...@li... > Subject: Re: [GD-General] Building pak/zip files > > On Dec 05, 2001 at 05:41 -0600, Tom Spilman wrote: > > > Zip file tools don't generally give you control over what > > > gets compressed and what doesn't(I think). > > > > Actually i don't think this is necessarily true > > It doesn't actually matter -- zip tools generally will choose the best > method of compression for each file, so .jpg's or .mpg's will be > stored uncompressed. > > > nor that you cannot > > specify the order of the contents of the zip file. Check out > > http://www.winzip.com/wzcline.htm which adds command line support to > WinZip. > > Infozip's command-line zip apparently stores things in the order you > specify. Also, it's open source under a X-style license, so you can > hack stuff in or incorporate the code in your project. There's also > zlib from the same project, designed for embedding. We use zlib at > Oddworld for unpacking resource files. > > http://www.info-zip.org/ > http://www.gzip.org/zlib/ > > -- > Thatcher Ulrich <tu...@tu...> > http://tulrich.com > > _______________________________________________ > Gamedevlists-general mailing list > Gam...@li... > https://lists.sourceforge.net/lists/listinfo/gamedevlists-general > > _______________________________________________ > Gamedevlists-general mailing list > Gam...@li... > https://lists.sourceforge.net/lists/listinfo/gamedevlists-general > NOTICE This e-mail and any attachments are confidential and may contain copyright material of Macquarie Bank or third parties. If you are not the intended recipient of this email you should not read, print, re-transmit, store or act in reliance on this e-mail or any attachments, and should destroy all copies of them. Macquarie Bank does not guarantee the integrity of any emails or any attached files. The views or opinions expressed are the author's own and may not reflect the views or opinions of Macquarie Bank. |
From: Brian H. <bri...@py...> - 2001-12-13 06:58:41
|
At 05:20 PM 12/13/2001 +1100, Chris Brodie wrote: >I'm currently coding up a zip loader myself. Dumb question -- why aren't you using zlib? Brian |
From: Chris B. <Chr...@ma...> - 2001-12-13 07:12:39
|
I thought zlib just did the decompression \ compression and your responsible for the data source, in this case zip files. I think I need to locate a memory block (pointer+size) to hand over to zlib. I was actually planning on using zlib, one I can locate the memory block that the file is in. Is this assumption wrong? > Dumb question -- why aren't you using zlib? > > Brian NOTICE This e-mail and any attachments are confidential and may contain copyright material of Macquarie Bank or third parties. If you are not the intended recipient of this email you should not read, print, re-transmit, store or act in reliance on this e-mail or any attachments, and should destroy all copies of them. Macquarie Bank does not guarantee the integrity of any emails or any attached files. The views or opinions expressed are the author's own and may not reflect the views or opinions of Macquarie Bank. |
From: Brian H. <bri...@py...> - 2001-12-13 16:35:35
|
At 06:11 PM 12/13/2001 +1100, Chris Brodie wrote: >I thought zlib just did the decompression \ compression and your >responsible for the data source, in this case zip files. Yes, but you're only responsible for the WHOLE ZIP file, you don't have to do any seeking at all. Just download ZLIB and look at the sample unzip utilities. Brian |